应直接使用 echootel.middleware,因其能自动记录 http.status_code、net.peer.ip、http.route 等语义标签,并确保 context 跨 goroutine 传播、span 精准结束;手动封装会导致 span 名退化、指标丢失、trace_id 为 0 及静默失效等问题。

直接用 echootel.Middleware,别自己封装 HTTP handler 包装逻辑——否则 span name 会退化成 GET /,丢失路由名、状态码、延迟等关键语义。
为什么不能手写中间件包装 HTTP handler
手动在 c.Next() 前后调 tracer.Start() 和 span.End() 会漏掉 OpenTelemetry 对 HTTP server 的标准约定:
- 不自动记录
http.status_code、net.peer.ip、http.route - 无法在
WriteHeader后精准结束 span(可能提前或延迟) - 跨 goroutine 时 context 不传播:比如你在 handler 里起
go func() { ... },里面的 span 就变成 root,trace_id 全是 0
必须确保 TracerProvider 全局唯一且提前注册
如果 TracerProvider 没在 main() 开头注册,或重复初始化,后果是静默失效:所有 otel.Tracer().Start() 返回 nil span,HTTP handler 不生成 server span,但程序完全不报错。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- 必须在
main()最开头调一次otel.SetTracerProvider(tp)和otel.SetTextMapPropagator(propagation.TraceContext{}) - 别放
init():单元测试并发初始化会 panic - 别在 handler 或中间件里 new:会导致 provider 冲突、采样错乱、exporter 连接泄漏
echootel.Middleware 的正确用法
它本质是把业务 handler 包进 otelhttp.NewHandler,并确保处于中间件链最外层(即第一个 e.Use())。
- 导入:
"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/v5/echootel" - 注册顺序必须靠前:
e.Use(echootel.Middleware("my-app")),不能嵌套在自定义日志/鉴权中间件之后 - 第二个参数是 service name,会作为
service.name标签写入 span - 默认 span name 是匹配到的路由名(如
GET /users/:id),不是原始路径
上报指标需额外配置 exporter 和 metrics pipeline
echootel.Middleware 只负责 traces,不自动暴露 Prometheus 指标。要上报 HTTP 指标(如请求数、延迟直方图),得单独配 metrics:
- 用
otelmetric.MustNewMeterProvider()初始化 meter provider - 注册
prometheus.NewExporter()或通过 OTLP 推给 Collector - 再手动挂一个 metrics 中间件(
echo-prometheus是旧方案,推荐用 OTel 原生http.Handler+otelhttp.NewHandler的 metrics 版本)
最容易被忽略的是:traces 和 metrics 的 exporter 必须共用同一个 TracerProvider / MeterProvider 上下文,否则数据对不上、采样不一致。










