必须在main()第一行调用otel.SetTracerProvider()和otel.SetTextMapPropagator(),否则otel.Tracer().Start()返回noop span,链路静默失效、无报错、无日志;HTTP需用otelhttp.NewHandler、出向调用需otelhttp.NewClient、数据库需otelsql.InjectDriver。

为什么 tracer.Start() 总是返回空 span
因为没在 main() 最早调用 otel.SetTracerProvider()。OpenTelemetry Go SDK 不会 fallback 到默认实现,未设置时 otel.Tracer().Start() 返回 noop span,不报错、无日志、链路静默消失——这是 90% 的初学者卡点。
- 必须在
main()函数第一行执行初始化,不能放在init()或中间件里 - 确保
resource.WithAttributes(semconv.ServiceNameKey.String("your-service"))至少包含service.name,否则 Jaeger/Tempo 无法分组 - 本地调试建议用
stdoutexporter.NewUnstarted()+.Start(),直接打印 JSON,比查日志快得多
HTTP 请求链路断在下游服务怎么办
根本原因是没走 OTel 的传播机制,而是手动 copy header 或裸用 http.DefaultClient。trace ID 不透传、context 丢失、采样率失效,全因绕过了 otelhttp.NewPropagator() 和自动 inject/extract。
- 服务端:必须用
otelhttp.NewHandler(yourMux, "service-name")包裹最终 handler,不是加一层中间件 - 客户端:用
otelhttp.NewClient(http.DefaultClient)替代原生 client,所有Do()自动携带 context - Gin 用户注意:
gin.Engine不兼容http.Handler,得套一层gin.WrapH(otelhttp.NewHandler()) - 别手写
req.Header.Set("traceparent", ...)——漏掉 net.peer.ip、状态码自动打标、跨 goroutine context 传播
gRPC 和数据库调用怎么埋点才不丢 span
手动在 db.Query() 前后 tracer.Start()/End() 只测出 SQL 解析耗时,完全漏掉连接池等待、网络往返、驱动解析等关键环节;gRPC 同理,只在业务层 StartSpan 会导致 parent-child 关系断裂、状态码不记录。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- gRPC 客户端:用
grpc.Dial(..., grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor())) - gRPC 服务端:用
grpc.NewServer(grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor())) - 数据库:导入
go.opentelemetry.io/contrib/instrumentation/database/sql,调otelsql.InjectDriver()注册驱动,再sql.Open() - 异步任务(如 goroutine 消费消息)必须显式传递带 trace 的
ctx,用trace.ContextWithSpan(ctx, span)补全上下文
OTLP 上报静默失败,怎么快速定位
Go SDK 默认走 OTLP gRPC 协议上报到 localhost:4317,但生产环境 collector 配置疏漏时,span 就直接消失——没有 error 日志,也没有 fallback 提示。
立即学习“go语言免费学习笔记(深入)”;
- 先确认 collector 是否监听
4317端口:telnet localhost 4317或nc -zv localhost 4317 - 检查
otel.SetTextMapPropagator(otelhttp.NewPropagator())是否在启动早期调用,否则 HTTP 传播字段名可能为空 - 若对接非 Go 服务(如 Python/Node.js),打印
otel.GetTextMapPropagator().Fields()确认字段名一致(如traceparentvsuber-trace-id) - collector 配置里 receiver 必须启用
otlp:并开放grpc:和/或http:协议,否则数据进不来

















