升级opentelemetry与opentelemetry-jaeger后编译失败求助
OpenTelemetry升级后Trait绑定错误的解决方法
问题背景
原使用以下依赖时,追踪订阅者函数可正常运行,启用Jaeger后能正常查看追踪数据:
opentelemetry = { version = "0.17", features = ["tokio"] } opentelemetry-jaeger = { version = "0.16", features = ["rt-tokio"] }
对应的实现代码:
pub fn get_subscriber(name: String, env_filter: String) -> impl Subscriber + Sync + Send { // Building the jaeger layer, if needed let telemetry = if std::env::var("JAEGER_ENABLED").is_ok() { let tracer = opentelemetry_jaeger::new_pipeline() .with_service_name(&name) .install_batch(opentelemetry::runtime::Tokio) .unwrap(); Some(tracing_opentelemetry::layer().with_tracer(tracer)) } else { None }; let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(env_filter)); let formatting_layer = BunyanFormattingLayer::new(name, std::io::stdout); Registry::default() .with(env_filter) .with(JsonStorageLayer) .with(formatting_layer) .with(sentry_tracing::layer()) .with(telemetry) }
升级到以下依赖后,项目无法编译,出现Trait绑定错误:
opentelemetry = { version = "0.18", features = ["rt-tokio"] } opentelemetry-jaeger = { version = "0.17", features = ["rt-tokio"] }
核心错误信息:
error[E0277]: the trait bound `opentelemetry::sdk::trace::Tracer: opentelemetry::trace::tracer::Tracer` is not satisfied --> rss-common/src/observability.rs:14:57 | 14 | Some(tracing_opentelemetry::layer().with_tracer(tracer)) | ----------- ^^^^^^ the trait `opentelemetry::trace::tracer::Tracer` is not implemented for `opentelemetry::sdk::trace::Tracer` | | | required by a bound introduced by this call | = help: the following other types implement trait `opentelemetry::trace::tracer::Tracer`: opentelemetry::global::trace::BoxedTracer opentelemetry::sdk::trace::tracer::Tracer opentelemetry::trace::noop::NoopTracer note: required by a bound in `OpenTelemetryLayer::<S, T>::with_tracer` --> /home/eric/.cargo/registry/src/github.com-1ecc6299db9ec823/tracing-opentelemetry-0.17.4/src/layer.rs:464:17 | 464 | Tracer: otel::Tracer + PreSampledTracer + 'static, | ^^^^^^^^^^^^ required by this bound in `OpenTelemetryLayer::<S, T>::with_tracer`
解决步骤
1. 同步依赖版本
tracing-opentelemetry作为桥接库,必须与opentelemetry主库版本严格匹配。当前使用的tracing-opentelemetry 0.17.4仅兼容opentelemetry 0.17,需升级到0.18.x版本:
# Cargo.toml中更新依赖 opentelemetry = { version = "0.18", features = ["rt-tokio"] } opentelemetry-jaeger = { version = "0.17", features = ["rt-tokio"] } tracing-opentelemetry = "0.18"
2. 调整Tracer的类型转换
在opentelemetry 0.18中,SDK内部的Tracer需要转换为Trait对象才能被tracing-opentelemetry的层接受,修改代码中创建Telemetry层的逻辑:
pub fn get_subscriber(name: String, env_filter: String) -> impl Subscriber + Sync + Send { // Building the jaeger layer, if needed let telemetry = if std::env::var("JAEGER_ENABLED").is_ok() { let tracer = opentelemetry_jaeger::new_pipeline() .with_service_name(&name) .install_batch(opentelemetry::runtime::Tokio) .unwrap(); // 将SDK Tracer转换为BoxedTracer,满足Trait绑定要求 let boxed_tracer = opentelemetry::trace::Tracer::boxed(tracer); Some(tracing_opentelemetry::layer().with_tracer(boxed_tracer)) } else { None }; let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(env_filter)); let formatting_layer = BunyanFormattingLayer::new(name, std::io::stdout); Registry::default() .with(env_filter) .with(JsonStorageLayer) .with(formatting_layer) .with(sentry_tracing::layer()) .with(telemetry) }
核心原因说明
opentelemetry 0.18对SDK内部的Tracer结构做了拆分,原opentelemetry::sdk::trace::Tracer不再直接实现顶层的opentelemetry::trace::TracerTrait,需通过装箱为BoxedTracer的方式满足约束。- 依赖版本不匹配是触发错误的根本原因,桥接库与主库版本不一致会导致Trait定义不兼容。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

