因为默认配置下tracerprovider未注册activitysource且未启用exporter,导致activity被丢弃;必须显式组装activitysource、tracerproviderbuilder(调addsource)和exporter(如addotlpexporter)三件套。

为什么直接用 OpenTelemetry.Sdk 会收不到 trace?
因为默认配置下,TracerProvider 没有注册任何 ActivitySource,也没有启用导出器(exporter),Activity 创建后直接被丢弃。常见现象是:代码里调了 StartActivity(),但 Jaeger/Zipkin/Otlp 端完全没数据。
关键点在于三件套必须显式组装:
-
ActivitySource—— 你代码里用来创建 span 的源头,名字要和后续采样/过滤规则对得上 -
TracerProviderBuilder—— 必须调用AddSource("your-service-name")把 source 注册进去 - 至少一个
Exporter(比如AddOtlpExporter())—— 否则 trace 数据无处可去
示例片段:
var builder = Sdk.CreateTracerProviderBuilder()
.AddSource("my-api") // 和 new ActivitySource("my-api") 对应
.AddOtlpExporter(opt => opt.Endpoint = new Uri("http://localhost:4317")); // 必须设 endpoint
ASP.NET Core 6+ 中如何自动注入 Activity 并关联 HTTP 上下文?
别手动在每个 Controller 里写 StartActivity() —— OpenTelemetry.Instrumentation.AspNetCore 包已经帮你做了 HTTP 入口的自动埋点,但前提是它得被加进 TracerProvider。
容易漏掉的两件事:
- 必须安装并引用
OpenTelemetry.Instrumentation.AspNetCoreNuGet 包(不是只装OpenTelemetrySDK) - 要在
AddOpenTelemetry()链式调用中显式加.AddAspNetCoreInstrumentation() - 如果用了 gRPC,还得额外加
OpenTelemetry.Instrumentation.GrpcNetClient或Grpc.Net.Client对应插件
否则你会看到:Controller 方法里自己创建的 span 有数据,但 HTTP 请求本身的 root span 缺失,导致链路断在入口。
ActivitySource 命名不一致会导致 trace 断裂吗?
会,而且很隐蔽。OpenTelemetry 的采样、资源标注、甚至 exporter 过滤都依赖 ActivitySource.Name。如果你在代码里写 new ActivitySource("order-service"),但 TracerProvider 只注册了 AddSource("orderservice"),那所有这个 source 发出的 span 全部静默丢失。
建议统一规范:
- 全部小写 + 连字符(如
"user-auth-service"),避免大小写混用或下划线 - 在
Program.cs初始化时就定义常量:public const string ActivitySourceName = "user-auth-service";,各处复用 - 检查日志输出里是否有类似
ActivitySource 'xxx' not registered的警告(需开启OpenTelemetry内部日志)
本地调试时 trace 总是延迟 10 秒才上报?
这是 OtlpExporter 默认的 batch 处理行为:攒够 512 条或等满 10 秒才发一次。开发阶段几乎等于“看不到实时 trace”。
解决方法是在配置 exporter 时显式调小参数:
.AddOtlpExporter(opt =>
{
opt.Endpoint = new Uri("http://localhost:4317");
opt.BatchExportProcessorOptions = new BatchExportActivityProcessorOptions
{
ExporterTimeoutMilliseconds = 3000,
MaxExportBatchSize = 1,
ScheduledDelayMilliseconds = 100
};
});
注意:MaxExportBatchSize = 1 虽然最“实时”,但会显著增加网络请求次数,仅限调试;生产环境建议保留默认或设为 512。
另外,确保后端接收服务(如 otel-collector)已启动且端口可达——HttpRequestException 类错误常被忽略,其实 exporter 连不上时只会默默降级,不抛异常。











