将OTLP追踪数据导出至Jaeger时遇服务未就绪错误求助
尝试将OTLP追踪数据导出至Jaeger时遇到如下错误:
OpenTelemetry trace error occurred. Exporter otlp encountered the following error(s): the grpc server returns error (Unknown error): , detailed error message: Service was not ready: transport error
推测可能是tokio与tonic的交互问题,但无法控制客户端创建。尝试使用grpc方式也失败,http方式缺乏文档说明。
可复现示例
Rust代码
use opentelemetry::trace::Tracer; use opentelemetry_otlp::WithExportConfig; #[tokio::main] async fn main() { let otlp_exporter = opentelemetry_otlp::new_exporter().tonic().with_endpoint("http://jaeger:4317/"); let tracer = opentelemetry_otlp::new_pipeline() .tracing() .with_exporter(otlp_exporter) .install_simple() .unwrap(); tracer.in_span("xyz", |_| {}); }
Cargo配置
[package] name = "sample" version = "0.1.0" edition = "2021" [dependencies] opentelemetry = "0.18.0" opentelemetry-otlp = "0.11" tokio = { version = "1.28", features = ["rt-multi-thread"] }
Docker Compose配置
version: '3.8' services: app: image: mcr.microsoft.com/devcontainers/base:jammy volumes: - ../..:/workspaces:cached command: sleep infinity network_mode: service:jaeger jaeger: image: jaegertracing/all-in-one:1.44 restart: unless-stopped
Jaeger运行在相邻容器中,DNS名称jaeger可解析。
以下是几个可行的排查和修复方向:
1. 强制启用Jaeger的OTLP GRPC端口
Jaeger all-in-one镜像默认开启4317端口,但可通过环境变量明确启用。修改Compose中的Jaeger服务:
jaeger: image: jaegertracing/all-in-one:1.44 restart: unless-stopped environment: - COLLECTOR_OTLP_ENABLED=true
重启Jaeger容器后重新测试连接。
2. 切换为OTLP HTTP/JSON协议
如果GRPC方式存在兼容性问题,可尝试HTTP/JSON协议:
首先更新Cargo.toml,添加http特性:
opentelemetry-otlp = { version = "0.11", features = ["http"] }
然后修改代码使用HTTP exporter:
use opentelemetry::trace::Tracer; use opentelemetry_otlp::WithExportConfig; #[tokio::main] async fn main() { let otlp_exporter = opentelemetry_otlp::new_exporter() .http() .with_endpoint("http://jaeger:4318/v1/traces"); // Jaeger OTLP HTTP默认端口为4318 let tracer = opentelemetry_otlp::new_pipeline() .tracing() .with_exporter(otlp_exporter) .install_simple() .unwrap(); tracer.in_span("xyz", |_| {}); }
3. 修复依赖版本兼容性
版本不匹配可能导致tokio与tonic交互异常,更新依赖到兼容版本:
[dependencies] opentelemetry = "0.19.0" opentelemetry-otlp = "0.12.0" tokio = { version = "1.32", features = ["rt-multi-thread", "macros"] } tonic = "0.9" # 显式指定版本,确保与opentelemetry-otlp兼容
更新后重新构建项目测试。
4. 验证容器网络连通性
在app容器内手动测试端口连通性:
# 进入app容器 docker exec -it <app_container_id> /bin/bash # 测试GRPC端口 nc -zv jaeger 4317 # 测试HTTP端口 nc -zv jaeger 4318
若端口不通,检查Jaeger容器是否正常启动,或是否有网络限制。
5. 启用调试日志排查细节
添加日志依赖并启用调试输出,帮助定位问题:
首先更新Cargo.toml:
tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] }
然后修改代码:
use opentelemetry::trace::Tracer; use opentelemetry_otlp::WithExportConfig; use tracing_subscriber::EnvFilter; #[tokio::main] async fn main() { // 启用调试日志 tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .init(); let otlp_exporter = opentelemetry_otlp::new_exporter() .tonic() .with_endpoint("http://jaeger:4317/") .with_timeout(std::time::Duration::from_secs(10)); // 设置超时时间 let tracer = opentelemetry_otlp::new_pipeline() .tracing() .with_exporter(otlp_exporter) .install_simple() .unwrap(); tracer.in_span("xyz", |_| {}); // 等待追踪数据导出完成 opentelemetry::global::shutdown_tracer_provider(); }
运行时设置环境变量RUST_LOG=debug查看详细日志,获取连接过程中的具体错误信息。
内容的提问来源于stack exchange,提问作者Tom01098

