jaeger.newtracer 返回 nil 的根本原因是 reporter 初始化失败(如 agent/collector 连接不上),而 go 的 opentracing.startspan 不校验 tracer 非空,导致 panic 且无明确提示;必须显式检查 tracer == nil 或 err != nil 并提前退出。

jaeger.NewTracer 返回 nil?先检查 reporter 是否连上了 agent 或 collector,否则 span 会静默丢失。
tracer 初始化失败:为什么 StartSpan 崩了还查不到错?
根本不是代码写错了,而是 jaeger.NewTracer 在 reporter 初始化失败时返回 nil,而 Go 的 opentracing.StartSpan 不做非空校验——你一调就 panic,但错误堆栈里根本看不到 “tracer is nil” 这种提示。
- 必须显式判断:
if tracer == nil || err != nil { log.Fatal("failed to init tracer:", err) } - 别在
init()里初始化 tracer:配置(比如SERVICE_NAME)可能还没从环境变量或配置中心加载完 - 本地开发时,用
jaeger.NewConstSampler(true)确保采样率 100%,避免因采样器误配导致 trace 消失 - Docker 环境下,
LocalAgentHostPort别写"localhost:6831",得换成服务名如"jaeger-agent:6831"(Docker Compose)或"host.docker.internal:6831"(Mac/Windows)
HTTP 中间件里 span 断链:为什么下游收不到 uber-trace-id?
上游没注入、下游没提取,或者用了不兼容的 header 格式——Jaeger 默认走 uber-trace-id,不是 X-B3-TraceId。自己手动读写 header 或用 Zipkin 风格解析器,链路必然断裂。
- 上游注入必须用:
tracer.Inject(span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header)) - 下游提取必须用:
tracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header)) - 注入后要记得把新 context 绑到 request 上:
req = req.WithContext(ctx),否则 handler 里r.Context()还是空的 - 别在中间件里
defer span.Finish():如果 handler panic,defer 不执行,span 永远 open,Jaeger UI 里显示 “in progress” 卡死
UDP reporter 静默丢数据:为什么 Jaeger UI 里完全没 trace?
Go 客户端默认用 UDP 发送到 localhost:6831,但这个地址在容器里根本不对;更糟的是,UDP 不建连、不报错、不重试——填错地址,span 就彻底消失,日志里连个 warning 都没有。
- 开发阶段直接切 HTTP reporter:
jaeger.NewHTTPReporter("http://localhost:14268/api/traces"),绕过 UDP 不可靠问题 - 用
jaeger-all-in-one镜像时,必须暴露6831/udp端口,否则 agent 收不到 compact thrift 包 - 若直连 collector,URL 必须带
/api/traces,少这一段就是 404,且无任何提示 - 启动 agent 时加
--collector.host-port=127.0.0.1:14268并用netstat -an | grep 14268确认监听正常
span 名称和 tag 写错:为什么 Jaeger UI 里搜不到关键请求?
UI 的搜索栏依赖固定 tag 字段过滤,比如 http.url、http.status_code、span.kind。你随便起个 "handleRequest" 或漏设 span.kind="server",搜索就失效,等于白埋。
- 必须设的 tags:
span.SetTag("span.kind", "server")、span.SetTag("http.url", r.URL.String())、span.SetTag("http.status_code", statusCode) - 业务参数可加 tag,但敏感字段(密码、token)必须脱敏,
span.SetTag("user_id", userID)可以,span.SetTag("auth_token", raw)不行 - 错误要显式标记:
span.SetTag("error", true)+span.LogFields(log.String("event", "error"), log.String("message", err.Error())),否则 UI 不标红 - 避免在循环里反复
span.Log(),高频打点会让 trace 存储暴涨;改用计数器 tag:span.SetTag("db.query.count", count)
StartSpan,而是 reporter 连不上、context 没传透、tag 写错字段、服务名拼错大小写——这些地方不报错,只沉默,等你花半天时间翻日志、抓包、怀疑人生。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











