Go应用需通过OpenTelemetry SDK配置OTLP HTTP exporter(指向Tempo的4318端口/v1/traces)发送trace,不可直调Tempo API或使用Jaeger Thrift;必须在main开头初始化TracerProvider并设置采样策略为ParentBased(AlwaysSample)以避免静默丢弃。

Go 应用如何发送 trace 到 Grafana Tempo
Tempo 不接收原始 trace 数据,只接受 OpenTelemetry 协议(OTLP)或 Jaeger/Zipkin 格式的数据;Go 项目必须通过 OpenTelemetry SDK + exporter 推送 trace,不能直接调用 Tempo API。
关键路径是:otelhttp 或 otelgrpc 自动注入 span → TracerProvider 配置 exporter → 使用 otlphttp.NewExporter 指向 Tempo 的 OTLP 接收端(通常是 http://tempo:4318/v1/traces)。
- Tempo 默认监听
4318端口的 OTLP HTTP endpoint,不是9411(Zipkin)或14268(Jaeger) - 若 Tempo 启用了 Basic Auth,需在 exporter 配置中传入
otlphttp.WithHeaders("Authorization", "Basic ...") - 不要用
jaeger.NewRawExporter——它发的是 Thrift over UDP,Tempo 不支持;必须用 OTLP HTTP 或 gRPC exporter
为什么 trace 在 Tempo 里搜不到?常见排查点
最常卡在数据“发出去了但没存进去”,不是 SDK 配置问题,而是 Tempo 侧接收链路断了。
先确认 Tempo 是否真正收到了 trace:
- 查 Tempo 日志,搜索
"received traces"或"traces dropped";如果日志里完全没出现 trace 相关关键词,说明 exporter 连接失败或被防火墙拦截 - 用
curl -X POST http://tempo:4318/v1/traces -H 'Content-Type: application/x-protobuf' --data-binary @trace.bin手动发一条测试 trace(需提前用otelcol导出 protobuf 格式),验证 endpoint 可达性 - Go client 默认使用
otlphttp.NewExporter,但若 Tempo 部署在 Kubernetes 中且启用了 TLS,必须显式设置otlphttp.WithInsecure()(开发环境)或配置 CA 证书(生产)
如何让 trace ID 被下游 HTTP 服务正确传递
Go 的 otelhttp 中间件只负责提取和注入 traceparent,但不会自动把 trace context 注入到 outbound request 的 header 中——你得手动做。
典型错误:A 服务收到请求并生成 span,调用 B 服务时没透传 context,导致 B 的 span 成为独立 root span。
- 所有 outbound HTTP 请求必须用
req = req.WithContext(ctx),其中ctx是从当前 span 获取的(trace.SpanContextFromContext(r.Context())) - 推荐用
http.DefaultClient.Do(req)而非http.Get,因为后者不支持传入带 context 的 request - 若用
resty或gqlgen等库,需确认其是否集成 otel;否则要在SetHeader中手动加traceparent字段(用otel.GetTextMapPropagator().Inject())
Tempo 查询慢或 span 数量异常少?检查采样率配置
Tempo 本身不采样,采样决策全在客户端(Go SDK)。默认是 ParentBased(AlwaysSample),但一旦你引入了 TraceIDRatioBased 或自定义采样器,就可能大量丢 span。
尤其注意:Kubernetes 环境下多个 Pod 共享同一服务名时,若用 TraceIDRatioBased(0.01),实际采样率可能远低于预期(因为 trace ID 分布不均)。
- 开发期建议设为
AlwaysSample();上线后改用ParentBased(TraceIDRatioBased(0.1)),确保子 span 跟随父 span 决策 - 避免在
TracerProvider中直接用TraceIDRatioBased作为顶层采样器——它会忽略 parent span 的 sampled flag - Tempo 的
search页面默认只查最近 1 小时、最多 20 条 trace;如要查更久或更多,需调整 URL 参数:?limit=100&lookback=6h


















