遥测配置循环依赖项,具有自定义 ITelemetry初始值设定项 - Core 5.0 ASP.NET 应用程序见解



我正在尝试实现一个自定义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现在又取决于构造TelemetryClientApplicationInsightsLoggerProvider,因此取决于所有配置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);
}
});

最新更新