You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang微服务中用Jaeger构建分布式追踪Span树

分布式追踪问题:Jaeger无法生成Parent ID,无法展示Span层级结构

我有一个微服务,用Jaeger+OpenTracing实现分布式追踪,但现在无法生成Parent ID,Jaeger UI只显示默认操作,看不到Span图和层级结构。

Docker-Compose Jaeger配置

jaeger:
  container_name: jaeger
  image: jaegertracing/all-in-one:1.39
  restart: always
  ports:
    - 5775:5775/udp
    - 6831:6831/udp
    - 6832:6832/udp
    - 5778:5778
    - 16686:16686
    - 14268:14268
    - 9411:9411
    
  environment:
    - COLLECTOR_OTLP_ENABLED=true
    - OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:16686"
    - COLLECTOR_ZIPKIN_HTTP_PORT=9411
    - JAEGER_SERVICE_NAME=baran-endpoint
    - JAEGER_AGENT_HOST=jaeger
    - JAEGER_REPORTER_LOG_SPANS=true
    - JAEGER_SAMPLER_TYPE=const
    - JAEGER_SAMPLER_PARAM=1
    - JAEGER_SAMPLER_SERVER_URL=
  networks:
    - network-jaeger

Go代码实现

var (
  TracingAnalysisEndpoint      = "http://localhost:26855/SaleService.svc"
)
const AgentSwitch = false

func NewJaegerTracer(service string) opentracing.Tracer {
    if AgentSwitch == true {
        return NewJaegerTracerAgent(service)
    }
    return NewJaegerTracerDirect(service)
}

func NewJaegerTracerDirect(service string) opentracing.Tracer {
    sender := transport.NewHTTPTransport(
        TracingAnalysisEndpoint,
    )
    tracer, _ := jaeger.NewTracer(service,
        jaeger.NewConstSampler(true),
        jaeger.NewRemoteReporter(sender, jaeger.ReporterOptions.Logger(jaeger.StdLogger)),
    )
    return tracer
}

func NewJaegerTracerAgent(service string) opentracing.Tracer {
    sender, _ := jaeger.NewUDPTransport("",0)
    tracer, _ := jaeger.NewTracer(service,
        jaeger.NewConstSampler(true),
        jaeger.NewRemoteReporter(sender, jaeger.ReporterOptions.Logger(jaeger.StdLogger)),
    )
    return tracer
}

func StartSpanFromRequest(tracer opentracing.Tracer, r *http.Request, funcDesc string) opentracing.Span {
 spanCtx, _ := Extract(tracer, r)
 return tracer.StartSpan(funcDesc, ext.RPCServerOption(spanCtx))
}

func Inject(span opentracing.Span, request *http.Request) error {
 return span.Tracer().Inject(
  span.Context(),
  opentracing.HTTPHeaders,
  opentracing.HTTPHeadersCarrier(request.Header))
}

func Extract(tracer opentracing.Tracer, r *http.Request) (opentracing.SpanContext, error) {
 return tracer.Extract(
  opentracing.HTTPHeaders,
  opentracing.HTTPHeadersCarrier(r.Header))
}

当前Span使用方式

span:= config.StartSpanFromRequest(config.Tracer,ctx.Request(), "customer method")
defer span.Finish()   
span.LogKV(fmt.Sprintf("Customer not found: %s", request.Mobile))

问题分析与解决方案

1. 追踪上报地址错误

你的TracingAnalysisEndpoint设置为http://localhost:26855/SaleService.svc,这不是Jaeger的收集地址。Jaeger HTTP收集的默认地址是http://localhost:14268/api/traces(直接上报到Collector),如果用Agent模式,UDP地址默认是localhost:6831。

修改TracingAnalysisEndpoint为正确地址:

TracingAnalysisEndpoint = "http://localhost:14268/api/traces"

如果用Agent模式,修正UDP地址:

sender, _ := jaeger.NewUDPTransport("localhost", 6831)

2. 缺少全局Tracer注册

OpenTracing需要将初始化的Tracer设置为全局实例,否则跨函数/请求的Span无法关联。在初始化Tracer后添加:

opentracing.SetGlobalTracer(tracer)

3. 父子Span关联的正确方式

  • 内部函数调用创建子Span:服务内部调用时,基于父Span创建子Span,使用opentracing.ChildOf选项:
// 在父Span上下文创建子Span
childSpan := tracer.StartSpan("sub-operation", opentracing.ChildOf(span.Context()))
defer childSpan.Finish()
  • 跨服务调用传递Span上下文:调用其他微服务时,必须将当前Span上下文注入到HTTP请求头,对方服务再Extract作为父Span:
// 发起请求前注入Span上下文
req, _ := http.NewRequest("GET", "http://other-service/api", nil)
err := Inject(parentSpan, req)
if err != nil {
    // 处理错误
}
// 发送请求
client.Do(req)

4. Docker-Compose环境变量修正

  • OTEL_EXPORTER_OTLP_ENDPOINT设置错误,Jaeger的OTLP HTTP端点默认是http://localhost:4318,不是UI端口16686,可删除该变量或设置正确值。
  • JAEGER_SERVICE_NAME是客户端配置,应在Go代码中设置,容器侧无需该配置。

修正后的Jaeger环境变量:

environment:
  - COLLECTOR_OTLP_ENABLED=true
  - COLLECTOR_ZIPKIN_HTTP_PORT=9411
  - JAEGER_REPORTER_LOG_SPANS=true

5. 完善错误处理

代码中忽略了大量错误(如tracer, _ := jaeger.NewTracer),初始化失败时无法排查,需添加错误处理:

tracer, err := jaeger.NewTracer(service, jaeger.NewConstSampler(true), jaeger.NewRemoteReporter(sender))
if err != nil {
    log.Fatalf("Failed to init Jaeger tracer: %v", err)
}

验证步骤

  1. 修正配置和代码后,重启Jaeger和微服务
  2. 发起请求,访问Jaeger UI(http://localhost:16686)
  3. 检查Span是否有Parent ID,是否形成层级结构

内容的提问来源于stack exchange,提问作者r saniei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:24:56