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

OpenTelemetry .NET SDK无Trace输出问题排查求助

问题:WebAPI中OpenTelemetry Trace无法输出及发送至Collector的排查

Metrics可正常发送到Prometheus并显示在控制台,但Trace既不输出到控制台,也未被OTel Collector接收(无日志记录),Grafana Tempo中也无数据。添加了ActivityListener后,控制台也没有任何Activity启动的输出。

原代码

using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);
var metricCollectorUrl = builder.Configuration["OtelMetricCollector:Host"] ?? "";
var traceCollectorUrl = builder.Configuration["OtelTraceCollector:Host"] ?? "";

builder.Services
    .AddMetrics()
    .AddOpenTelemetry()
    .ConfigureResource(r =>
    {
        r.AddService("OrderService");
    })
    .WithMetrics(m =>
    {
        m.AddMeter("OrderServiceMeter")
            .AddOtlpExporter(o =>
            {
                o.Protocol = OtlpExportProtocol.HttpProtobuf;
                o.Endpoint = new Uri(metricCollectorUrl);
            })
            .AddConsoleExporter();

    })
    .WithTracing(t =>
    {
        t.AddSource("Order Service APIs")
            .AddConsoleExporter()
            .AddOtlpExporter(o =>
            {
                o.Protocol = OtlpExportProtocol.HttpProtobuf;
                o.Endpoint = new Uri(traceCollectorUrl);
            });
    });


var app = builder.Build();

Counter<int>? otlOrderCount = null;

ActivitySource.AddActivityListener(new ActivityListener()
{
    ActivityStarted = r =>
    {
        Console.WriteLine($"Activity {r.DisplayName} started.");
    }
});
app.MapGet("/", async (context) =>
{
    using var activity = Activity.Current?.Start();
    activity.SetTag("Service", "Order");
    activity.DisplayName = "Order Processing";

    var metricFactory = context.RequestServices.GetService<IMeterFactory>();
    var meter = metricFactory?.Create(new MeterOptions("OrderServiceMeter"));
    otlOrderCount = meter?.CreateCounter<int>("otel_order");

    otlOrderCount?.Add(1);

    using (var step1Activity = activity.Start()) // Create child spans within the root activity
    {
        step1Activity.SetTag("Step", "Get Customer Info.");
        step1Activity.DisplayName = "Customer Info";
        step1Activity.SetStatus(ActivityStatusCode.Ok);
            
    }

    using (var step2Activity = activity.Start())
    {
        step2Activity.SetTag("Step", "Get Shipping Info.");
        step2Activity.DisplayName = "Shipping Info";
        step2Activity.SetStatus(ActivityStatusCode.Ok);
    }

    activity.SetStatus(ActivityStatusCode.Ok); // Set status on root activity
});
app.Run();

代码中的错误点

  • Activity创建逻辑错误:Activity.Current?.Start()无法创建有效的Activity,因为初始请求进来时Activity.Current为null,导致后续所有子Activity也无法生成。必须通过ActivitySource实例来启动Activity,且该实例的名称要和OTel配置中AddSource的名称一致。

  • 未启用ASP.NET Core请求追踪:OTel未配置捕获WebAPI的请求Activity,需要在WithTracing中添加.AddAspNetCore(),否则WebAPI的请求不会被纳入Trace链路。

  • ActivityListener未设置监听规则:添加的ActivityListener没有配置ShouldListenTo委托,导致它不会监听任何ActivitySource,自然不会触发ActivityStarted事件。

  • Metrics对象重复创建:每次请求都创建新的Meter和Counter,这会导致Metrics数据混乱,不符合OTel的最佳实践,应该在应用启动时一次性创建。

修正后的代码示例

using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);
var metricCollectorUrl = builder.Configuration["OtelMetricCollector:Host"] ?? "";
var traceCollectorUrl = builder.Configuration["OtelTraceCollector:Host"] ?? "";

// 全局定义ActivitySource,名称要和OTel配置中的AddSource一致
var activitySource = new ActivitySource("Order Service APIs");
// 全局创建Meter和Counter
var meter = new Meter("OrderServiceMeter");
var otlOrderCount = meter.CreateCounter<int>("otel_order");

builder.Services
    .AddMetrics()
    .AddOpenTelemetry()
    .ConfigureResource(r =>
    {
        r.AddService("OrderService");
    })
    .WithMetrics(m =>
    {
        m.AddMeter(meter.Name)
            .AddOtlpExporter(o =>
            {
                o.Protocol = OtlpExportProtocol.HttpProtobuf;
                o.Endpoint = new Uri(metricCollectorUrl);
            })
            .AddConsoleExporter();

    })
    .WithTracing(t =>
    {
        t.AddSource(activitySource.Name)
            // 添加ASP.NET Core请求追踪,捕获根请求Activity
            .AddAspNetCore()
            .AddConsoleExporter()
            .AddOtlpExporter(o =>
            {
                o.Protocol = OtlpExportProtocol.HttpProtobuf;
                o.Endpoint = new Uri(traceCollectorUrl);
            });
    });

var app = builder.Build();

// 配置ActivityListener,指定监听的ActivitySource
ActivitySource.AddActivityListener(new ActivityListener()
{
    ShouldListenTo = source => source.Name == activitySource.Name,
    ActivityStarted = r =>
    {
        Console.WriteLine($"Activity {r.DisplayName} started.");
    }
});

app.MapGet("/", async (context) =>
{
    // 使用全局ActivitySource创建根Activity
    using var activity = activitySource.StartActivity("Order Processing");
    if (activity == null) return;
    
    activity.SetTag("Service", "Order");
    activity.SetStatus(ActivityStatusCode.Ok);

    otlOrderCount.Add(1);

    // 创建子Activity
    using var step1Activity = activitySource.StartActivity("Customer Info", ActivityKind.Internal, activity.Context);
    if (step1Activity != null)
    {
        step1Activity.SetTag("Step", "Get Customer Info.");
        step1Activity.SetStatus(ActivityStatusCode.Ok);
    }

    using var step2Activity = activitySource.StartActivity("Shipping Info", ActivityKind.Internal, activity.Context);
    if (step2Activity != null)
    {
        step2Activity.SetTag("Step", "Get Shipping Info.");
        step2Activity.SetStatus(ActivityStatusCode.Ok);
    }
});

app.Run();

内容的提问来源于stack exchange,提问作者Aref Karimi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:55:01