ASP.NET Core中用OpenTelemetry为Serilog日志注入traceId(Activity.Current为空)
你的核心问题是Activity.Current在日志写入时始终为null,导致自定义TraceContextEnricher输出"no-activity"。以下是针对性的修复步骤:
1. 注册IHttpContextAccessor服务
ASP.NET Core默认不会自动注册IHttpContextAccessor,你的自定义Enricher依赖它,但当前代码中缺少注册逻辑。在服务配置阶段添加:
builder.Services.AddHttpContextAccessor();
建议放在AddOpenTelemetry()之前,确保DI容器提前准备好该服务。
2. 修复Serilog Enricher的实例获取方式
你手动通过services.GetRequiredService<IHttpContextAccessor>()创建TraceContextEnricher实例,此时DI容器可能尚未完全初始化,导致获取的上下文访问器无法正确关联请求上下文。改用Serilog的DI集成方式:
// 替换原来的.Enrich.With(new TraceContextEnricher(...)) .Enrich.With<TraceContextEnricher>()
这样Serilog会从DI容器中自动获取TraceContextEnricher实例,确保上下文访问器的正确性。
3. 替换自定义Enricher为官方集成(可选但推荐)
自己实现TraceContextEnricher容易踩坑,推荐使用Serilog官方的Activity enricher包简化配置:
- 安装NuGet包:
Serilog.Enrichers.Activity - 修改Serilog配置,移除自定义Enricher,添加:
.Enrich.WithTraceIdAndSpanId()
该包会自动从Activity.Current中提取traceId和spanId,无需手动编写Enricher逻辑。
4. 验证OpenTelemetry Activity的创建逻辑
确保OpenTelemetry的AspNetCore Instrumentation正确启用,当前代码中的配置已经包含.AddAspNetCoreInstrumentation(),默认会为每个HTTP请求创建Activity。如果需要更精细控制,可以添加配置选项:
.AddAspNetCoreInstrumentation(options => { options.EnableActivityTracking = true; // 默认值,可显式声明 options.RecordException = true; // 可选:记录请求中的异常到Activity })
额外排查点
- 如果日志是在请求上下文之外(如启动逻辑、后台任务)写入的,
Activity.Current确实会为空,这种情况属于正常现象,你可以保留当前else分支的逻辑处理。 - 确认采样器设置为
AlwaysOnSampler(你已经配置),避免因采样导致Activity未创建。
内容的提问来源于stack exchange,提问作者ABDELILAH AIT LHAJ

