go服务中加opentelemetry自动埋点需使用官方instrumentation插件(如otelhttp、otelgin、otelsql),http handler须用otelhttp.newhandler封装,gin需替换servehttp,数据库用otelsql.open;必须提前初始化trace provider并设置全局propagator(如b3或w3c),本地调试可配jaeger all-in-one(udp 6831)并禁用采样;跨服务需确保context透传(otelhttp.transport/otelgrpc.interceptor),异步任务须用trace.contextwithspan携带span;生产环境推荐parentbased采样+span过滤,避免属性过多和exporter超时阻塞。

Go服务里怎么加OpenTelemetry自动埋点
直接用 go.opentelemetry.io/contrib/instrumentations/net/http 和 go.opentelemetry.io/contrib/instrumentations/github.com/gin-gonic/gin 这类官方维护的插件,比自己手写span更稳。自动埋点只覆盖HTTP handler和数据库驱动这类标准组件,业务逻辑里的关键路径还得手动打点。
常见错误是只注册了trace provider但没设置全局propagator,导致跨服务链路断开;或者忘了调用 otel.SetTextMapPropagator 配合B3或W3C格式。
- HTTP服务必须用
otelhttp.NewHandler包一层原handler,不能只靠中间件 - Gin用户要替换默认engine.ServeHTTP为
otelgin.Middleware返回的handler - 数据库要用封装过的driver,比如
otelsql.Open替代sql.Open - 所有instrumentation初始化必须在服务启动前完成,否则首几个请求不带traceID
本地开发时怎么把trace发到Jaeger
不用搭完整后端,Jaeger All-in-One镜像足够调试:运行 docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one,然后Go服务里配置exporter指向 localhost:6831。
注意UDP端口6831是Jaeger thrift compact协议默认入口,别错配成14268(HTTP接收端),后者需要额外配置JSON body和Content-Type,容易405。
- 用
otlptracegrpc.NewClient会连不上Jaeger——它只支持OTLP协议,而Jaeger默认不开启OTLP receiver - 临时调试建议关掉采样:
sdktrace.AlwaysSample(),避免因采样率=0.001看不到trace - 检查日志里有没有
Failed to export spans,大概率是地址写成http://localhost:6831(多了http://)
微服务间context怎么透传traceID
HTTP调用走 otelhttp.Transport 就行,它自动inject context到request header;gRPC用 otelgrpc.Interceptor 同理。但手动构造HTTP client或用第三方库(如 resty)时,得显式调用 otel.GetTextMapPropagator().Inject。
最容易漏的是异步任务:比如发消息到Kafka,或起goroutine处理数据。这些场景下原始request context已结束,必须用 trace.ContextWithSpan 拷贝span到新context,否则子任务traceID为空。
- HTTP header key默认是
traceparent(W3C)或X-B3-TraceId(B3),两边服务要一致 - 如果上游是Java Spring Cloud,大概率用B3,Go这边就得设
otel.SetTextMapPropagator(b3.New()) - logrus/zap等日志库集成OTel时,记得用
otellogrus.WithTracing,不然log里不带trace_id字段
生产环境怎么控制trace数据量
全量上报撑不住,得靠采样+过滤。SDK自带的 ParentBased 采样器最常用:根span(无parent)按固定率采,子span继承父span决策。别用 TraceIDRatioBased,它对每个traceID哈希,同一trace里部分span可能被丢弃,链路不完整。
更细粒度控制靠span processor:比如用 bsp.SpanProcessor 加filter,跳过健康检查、metrics endpoint这类无业务价值的span。
- 采样率设0.01(1%)适合中等流量服务;QPS过万的服务建议先设0.001,观察jaeger-query内存占用
- 避免在handler里用
span.SetAttributes写大量字符串,属性过多会拖慢exporter,优先用event记录关键状态 - exporter超时设短一点:
WithTimeout(5 * time.Second),防止卡住整个HTTP响应
链路追踪不是开箱即用的功能,从本地验证到生产灰度,每一步都要确认context是否真正传递、span是否被正确结束、exporter有没有静默失败——这些地方一出问题,整条链就断了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











