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

OpenTelemetry: ActivitySource.StartActivity返回Null及traceparent标记随机问题

问题:OpenTelemetry traceparent末尾标记随机为00/01导致Activity创建失败

环境信息

  • OpenTelemetry 1.4.0
  • OpenTelemetry.Extensions.Hosting 1.4.0
  • OpenTelemetry.Instrumentation.AspNetCore 1.0.0-rc9.14
  • .NET 6.0 ASP.NET WebApi
  • Docker镜像:6.0-alpine3.17

场景与问题

有两个REST API服务A和B,服务A的OpenTelemetry注册代码如下:

public static class OTRegistration
{
    private static readonly ActivitySource _activitySource = new ActivitySource(Assembly.GetExecutingAssembly().GetName().Name!, "1.0.0");

    public static void AddOT(this IServiceCollection services)
    {
        services.AddOpenTelemetry()
            .WithTracing(tracerProviderBuilder =>
                tracerProviderBuilder
                .AddSource(_activitySource.Name)
                .ConfigureResource(resource => resource.AddService(_activitySource.Name))
                .AddAspNetCoreInstrumentation()
                );
    }
}

客户端调用服务A后,A会调用服务B。此时A发送的traceparent头部末尾标记随机出现00或01(示例:00-000000000000000056473954588e71ac-36ae11cc57b1e9c1-00)。当标记为00时,服务B执行Activity? activity = _activitySource.StartActivity("TestActivity");会返回null,且已确认B已挂载监听者(日志显示HasListeners=True)。

根据微软文档,ActivityTraceFlags有None(0)和Recorded(1)两个值,怀疑00标记会导致Activity无法创建。

想问:服务A发送的traceparent末尾为何随机出现00和01?如何控制该行为消除随机性?


原因分析

traceparent末尾的标记对应ActivityTraceFlags.Recorded,随机性的核心原因是采样策略未明确配置:

  1. 你的服务A当前未指定采样器,OpenTelemetry默认使用ParentBasedSampler。在1.4.0版本中,若未添加任何导出器(如控制台、Jaeger等),TracerProvider会动态判断是否需要采样——当认为没有记录目标时,部分Activity会被标记为Drop(对应00),部分保留为Recorded(对应01),表现出随机性。
  2. 服务B中StartActivity返回null是因为OpenTelemetry的采样规则:父Activity被标记为Drop(00)时,子Activity默认会继承该状态,即使有监听者也会跳过创建。

解决方案

方法1:显式配置全采样器(强制所有链路被记录)

修改服务A的OpenTelemetry注册代码,添加SetSampler指定AlwaysOnSampler,确保所有Activity的采样状态一致为Recorded:

public static void AddOT(this IServiceCollection services)
{
    services.AddOpenTelemetry()
        .WithTracing(tracerProviderBuilder =>
            tracerProviderBuilder
            .AddSource(_activitySource.Name)
            .ConfigureResource(resource => resource.AddService(_activitySource.Name))
            .AddAspNetCoreInstrumentation()
            // 强制开启全采样
            .SetSampler(new AlwaysOnSampler())
            );
}

方法2:添加导出器(明确Trace记录目标)

如果需要保留默认采样逻辑但消除随机性,添加一个导出器(如控制台导出器),让TracerProvider明确知道有记录目标,从而稳定采样状态:

public static void AddOT(this IServiceCollection services)
{
    services.AddOpenTelemetry()
        .WithTracing(tracerProviderBuilder =>
            tracerProviderBuilder
            .AddSource(_activitySource.Name)
            .ConfigureResource(resource => resource.AddService(_activitySource.Name))
            .AddAspNetCoreInstrumentation()
            // 添加控制台导出器作为示例,也可替换为Jaeger/Zipkin等
            .AddConsoleExporter()
            );
}

可选:服务B的局部优化

若希望服务B不受父采样状态影响,可在StartActivity时强制指定采样决策:

// 忽略父Activity的采样状态,强制创建并记录Activity
Activity? activity = _activitySource.StartActivity(
    "TestActivity", 
    ActivityKind.Internal, 
    default,
    samplingDecision: ActivitySamplingDecision.RecordAndSample
);

但更推荐从服务A统一配置采样策略,保证整条链路的Trace状态一致性。


内容的提问来源于stack exchange,提问作者Jacek Kowalski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:52:21