init_tracing_opentelemetry/
lib.rs

1//#![warn(missing_docs)]
2#![forbid(unsafe_code)]
3#![warn(clippy::perf)]
4#![warn(clippy::pedantic)]
5#![allow(clippy::module_name_repetitions)]
6#![allow(clippy::missing_errors_doc)]
7#![doc = include_str!("../README.md")]
8#![cfg_attr(docs_rs, feature(doc_cfg))]
9
10pub use opentelemetry_sdk;
11pub use tracing_opentelemetry;
12
13mod error;
14pub use error::Error;
15
16use opentelemetry::propagation::{TextMapCompositePropagator, TextMapPropagator};
17use opentelemetry_sdk::propagation::{BaggagePropagator, TraceContextPropagator};
18use opentelemetry_sdk::trace::TraceError;
19
20#[cfg(feature = "tracing_subscriber_ext")]
21#[cfg_attr(docs_rs, doc(cfg(feature = "tracing_subscriber_ext")))]
22pub mod config;
23#[cfg(feature = "tracing_subscriber_ext")]
24#[cfg_attr(docs_rs, doc(cfg(feature = "tracing_subscriber_ext")))]
25pub mod formats;
26#[cfg(feature = "otlp")]
27#[cfg_attr(docs_rs, doc(cfg(feature = "otlp")))]
28pub mod otlp;
29#[cfg(feature = "tracer")]
30#[cfg_attr(docs_rs, doc(cfg(feature = "tracer")))]
31pub mod resource;
32#[cfg(feature = "stdout")]
33#[cfg_attr(docs_rs, doc(cfg(feature = "stdout")))]
34pub mod stdio;
35#[cfg(feature = "tracing_subscriber_ext")]
36#[cfg_attr(docs_rs, doc(cfg(feature = "tracing_subscriber_ext")))]
37pub mod tracing_subscriber_ext;
38
39/// Configure the global propagator based on content of the env variable [OTEL_PROPAGATORS](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_propagators)
40/// Specifies Propagators to be used in a comma-separated list.
41/// Default value: `"tracecontext,baggage"`
42/// Example: `export OTEL_PROPAGATORS="b3"`
43/// Accepted values for `OTEL_PROPAGATORS` are:
44///
45/// - "tracecontext": W3C Trace Context
46/// - "baggage": W3C Baggage
47/// - "b3": B3 Single (require feature "zipkin")
48/// - "b3multi": B3 Multi (require feature "zipkin")
49/// - "jaeger": Jaeger (require feature "jaeger")
50/// - "xray": AWS X-Ray (require feature "xray")
51/// - "ottrace": OT Trace (third party) (not supported)
52/// - "none": No automatically configured propagator.
53///
54/// # Errors
55///
56/// Will return `TraceError` if issue in reading or instanciate propagator.
57pub fn init_propagator() -> Result<(), TraceError> {
58    let value_from_env =
59        std::env::var("OTEL_PROPAGATORS").unwrap_or_else(|_| "tracecontext,baggage".to_string());
60    let propagators: Vec<(Box<dyn TextMapPropagator + Send + Sync>, String)> = value_from_env
61        .split(',')
62        .map(|s| {
63            let name = s.trim().to_lowercase();
64            propagator_from_string(&name).map(|o| o.map(|b| (b, name)))
65        })
66        .collect::<Result<Vec<_>, _>>()?
67        .into_iter()
68        .flatten()
69        .collect();
70    if !propagators.is_empty() {
71        let (propagators_impl, propagators_name): (Vec<_>, Vec<_>) =
72            propagators.into_iter().unzip();
73        tracing::debug!(target: "otel::setup", OTEL_PROPAGATORS = propagators_name.join(","));
74        let composite_propagator = TextMapCompositePropagator::new(propagators_impl);
75        opentelemetry::global::set_text_map_propagator(composite_propagator);
76    }
77    Ok(())
78}
79
80#[allow(clippy::box_default)]
81fn propagator_from_string(
82    v: &str,
83) -> Result<Option<Box<dyn TextMapPropagator + Send + Sync>>, TraceError> {
84    match v {
85        "tracecontext" => Ok(Some(Box::new(TraceContextPropagator::new()))),
86        "baggage" => Ok(Some(Box::new(BaggagePropagator::new()))),
87        #[cfg(feature = "zipkin")]
88        "b3" => Ok(Some(Box::new(
89            opentelemetry_zipkin::Propagator::with_encoding(
90                opentelemetry_zipkin::B3Encoding::SingleHeader,
91            ),
92        ))),
93        #[cfg(not(feature = "zipkin"))]
94        "b3" => Err(TraceError::from(
95            "unsupported propagators form env OTEL_PROPAGATORS: 'b3', try to enable compile feature 'zipkin'"
96        )),
97        #[cfg(feature = "zipkin")]
98        "b3multi" => Ok(Some(Box::new(
99            opentelemetry_zipkin::Propagator::with_encoding(
100                opentelemetry_zipkin::B3Encoding::MultipleHeader,
101            ),
102        ))),
103        #[cfg(not(feature = "zipkin"))]
104        "b3multi" => Err(TraceError::from(
105            "unsupported propagators form env OTEL_PROPAGATORS: 'b3multi', try to enable compile feature 'zipkin'"
106        )),
107        #[cfg(feature = "jaeger")]
108        "jaeger" => Ok(Some(Box::new(
109            opentelemetry_jaeger_propagator::Propagator::default()
110        ))),
111        #[cfg(not(feature = "jaeger"))]
112        "jaeger" => Err(TraceError::from(
113            "unsupported propagators form env OTEL_PROPAGATORS: 'jaeger', try to enable compile feature 'jaeger'"
114        )),
115        //FIXME re-enable when opentelementry_aws available for the current version of opentelemetry
116        // #[cfg(feature = "xray")]
117        // "xray" => Ok(Some(Box::new(
118        //     opentelemetry_aws::trace::XrayPropagator::default(),
119        // ))),
120        // #[cfg(not(feature = "xray"))]
121        // "xray" => Err(TraceError::from(
122        //     "unsupported propagators form env OTEL_PROPAGATORS: 'xray', try to enable compile feature 'xray'"
123        // )),
124        "none" => Ok(None),
125        unknown => Err(TraceError::from(format!(
126            "unsupported propagators form env OTEL_PROPAGATORS: '{unknown}'"
127        ))),
128    }
129}
130
131// Re-export the new configuration API for easier access
132#[cfg(feature = "tracing_subscriber_ext")]
133pub use config::{
134    FeatureSet, Guard, LevelConfig, LogFormat, LogTimer, OtelConfig, TracingConfig, WriterConfig,
135};
136
137#[cfg(feature = "tracing_subscriber_ext")]
138pub use formats::{
139    CompactLayerBuilder, FullLayerBuilder, JsonLayerBuilder, LayerBuilder, PrettyLayerBuilder,
140};
141
142#[cfg(all(feature = "tracing_subscriber_ext", feature = "logfmt"))]
143pub use formats::LogfmtLayerBuilder;
144
145#[cfg(test)]
146#[cfg(feature = "tracer")]
147mod tests {
148    use assert2::let_assert;
149
150    #[test]
151    fn init_tracing_failed_on_invalid_propagator() {
152        let_assert!(Err(_) = super::propagator_from_string("xxxxxx"));
153
154        // std::env::set_var("OTEL_PROPAGATORS", "xxxxxx");
155        // dbg!(std::env::var("OTEL_PROPAGATORS"));
156        // let_assert!(Err(_) = init_tracing());
157    }
158}