Reputation: 63
I'm trying to implement a custom ITelemetryInitializer
(UserTelemetryInitialiser
) that attaches some user metadata to app insights messages, and I'm getting the following circular dependency.
UserTelemetryInitialiser
goes to a users cache that depends on IMemoryCache
as implemented by Microsoft.Extensions.Caching.Memory.MemoryCache
. MemoryCache
is then dependent on ILoggerFactory
(implemented by Microsoft.Extensions.Logging.LoggerFactory
) and LoggerFactory
eventually depends on TelemetryConfiguration
.
So I have this (shortened) circular chain: TelemetryConfiguration
-> UserTelemetryInitialiser
-> MyUserCache
-> MemoryCache
-> LoggerFactory
-> TelemetryConfiguration
.
Any ideas on how to resolve this?
I'm using ASP.NET Core 5.0 with Microsoft.ApplicationInsights.AspNetCore 2.18.0.
EDIT:
My simplified initializer looks like this (where IHttpContextAccessor
is used to get the user identity):
public class UserTelemetryInitialiser : ITelemetryInitializer
{
private readonly IHttpContextAccessor contextAccessor;
private readonly IMemoryCache cache;
public UserTelemetryInitialiser(IHttpContextAccessor contextAccessor, IMemoryCache cache)
{
this.contextAccessor = contextAccessor;
this.cache = cache;
}
public void Initialize(ITelemetry telemetry)
{
}
}
Upvotes: 0
Views: 862
Reputation: 141
The problem with Injecting IMemoryCache
into a ITelemetryInitializer
when using dependency-injection, is, that calling services.AddApplicationInsightsTelemetry()
registers a ApplicationInsightsLoggerProvider
for the LoggerFactory
.
Since the default implementation of IMemoryCache
(MemoryCache
) has a dependency on a ILogger
, and this requires a
LoggerFactory
which now in turn depends on ApplicationInsightsLoggerProvider
which constructs a TelemetryClient
and thus depends on all configured ITelemetryInitializers
... we now have a circular dependency.
if you are okay with not logging messages from MemoryCache
within your TelemetryInitializer, you could configure your TelemetryInitializer simply by providing a Setup-method where you construct a MemoryCache
without a Logger (which defaults to using a NullLogger.Instance
):
services.AddSingleton<ITelemetryInitializer>(serviceProvider
=> new MyTelemetryInitializer(new MemoryCache(optionsAccessor: serviceProvider.GetRequiredService<IOptions<MemoryCacheOptions>>())));
for the off-chance, that logging in MemoryCache is more important to you, than having warnings
tracked by application insights, you could remove the ApplicationInsightsLoggerProvider
from your LoggerFactory:
services.AddApplicationInsightsTelemetry();
services.AddSingleton<ITelemetryInitializer, MyTelemetryInitializer>();
//must be called *after* AddApplicationInsightsTelemetry()
services.AddLogging(loggingBuilder =>
{
foreach(var aiLoggingProvider in loggingBuilder.Services.Where(p => p.ImplementationType == typeof(Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider)).ToArray())
{
loggingBuilder.Services.Remove(aiLoggingProvider);
}
});
Upvotes: 1