jaeger客户端初始化报nil pointer dereference主因是未检查jaeger.newtracer返回的tracer是否为nil就调用startspan;opentelemetry采样率不生效因sampler需在tracerprovider构建时配置;http中间件须显式提取并注入context;共存时应统一用otel sdk+jaegerexporter并规范resource和span属性。

Jaeger 客户端初始化为什么总报 nil pointer dereference
常见于没传入有效的 tracer 就直接调用 opentracing.StartSpan,尤其在多 goroutine 场景下误以为全局 tracer 已就绪。Jaeger 的 jaeger.NewTracer 返回值可能为 nil(比如 reporter 初始化失败但没显式检查),而 Go 的 opentracing API 不做非空校验。
- 务必检查
tracer, err := jaeger.NewTracer(...)后的err,且tracer != nil再注册到opentracing.SetGlobalTracer - 避免在
init()函数里初始化 tracer:依赖的配置(如 agent 地址)可能尚未加载完成 - 使用
opentelemetry-go替代opentracing时,otel.Tracer是接口,不会 nil,但otel.GetTracerProvider().Tracer(...)返回的 tracer 仍需确保 provider 已正确设置
OpenTelemetry SDK 配置采样率后链路仍全量上报
默认采样器是 AlwaysSample,但很多人改了 TraceConfig.Sampler 却忘了它只影响新创建的 TracerProvider 实例——已启动的 HTTP handler、gRPC server 不会自动热更新。
- 采样策略必须在
oteltrace.NewTracerProvider构建时传入,例如:oteltrace.WithSampler(oteltrace.ParentBased(oteltrace.TraceIDRatioBased(0.1))) - 若用
otelhttp.NewHandler包裹服务,确保该 handler 使用的是你刚创建的TracerProvider,而非默认的 global provider - Jaeger exporter 默认不压缩 span,大数据量时容易触发 UDP 包截断(尤其在容器内),建议改用
http.NewExporter发送到 Jaeger Collector 的/api/traces端点
Go HTTP 中间件里 context 传递 span 失败,span.Context() 返回空
根本原因是没把带 span 的 context 注入到 request 中,或中间件顺序错乱导致后续 handler 拿不到。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 必须用
req = req.WithContext(otel.GetTextMapPropagator().Extract(req.Context(), propagation.HeaderCarrier(req.Header)))显式提取上游 trace 上下文 - HTTP handler 内部要调用
span := otel.Tracer("http").Start(ctx, "handler"),这里的ctx必须是上一步提取并注入后的 request context - 别在 defer 里调用
span.End()前修改 response header 或写 body,否则 span 可能记录错误状态码(如 200 而非实际返回的 500)
Jaeger 和 OpenTelemetry 共存时 span 名称混乱、服务名丢失
两者对 service name、operation name 的语义约定不同:Jaeger 的 serviceName 对应 OTel 的 service.name resource 属性,而 operation name 在 OTel 中是 span 名,在 Jaeger 中是 operationName 字段。混用 SDK 会导致字段映射错位。
- 统一用 OpenTelemetry SDK,通过
jaegerexporter输出到 Jaeger backend,禁用旧版jaeger-client-go - 设置 resource 时明确指定服务名:
resource.WithAttributes(semconv.ServiceNameKey.String("my-api")) - 避免在 span 名中硬编码 HTTP 方法+路径(如
"GET /users"),改用semconv.HTTPMethodKey、semconv.HTTPRouteKey等标准属性,让 UI 自动聚合
跨进程传播最脆弱的不是代码,而是 header key 大小写和空格——traceparent 必须全小写,baggage 值里不能有未转义的逗号或分号。这些细节一错,整条链路就断在第一个跳转点。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










