我正在尝试实现一个自定义ITelemetryInitializer
(UserTelemetryInitialiser
),它将一些用户元数据附加到应用程序见解消息,并且我得到了以下循环依赖项。
UserTelemetryInitialiser
转到依赖于Microsoft.Extensions.Caching.Memory.MemoryCache
实现的IMemoryCache
的用户缓存。 然后MemoryCache
依赖于ILoggerFactory
(由Microsoft.Extensions.Logging.LoggerFactory
实现),LoggerFactory
最终取决于TelemetryConfiguration
。
所以我有这个(缩短的)循环链:TelemetryConfiguration
->UserTelemetryInitialiser
->MyUserCache
->MemoryCache
->LoggerFactory
->TelemetryConfiguration
.
关于如何解决这个问题的任何想法?
我正在使用 ASP.NET Core 5.0和Microsoft.ApplicationInsights.AspNetCore 2.18.0。
编辑: 我的简化初始值设定项如下所示(其中IHttpContextAccessor
用于获取用户标识):
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)
{
}
}
问题根源
使用依赖注入时将IMemoryCache
注入ITelemetryInitializer
的问题在于,调用services.AddApplicationInsightsTelemetry()
为LoggerFactory
注册ApplicationInsightsLoggerProvider
。
由于IMemoryCache
(MemoryCache
)的默认实现依赖于ILogger
,这需要LoggerFactory
现在又取决于构造TelemetryClient
ApplicationInsightsLoggerProvider
,因此取决于所有配置ITelemetryInitializers
......我们现在有一个循环依赖。
解决方案 A(遥测初始值设定项中的内存缓存中没有日志记录)
如果您不记录来自遥测初始值设定项中MemoryCache
的消息,则可以简单地通过提供一个 Setup-方法来配置遥测初始值设定项,该方法可以在没有记录器的情况下构造MemoryCache
(默认使用NullLogger.Instance
):
services.AddSingleton<ITelemetryInitializer>(serviceProvider
=> new MyTelemetryInitializer(new MemoryCache(optionsAccessor: serviceProvider.GetRequiredService<IOptions<MemoryCacheOptions>>())));
解决方案 B(从日志记录配置中删除 ApplicationInsightsLoggerProvider)
对于偶然的机会,在 MemoryCache 中记录对您来说比通过应用程序见解跟踪warnings
更重要,您可以从 LoggerFactory 中删除ApplicationInsightsLoggerProvider
:
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);
}
});