必须在main()最开头初始化TracerProvider并调用otel.SetTracerProvider和otel.SetTextMapPropagator,否则所有span静默失效;Beego需用otelhttp.NewMiddleware注册中间件、otelhttp.Transport封装HTTP客户端,并确保ServiceName合法。

Beego 初始化 tracer 必须在 main() 最开头
Beego 的 App.Run() 启动后会接管 HTTP server,所有中间件、路由注册都发生在它之后——但 OpenTelemetry 全局 TracerProvider 是单例且只初始化一次。如果把 initTracer() 塞进 func init()、app.Config() 或 Beego 中间件里,otel.GetTracerProvider() 会返回 tracer.Start() 都静默退化为 noop,Jaeger UI 里完全空白。
正确顺序只有这一种:
- 加载配置(如
viper.ReadInConfig()) - 紧跟着调用
initTracer()(含非空ServiceName和有效 reporter) - 再执行
beego.Run()
验证是否生效:加一行 log.Printf("tracer provider: %v", otel.GetTracerProvider()),输出必须是非
Beego 中间件必须用 otelhttp.NewMiddleware(),不能手写 Extract
Beego 的 Controller.Run() 不自动解析 uber-trace-id 或 traceparent header,手动调 tracer.Extract() 极易出错:大小写写成 Uber-Trace-Id、漏传 tracestate、carrier 类型用错(比如传 map[string][]string 却没实现 TextMapCarrier 接口),Jaeger 就静默丢弃整个 span。
标准做法是直接注册 OTel 官方中间件:
beego.InsertFilter("*", beego.BeeAppHandler, otelhttp.NewMiddleware("my-beego-service").ServeHTTP)
它内部调用 otel.GetTextMapPropagator().Extract(),并把 parent span 绑定到 ctx,后续业务代码才能通过 this.Ctx.Request.Context() 拿到上下文派生子 span。别只调 tracer.StartSpan("http-server") 就完事——没绑定到 request context,子 span 全部孤立。
Beego 调用下游 HTTP 服务时,必须用 otelhttp.Transport
Beego 默认用 http.DefaultClient,它不自动注入 trace context。裸调 http.Post() 或 client.Do(req) 会断链,下游收不到 traceparent header。
正确方式是封装一个带追踪能力的 client:
client := &http.Client{
Transport: otelhttp.NewTransport(http.DefaultTransport),
}
req, _ := http.NewRequestWithContext(ctx, "GET", "http://user-svc/users/123", nil)
resp, _ := client.Do(req) // 自动注入 traceparent header
注意:req 必须带上游传入的 ctx(来自 Beego controller 的 this.Ctx.Request.Context()),否则注入的是 root span,不是 child of。
本地开发 UDP reporter 端口和协议必须严格匹配 Jaeger Agent
本地跑 jaegertracing/all-in-one 时,默认监听 6831/udp(Thrift Compact 协议)。如果你配成 "localhost:6832",Jaeger Agent 会静默丢包——因为 6832 是 Thrift Binary 协议端口,需显式设 Reporter.Protocol = "thrift_binary"。
Docker Desktop for Mac 上 UDP 转发偶尔失效,可改用:
-
docker run -d --network=host jaegertracing/all-in-one,然后 Go 侧配localhost:6831 - 或换 HTTP reporter:
jaeger.NewHTTPReporter("http://localhost:14268/api/traces"),失败会明确报错,比 UDP 静默丢包好排查
ServiceName 不能含空格或特殊字符(如 "my-beego app" 或 "my-beego-app!"),填错会导致 Collector 静默拒收,UI 搜不到服务。


















