.NET 8中Serilog DI变更引发DiagnosticContext注入问题咨询
问题
在ASP.NET Core 8.0 Web API中,遇到Serilog与DiagnosticContext相关的运行时问题。此前正常运行的配置代码如下:
public static WebApplicationBuilder AddLogging(this WebApplicationBuilder builder, params ILogEventSink[] extraLogEventSinks) { builder.Host .UseSerilog((context, services, configuration) => { configuration .ReadFrom.Configuration(context.Configuration) .Enrich.WithMachineName() .Enrich.WithEnvironmentName() .Enrich.FromLogContext() .Enrich.With<OperationIdEnricher>() .Enrich.With<VersionNumberEnricher>() .Enrich.With(new ServiceNameEnricher(builder.Configuration)) .Enrich.WithExceptionDetails() .Enrich.WithSensitiveDataMasking(options => { options.MaskProperties = ["Authorization"]; options.MaskingOperators.Clear(); }) .Filter.With(new HealthEndpointFilter()) .WriteTo.ApplicationInsights(services.GetRequiredService<TelemetryConfiguration>(), new OperationTelemetryConverter()); foreach (var extraLogEventSink in extraLogEventSinks) { configuration.WriteTo.Sink(extraLogEventSink); } var minimumLoglevel = builder.Environment.IsDevelopment() ? LogEventLevel.Verbose : LogEventLevel.Error; if (builder.Environment.IsProduction()) { configuration.WriteTo.Console(new CompactJsonFormatter(), restrictedToMinimumLevel: minimumLoglevel); } else { configuration.WriteTo.Console(restrictedToMinimumLevel: minimumLoglevel); } }); return builder; }
现在API无法启动,抛出运行时错误:
System.InvalidOperationException: Unable to resolve service for type 'Serilog.Extensions.Hosting.DiagnosticContext' while attempting to activate 'Serilog.AspNetCore.RequestLoggingMiddleware'
尝试添加.Services.AddSingleton<DiagnosticContext>()到WebApplicationBuilder,又引发新错误:
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType:
Serilog.Extensions.Hosting.DiagnosticContext Lifetime: Singleton ImplementationType: Serilog.Extensions.Hosting.DiagnosticContext':
Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'Serilog.Extensions.Hosting.DiagnosticContext'.)
添加.Services.AddSingleton<DiagnosticContext>().AddSingleton(Log.Logger)后问题暂时解决,但有以下疑问:
- .NET 8的ASP.NET Core Web API包与Serilog有哪些变更导致此问题?
- 添加该Singleton Logger是否会破坏其他ILogger或ILogger
依赖? - 是否需要添加文档中的Logger创建代码?当前配置是否正确?using Serilog是否会引发Serilog.Log与Microsoft.Extensions.Logging的冲突?
解答
1. 问题根源:.NET 8与Serilog的适配变更
.NET 8调整了ASP.NET Core中间件的激活逻辑,而适配.NET 8的Serilog.AspNetCore版本,对DiagnosticContext等服务的注册方式做了修改。旧版本中UseSerilog可能会自动注册这些服务,但如果你的Serilog版本未及时升级,或者配置方式未触发自动注册逻辑(比如仅在委托内配置Logger,未让Serilog完全接管日志系统),就会导致DI容器无法解析DiagnosticContext,进而引发RequestLoggingMiddleware的激活失败。
2. 添加Singleton Logger的影响
不会破坏其他ILogger或ILogger<T>依赖。Serilog.AspNetCore已经将Microsoft.Extensions.Logging.ILogger<T>的实现替换为Serilog适配器,你添加的Serilog.ILogger单例是Serilog自身的核心日志实例,与.NET框架的日志接口属于不同类型,DI容器会正确区分两者,不会出现冲突或覆盖。
3. 配置正确性与命名空间冲突
- 是否需要手动创建Logger:不需要。正确的做法是升级到适配.NET 8的最新Serilog.AspNetCore版本,此时调用
builder.Host.UseSerilog(...)会自动注册DiagnosticContext、Serilog.ILogger等必要服务,无需手动添加单例。 - 当前配置的问题:配置逻辑本身没问题,但缺少Serilog服务的自动注册环节。升级Serilog.AspNetCore版本后,移除手动添加的
AddSingleton<DiagnosticContext>()和AddSingleton(Log.Logger)代码,即可正常启动。 - 命名空间冲突问题:不会冲突。
Serilog.Log是Serilog的静态日志类,Microsoft.Extensions.Logging下的是日志接口及实现,两者命名空间不同。若代码中出现歧义,可使用完全限定名(如Serilog.Log.Information(...)或Microsoft.Extensions.Logging.ILogger)明确区分。
内容的提问来源于stack exchange,提问作者Chaos

