主题
31 · OpenTelemetry 链路追踪
目标:理解 Trace / Span / Context 传播,给 Gin(或 gRPC)打上最小链路,并能在后端 UI 里看到一条完整请求。
前置:30 · Prometheus · 28 · gRPC
官方:OpenTelemetry · Go:opentelemetry-go · 导出:OTLP
1. Trace 解决什么
Metrics 告诉你「P95 变慢了」;Trace 告诉你「慢在 DB 还是下游 gRPC」。
text
Trace(一次请求)
└─ Span HTTP Gin
├─ Span GORM Query
└─ Span gRPC GetUser1
2
3
4
2
3
4
| 词 | 含义 |
|---|---|
| TraceId | 全链路唯一 |
| SpanId | 当前步骤 |
| ParentSpan | 父子调用关系 |
| Context | 跨进程传播(HTTP header / gRPC metadata) |
Node 对照:@opentelemetry/sdk-node。日志可把 trace_id 打进 Zap 字段(与 14 串联)。
2. 学习用后端(选一)
| 方案 | 说明 |
|---|---|
| Jaeger all-in-one | 经典,看 Trace UI |
| Grafana Tempo + Grafana | 与 30 同生态 |
| OTel Collector | 统一接收再转发 |
Compose 示意(Jaeger):
yaml
jaeger:
image: jaegertracing/all-in-one:1.60
ports:
- "16686:16686" # UI
- "4318:4318" # OTLP HTTP1
2
3
4
5
2
3
4
5
3. 最小接入思路(Go)
bash
go get go.opentelemetry.io/otel
go get go.opentelemetry.io/otel/sdk
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go get go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin1
2
3
4
2
3
4
启动时:
text
1. 建 OTLP exporter → TracerProvider → otel.SetTracerProvider
2. 设 TextPropagator(TraceContext + Baggage)
3. Gin:r.Use(otelgin.Middleware("notesapi"))
4. 业务里:tracer.Start(ctx, "exportPDF");defer span.End()
5. 下游 HTTP/gRPC 把 ctx 传下去(自动或手动 inject)1
2
3
4
5
2
3
4
5
伪代码:
go
ctx, span := otel.Tracer("notes").Start(ctx, "BuildPDF")
defer span.End()
// ... 业务;出错 span.RecordError(err); span.SetStatus(...)1
2
3
2
3
关键:函数签名带 context.Context,中间件/Start 的 ctx 一路传,不断链。
4. 动手清单
- [ ] Jaeger UI 打开;发一次 HTTP 能看到 Trace
- [ ] 同一 Trace 下至少 2 个 Span(中间件 + 业务)
- [ ] 故意 sleep/慢查询,在时间条上能指出来
- [ ] (可选)Gin → gRPC,两个服务同一 TraceId
- [ ] Zap 日志带上 trace_id(字段级关联)
5. 项目驱动
| 场景 | 看什么 |
|---|---|
| 导出 PDF 慢 | HTTP → Asynq 消费(worker 单独服务时注意传播)→ MinIO |
| 搜索慢 | HTTP → ES client span |
| 多服务 | 用户 gRPC + 手帐 HTTP |
Worker 异步:入队时把 trace context 写入 payload 头,消费时 ContextFromRemote(进阶,知悉即可)。
6. 常见坑 + AI 审查
| 坑 | 说明 |
|---|---|
| 丢 ctx | context.Background() 重启一条新链 |
| 采样 100% 打满生产 | 学习可全采;生产降采样 |
| Span 名过碎/过巨 | 有意义业务名;别每个 for 一次 |
| 只装 SDK 不设 exporter | UI 永远空 |
| AI 混用 OpenTracing 老包 | 统一 OTel |
7. 与 Prometheus 怎么共存
- Metrics:RED、容量
- Traces:单次慢请求解剖
- 进阶:exemplars 把指标点连到 Trace(知悉)
8. 下一篇
有了镜像与指标,再谈编排:
→ 32 · Kubernetes 入门
