必须用activitysource.startactivity()启动trace,返回null是采样器主动丢弃;sourcename必须完全一致;跨线程需显式传activitycontext;baggage需手动传播与重建;activity不适用于数据沿袭追踪。

直接用 new Activity("name") 启动不了有效 trace,必须走 ActivitySource.StartActivity(),且返回值为 null 时不能继续操作——这是绝大多数人踩坑的第一步。
为什么 StartActivity() 返回 null?
不是 bug,是采样器主动丢弃。OpenTelemetry 默认采样策略(如 ParentBased<code>(AlwaysOff))会根据父上下文决定是否创建 span。若上游没传 <code>traceparent 或当前服务未启用采样,StartActivity() 就返回 null。
- 忽略判空直接调
SetTag()或Stop()→NullReferenceException - 误以为“没数据”是配置错,其实 trace 已被合法丢弃
- 开发期可临时设
AddAlwaysOnSampler()验证逻辑,上线前切回合理策略
ActivitySource.Name 不匹配就彻底静默
你在代码里写 new ActivitySource("user-service"),但 TracerProviderBuilder 只调了 AddSource("userservice"),那所有 activity 全部丢失,连日志都不会报错。
- 名称必须完全一致:大小写、连字符、点号都不能差
- 建议定义常量:
public const string SourceName = "user-service";,各处复用 - ASP.NET Core 中若用了
AddAspNetCoreInstrumentation(),它默认注册的 source 名是Microsoft.AspNetCore.Hosting,不是你的服务名
手动传播 traceparent 时漏掉 Baggage 和 TraceState
只传 traceparent 头,下游能拿到链路 ID,但业务透传字段(如 tenant-id)和供应商扩展字段(如 vendor-state)全丢了。
- 发送方要同时写三个头:
traceparent、tracestate、baggage - 接收方不能只用
ActivityContext.TryParse()解析traceparent,还得手动重建 Baggage:ActivityContext.CreateBaggage(baggageHeader) -
Baggage是只读集合,修改需用WithBaggageItem("k", "v")生成新实例
跨线程/Task.Run 里 Activity.Current 为空怎么办?
Activity.Current 在 async/await 下自动流转,但 Task.Run(() => { ... }) 或 ThreadPool.QueueUserWorkItem 会断开上下文。
- 别用
AsyncLocal<activity></activity>手动存取——它已被Activity.Current底层封装,直接操作会破坏一致性 - 正确做法:在主线程捕获
Activity.Current?.Context,子线程入口用Activity.StartActivity("name", ActivityKind.Internal, context)显式传入 - 细粒度 IO(如每读一块文件)不值得单独开 span,按语义操作建(如
"File.Load.Config"),否则压垮 collector
最易被忽略的是:Activity 不是数据沿袭工具。它不管变量从哪来、被谁改过,只管“谁触发了谁”。想追踪文件内容流向,得自己设计 DataFlowContext + AsyncLocal,别硬套 Activity。











