OpenTelemetry 是 Golang 微服务链路追踪的唯一合理起点,因老方案已停维护且与现代后端不兼容;HTTP 服务需用 otelhttp.NewHandler 自动注入透传 traceparent,Gin/Echo 等框架须适配对应中间件,跨 goroutine 和异步任务必须显式传递 context,gRPC 需同时注册 unary 和 stream 拦截器,数据库应优先选用支持 OTel 的驱动。

OpenTelemetry 是当前 Golang 微服务链路追踪的唯一合理起点。老方案(如 opentracing-go 或原始 jaeger-client-go)已停止维护,且与现代后端(Jaeger v1.50+、Tempo、AWS X-Ray)存在传播格式不兼容、采样策略无法同步等问题。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
HTTP 服务怎么自动注入和透传 traceparent
otelhttp.NewHandler 能自动完成提取、创建 server span、写回响应头三件事,但前提是你的 handler 是标准 http.Handler。Gin/Echo 等框架需手动适配:
- 不要用
context.Background()或context.TODO()启动新 goroutine,必须从c.Request.Context()派生 - 若手写中间件,调用
otel.GetTextMapPropagator().Extract(),别自己拼traceparent字符串(易错且不兼容 baggage) - 对接 Java Spring Cloud 时,默认
TraceContextpropagator 不生效,必须显式注册propagation.B3{}并确保 header 是X-B3-TraceId
gRPC 客户端和服务端如何避免链路断裂
只配otelgrpc.UnaryServerInterceptor 不够,长连接场景下 stream 调用会丢 span:
- 必须同时注册
otelgrpc.UnaryServerInterceptor和otelgrpc.StreamServerInterceptor - 客户端侧同样要配
otelgrpc.UnaryClientInterceptor和otelgrpc.StreamClientInterceptor -
grpc.ClientConn初始化时需传入拦截器,不能只在单次Invoke里加 - metadata 是透传载体,但 OTel 拦截器已自动处理,无需手动读写
metadata.MD
跨 goroutine 和异步任务怎么保 trace 上下文
Go 没有 TLS,context.Context 是唯一可靠载体,漏传一次就断:
- 启动新 goroutine 时,必须用
ctx := context.WithValue(parentCtx, key, val)或更推荐的context.WithCancel(parentCtx),而不是go func() { ... }()直接闭包捕获 - 定时任务(如
time.AfterFunc)、消息队列消费者(如 Kafka handler)都得显式接收并传递context.Context - 数据库操作若用原生
db.Query,需手动 wrap 成带 ctx 的版本;优先选支持 OTel 的驱动(如otelmysql)
真正容易被忽略的不是“怎么加 tracer”,而是所有中间层对 context.Context 的无感透传——它不报错,但链路会在某个 goroutine 分叉点悄无声息地消失。

















