You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Web API:ILogger日志接入OpenTelemetry-Jaeger无显示问题排查

.NET Web API日志无法关联Jaeger链路追踪的问题排查与修复

问题场景

在.NET Web API中,通过ILogger、OpenTelemetry协议向Jaeger Collector上报日志并关联链路追踪时,使用Activity.AddEvent()添加的日志能在Jaeger UI正常显示,但调用logger.LogInformation()输出的日志无法被Jaeger捕获关联。

用户原配置代码:

var serviceName = "some_service_name" + mode.ToString();
var jaegrCollectorUrl = "http://jaeger_collector_url:4317";


builder.Services.AddOpenTelemetry()
                    .ConfigureResource(resource => resource.AddService(serviceName: serviceName))
                    .WithMetrics()
                    .WithTracing(tracing => tracing
                        .AddJaegerExporter(a =>
                        {
                            a.Endpoint = new Uri(jaegrCollectorUrl);
                        })
                        .AddAspNetCoreInstrumentation(opt =>
                        {
                            opt.EnrichWithHttpRequest = (activity, httpRequest) =>
                            {
                                activity.DisplayName = httpRequest.Path.Value;
                            };
                        })
                        .AddHttpClientInstrumentation()
                        .AddEntityFrameworkCoreInstrumentation(options =>
                        {
                            options.EnrichWithIDbCommand = (activity, command) =>
                            {
                                activity.DisplayName = $"EFCore DB Command: ({command.CommandType})";
                                activity.SetTag("command_text", command.CommandText);
                                activity.AddTag("method_name", null);
                            };
                        })
                        .AddOtlpExporter(otlpOptions =>
                        {
                            otlpOptions.Endpoint = new Uri(jaegrCollectorUrl);
                            otlpOptions.Protocol = OtlpExportProtocol.Grpc;
                        }));

builder.Logging.ClearProviders();
Log.Logger = new LoggerConfiguration()
               .MinimumLevel.Information()
               .WriteTo.Console()
               .WriteTo.OpenTelemetry(a =>
               {
                   a.Endpoint = jaegrCollectorUrl;
                   a.Protocol = OtlpProtocol.Grpc;
               })
               .CreateLogger();
builder.Logging.AddSerilog(Log.Logger);

问题原因

  1. Serilog未关联链路上下文:原配置中Serilog的OpenTelemetry输出没有绑定当前的Activity(链路上下文),导致日志无法关联到对应的Trace/Span。
  2. 重复Exporter配置:同时添加JaegerExporter和OtlpExporter,两者功能重叠,可能引发上报逻辑冲突。
  3. 日志缺少链路标识:日志未注入TraceId和SpanId,Jaeger无法将日志匹配到具体链路。

修复步骤及代码调整

1. 修改Serilog配置,关联链路上下文

添加日志上下文 enrichment,确保链路信息被注入到日志中:

builder.Logging.ClearProviders();
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .Enrich.FromLogContext() // 从日志上下文获取当前Activity信息
    .Enrich.WithTraceIdAndSpanId() // 自动注入TraceId、SpanId到日志属性
    .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} TraceId:{TraceId} SpanId:{SpanId}{NewLine}{Exception}") // 控制台输出链路ID方便调试
    .WriteTo.OpenTelemetry(options =>
    {
        options.Endpoint = jaegrCollectorUrl;
        options.Protocol = OtlpProtocol.Grpc;
        options.ResourceAttributes = new Dictionary<string, object>
        {
            { "service.name", serviceName } // 确保服务名称与OTel配置一致
        };
        options.IncludeScopes = true; // 包含日志作用域,关联Activity上下文
    })
    .CreateLogger();
builder.Logging.AddSerilog(Log.Logger);

2. 简化OpenTelemetry Tracing配置

Jaeger原生支持OTLP协议,无需同时配置JaegerExporter,保留OtlpExporter即可:

builder.Services.AddOpenTelemetry()
    .ConfigureResource(resource => resource.AddService(serviceName: serviceName))
    .WithMetrics()
    .WithTracing(tracing => tracing
        .AddAspNetCoreInstrumentation(opt =>
        {
            opt.EnrichWithHttpRequest = (activity, httpRequest) =>
            {
                activity.DisplayName = httpRequest.Path.Value;
            };
        })
        .AddHttpClientInstrumentation()
        .AddEntityFrameworkCoreInstrumentation(options =>
        {
            options.EnrichWithIDbCommand = (activity, command) =>
            {
                activity.DisplayName = $"EFCore DB Command: ({command.CommandType})";
                activity.SetTag("command_text", command.CommandText);
                // 移除null值的tag,避免潜在异常
                // activity.AddTag("method_name", null);
            };
        })
        .AddOtlpExporter(otlpOptions =>
        {
            otlpOptions.Endpoint = new Uri(jaegrCollectorUrl);
            otlpOptions.Protocol = OtlpExportProtocol.Grpc;
        }));

3. 确保日志在链路上下文内输出

在API请求的Action中,AspNetCoreInstrumentation会自动创建Activity,此时调用ILogger的日志会自动关联链路:

[ApiController]
[Route("[controller]")]
public class DemoController : ControllerBase
{
    private readonly ILogger<DemoController> _logger;

    public DemoController(ILogger<DemoController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IActionResult Index()
    {
        // 此时已存在请求对应的Activity,日志会自动关联链路
        _logger.LogInformation("Starting work. 2: ");
        return Ok();
    }
}

修改完成后,logger.Log输出的日志会携带TraceId和SpanId,并通过OpenTelemetry上报到Jaeger,即可在对应链路的详情页面中查看这些日志。

内容的提问来源于stack exchange,提问作者Mohamad Lashgarbolok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 03:18:17