必须在main()开头注册tracerprovider并调用otel.settracerprovider和otel.settextmappropagator,否则所有span为nil且静默失效;http须用otelhttp.newhandler、数据库用otelsql.injectdriver、goroutine必须显式传递context。

不注册 TracerProvider,所有 otel.Tracer().Start() 返回的都是 nil span,Jaeger 里永远看不到 trace_id——这不是 bug,是静默失效,程序照跑、日志无报错、链路彻底不可见。
TracerProvider 必须在 main() 开头注册且全局唯一
Go 的 OpenTelemetry SDK 不会 panic,但一旦漏掉这一步,整个链路追踪就形同虚设。原因在于 otel.Tracer() 内部 fallback 到 noop 实现,后续所有 span 操作都无效。
- 必须在
main()第一行(或紧随init()后)执行:sdktrace.NewTracerProvider()+otel.SetTracerProvider()+otel.SetTextMapPropagator(propagation.TraceContext{}) - 别放
init():单元测试并发调用时可能 panic;别在 handler 或中间件里 new:会导致多个 provider 冲突、采样逻辑错乱、exporter 连接泄漏 -
Resource必须提前构造并传入sdktrace.NewTracerProvider(),否则service.name、host.ip等关键属性全丢,后台无法按服务聚合
HTTP 入口必须用 otelhttp.NewHandler,不是手写 header 解析
自己解析 req.Header.Get("traceparent") 再调 tracer.Start(),看似能生成 span,实则漏掉 HTTP server 的全部语义约定。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 不会自动记录
http.status_code、net.peer.ip、http.route,span name 固定为HTTP GET,而非真实路由如GET /api/users/:id - 跨 goroutine 传播失败:handler 里起
go doWork(),子协程里的 span 就变成 root,trace_id全 0 - Gin/Echo 用户必须用
ginotel.Middleware或echootel.Middleware,不能把otelhttp.NewHandler塞进gin.Use()——否则路由参数丢失,span name 退化
数据库和出向 HTTP 调用必须用 instrumented client
在 db.Query() 前后手动 span.Start()/End() 是典型误区:它只覆盖业务层执行时间,完全忽略连接池等待、驱动解析、网络往返等真实瓶颈。
- 数据库:用
go.opentelemetry.io/contrib/instrumentation/database/sql,注册时调sql.OpenDB(otelsql.InjectDriver("mysql", driver)),不是sql.Open() - MySQL 驱动限定为
github.com/go-sql-driver/mysql;modernc.org/sqlite等纯 Go 驱动不兼容 hook 点 - 出向 HTTP:必须用
otelhttp.NewTransport(http.DefaultTransport)构造http.Client,不能直接改http.DefaultClient,否则影响其他未 instrument 的 SDK
goroutine 和异步逻辑里 context 必须显式传递
Go 的 context 不会自动跨 goroutine 继承 span。这是 80% 的链路断裂根源,不是 SDK 问题,是代码没传对 context。
- 禁止出现
context.Background()或context.TODO()——生产代码里它们等于主动切断链路 - 所有新 goroutine 必须显式传参:
go doWork(ctx),不是go doWork() - 数据库操作必须用
db.QueryContext(ctx, ...),ORM 如 GORM 必须链式调用.WithContext(ctx) - 第三方库若未适配 OpenTelemetry(如老版本 ent),需手动用
otel.GetTextMapPropagator().Inject()补traceparentheader
最易被忽略的点是:TracerProvider 注册后,otel.SetTextMapPropagator() 缺一不可;而所有异步分支里,ctx 传错一次,整条链就断在那个位置,且毫无提示。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










