Don't use static Agent API on APM middleware registration
See original GitHub issueUseElasticApm
function relies on static Agent.Setup(config)
, which throws if registering the middleware was already done. But this is not considering the scenario where more than one IHost
or IWebHost
instances can be running on the same process.
I think the common practice is registering a new IApmAgent
instance as singleton to IServiceCollection
and injecting it into the middleware. AutoMapper had the same issue previously and they fixed it following this approach and they just removed the static API for good in version 9.
That said, having IApmAgent
registered in DI allows injecting into controllers/services instead of relying on statics as documentation recommends.
Furthermore, current configuration approach only allows configuring the Agent form IConfiguration
and would be flexible to have an Options Builder approach like EF Core has.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:17
- Comments:10 (2 by maintainers)
We released the
Elastic.Apm.Extensions.Hosting
package which I believe will make this better - it’s currently beta, in the next release we can remove the beta flag. That package has an extension method forIHostBuilder
and you don’t need to register a middleware anymore, it basically creates the agent and adds its components toIServiceCollection
.It’s also part of the
NetCoreAll
package that most of the people use.Just do this in when you create your hostbuilder
Once you do that, you’ll be able to dependency inject a tracer - for example:
Sometimes I see people wanting the whole agent instance - I don’t understand why people want that (happy to hear what you want to do with it), nevertheless, you can also inject an
IApmAgent
instance into your class. I believe most people want to manually create spans and transactions and for that I’d suggest injecting anITracer
- the tracer is the one that let’s you create those.Now, in the latest beta release of this package I believe we don’t have ASP.NET Core monitoring (which is a huge missing thing), but that’s already on master, so in the next release that’ll be there and you can try it already on master.
Also, I’d like to point out that there is an
Agent.IsConfigured
property which lets you avoid the double initialization problem.On the “static Agent API” part: I understand everyone’s concerns, I hope the approach above satisfies peoples needs - about the reasons why we can’t drop it I wrote here and maybe this here is also related.
Let me know if this would help with everyone’s problem here. Also maybe give a try to this new package.
@gregkalapos I just transitioned my current project to it, this resolves any double initialization problems (race conditions… one in 4 startups is lucky) I’ve had with multiple
IHostedService
s next to the ASP.NET Core stack but then no HTTP traces are created.After playing around, this is the only working single configuration I could come up with that works under all cirumcstances:
Am I missing some configuration option that provides a single configuration and allows for ASP.NET Core + IHostedService usage without startup race issues? (plus I really don’t want to miss some transactions that happen at the app start in these
IHostedService
s)Since this needs reflection to access internal types, I’d be happy for a version that works with public API only.