Docker Compose部署Prometheus与Jaeger:Jaeger无数据排查求助
已完成Prometheus与gRPC服务的监控集成,但Jaeger无法采集链路数据,结合你的配置,从以下维度排查修复:
一、OTEL Collector配置调整
启用Debug Exporter详细日志
当前debug exporter未配置详细输出,无法确认Collector是否收到trace数据。修改配置:exporters: debug: verbosity: detailed sampling_initial: 5 sampling_thereafter: 200重启Collector后查看日志:若无trace输出,说明服务端未发送数据;若有输出但Jaeger未收到,说明Collector到Jaeger的链路存在问题。
添加Batch处理器避免数据丢失
空processors可能导致短时间内的span未批量发送就丢失,添加batch处理器:processors: batch: timeout: 10s send_batch_size: 100并在pipeline中引用该处理器:
service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlp, debug] metrics: receivers: [otlp] processors: [batch] exporters: [prometheus, debug]验证Collector到Jaeger的网络连通性
在OTEL Collector容器中执行命令测试:telnet jaeger 4317若无法连通,检查Jaeger容器是否正常启动、是否与Collector在同一Docker网络,或确认Jaeger的OTLP端口配置。
二、gRPC服务端Trace Provider修复
移除Endpoint的HTTP前缀
otlptracegrpc.WithEndpoint无需http://前缀,gRPC协议直接使用主机+端口。修改SetupTracing中的端点:tp, err := otelTraceProvider(ctx, "otel-collector:4317", "", "", true)移除重复的WithInsecure配置
当前代码重复添加了WithInsecure(),去掉重复项:func otelTraceProvider(ctx context.Context, endpoint, apiKey, caCertPath string, insecure bool) (*trace.TracerProvider, error) { var opts []otlptracegrpc.Option // 设置端点(已去掉http://前缀) opts = append(opts, otlptracegrpc.WithEndpoint(endpoint)) // 处理安全配置 if insecure { opts = append(opts, otlptracegrpc.WithInsecure()) } else { c, err := credentials.NewClientTLSFromFile(caCertPath, "") if err != nil { return nil, fmt.Errorf("failed to create TLS credentials: %w", err) } opts = append(opts, otlptracegrpc.WithTLSCredentials(c)) } // 后续代码保持不变... }添加Trace Provider的Shutdown逻辑
程序退出时未关闭Trace Provider会导致缓存的span未发送,在服务启动的main函数中添加:defer func() { if err := traceProvider.Shutdown(ctx); err != nil { log.Fatal(err) } }()
三、gRPC拦截器正确性验证
替换为官方OTEL gRPC拦截器
当前使用的grpcspan.Interceptors()若为自定义实现,可能存在span生成问题,替换为官方拦截器:// -- OpenTelemetry拦截器配置 otel.SetTracerProvider(traceProvider) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, )) // 使用官方OTEL gRPC拦截器 unaryInterceptor := otelgrpc.UnaryServerInterceptor() streamInterceptor := otelgrpc.StreamServerInterceptor()然后在拦截器链中替换为这两个拦截器:
grpc.ChainUnaryInterceptor( unaryInterceptor, promInterceptor.Unary, serverInterceptor.Unary, logInterceptor.Unary, sessionInterceptor, requestGeneratorSession, recoveryInterceptor.Unary, ) grpc.ChainStreamInterceptor( streamInterceptor, promInterceptor.Stream, serverInterceptor.Stream, logInterceptor.Stream, recoveryInterceptor.Stream, recoveryInterceptor.Stream, )保持拦截器顺序正确
Trace拦截器必须处于链的第一个位置,确保能获取原始请求上下文,当前顺序符合要求,替换后保持不变即可。
四、验证gRPC服务到Collector的连通性
在gRPC服务容器中执行命令测试:
telnet otel-collector 4317
若无法连通,检查服务容器与Collector是否在同一网络,或Collector的OTLP端口是否正确暴露。
内容的提问来源于stack exchange,提问作者Fernando Correia

