Kratos 默认不集成 Jaeger,需手动配置 OpenTelemetry SDK 并指定 Jaeger Exporter;必须显式注册 ServerInterceptor 和 ClientInterceptor 以保障跨服务链路完整,且须调用 otel.SetTracerProvider(tp) 否则上报无效。

Kratos 默认不自动集成 Jaeger,必须手动配置 OpenTelemetry SDK 并指定 Jaeger Exporter 才能上报链路数据。
确认 Kratos 项目已启用 Tracing 中间件
Kratos 的 tracing 能力基于 otel(OpenTelemetry)实现,但不会默认开启。你需要显式注册 tracing.ServerInterceptor 和 tracing.ClientInterceptor,否则所有 HTTP/gRPC 请求都不会生成 Span。
- 服务端:在创建
http.Server或grpc.Server时,传入tracing.ServerInterceptor()作为中间件 - 客户端:调用远程服务时,需用
tracing.ClientInterceptor()包装http.Client或grpc.ClientConn - 若只配服务端没配客户端,跨服务调用链会断在第一个出口;只配客户端则入口无 Span,链路不完整
初始化 OpenTelemetry 并指向 Jaeger Collector
Kratos 不提供开箱即用的 Jaeger 配置封装,你得自己构造 TracerProvider,并使用 otlptracehttp.New 或 otlptracegrpc.New 连接 Jaeger 的 collector 端口(默认 http://localhost:14268 或 localhost:14250)。
- Jaeger All-in-One 镜像暴露的是
14268(OTLP HTTP)和14250(OTLP gRPC),不是旧版 Zipkin 端口9411 - 别用
jaeger.New(已弃用),Kratos v2.7+ 强制要求 OTLP 协议 - 必须调用
otel.SetTracerProvider(tp),否则otel.Tracer返回的是 noop 实现,什么也不上报 - 示例关键代码片段:
import (
"go.opentelemetry.io/otel"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
otlptracehttp "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
)
func initTracer() {
exporter, _ := otlptracehttp.New(
context.Background(),
otlptracehttp.WithEndpoint("localhost:14268"),
otlptracehttp.WithInsecure(), // 开发环境可跳过 TLS
)
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.WithAttributes(
semconv.ServiceNameKey.String("user-service"),
)),
)
otel.SetTracerProvider(tp)
}
注意 Context 传递和 Span 命名一致性
Kratos 的 transport 层(http.Transport、grpc.Transport)会自动注入/提取 traceparent header,但前提是你的业务 handler 没有丢弃原始 ctx。
- 所有异步 goroutine 启动前,必须用
trace.ContextWithSpan或trace.SpanContextFromContext显式携带上下文,否则新 goroutine 里新建的 Span 是孤立的 - 避免在 Span 名称里硬编码动态值(如
"GET /user/" + id),会导致指标爆炸;应统一用"GET /user/{id}"并设 attribute - HTTP handler 中不要直接用
req.Context()创建 Span,而要用transport.FromServerContext(req.Context())提取框架注入的元数据后再 start
验证链路是否真正上报成功
光看 Jaeger UI 出现服务名不代表链路完整——常见假阳性是只有单个 Span(比如只有 http.server),没有下游 http.client 或 grpc.client Span。
- 启动服务后,用
curl -v http://localhost:8000/helloworld/bob触发一次调用 - 立刻查 Jaeger UI(
http://localhost:16686),筛选 service name,看 trace 是否包含 ≥2 个 span 且parent_id正确串联 - 如果只看到一个 Span,大概率是客户端拦截器没注册,或下游服务没配 tracing,或网络不通(检查
docker logs jaeger是否有failed to export traces) - 生产环境务必加
sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.01)))控制采样率,否则高 QPS 下 Jaeger 直接 OOM
最易被忽略的一点:Kratos 的 transport 模块会把 Metadata 自动映射为 HTTP headers,但 Jaeger 的 trace context 必须走标准 traceparent 字段;如果你自定义了 header 透传逻辑(比如用 x-trace-id),OpenTelemetry 就无法识别,链路必然断裂。


















