LCOV - code coverage report
Current view: top level - libs/tracing-utils/src - lib.rs (source / functions) Coverage Total Hit
Test: a72ced5dd7f4aed9fdb382f13853712ccbc77d26.info Lines: 0.0 % 48 0
Test Date: 2025-07-22 20:53:24 Functions: 0.0 % 6 0

            Line data    Source code
       1              : //! Helper functions to set up OpenTelemetry tracing.
       2              : //!
       3              : //! Example:
       4              : //!
       5              : //! ```rust,no_run
       6              : //! use tracing_subscriber::prelude::*;
       7              : //!
       8              : //! #[tokio::main]
       9              : //! async fn main() {
      10              : //!     // Set up logging to stderr
      11              : //!     let env_filter = tracing_subscriber::EnvFilter::try_from_default_env()
      12              : //!         .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info"));
      13              : //!     let fmt_layer = tracing_subscriber::fmt::layer()
      14              : //!         .with_target(false)
      15              : //!         .with_writer(std::io::stderr);
      16              : //!
      17              : //!     // Initialize OpenTelemetry. Exports tracing spans as OpenTelemetry traces
      18              : //!     let provider = tracing_utils::init_tracing("my_application", tracing_utils::ExportConfig::default());
      19              : //!     let otlp_layer = provider.as_ref().map(tracing_utils::layer);
      20              : //!
      21              : //!     // Put it all together
      22              : //!     tracing_subscriber::registry()
      23              : //!         .with(env_filter)
      24              : //!         .with(otlp_layer)
      25              : //!         .with(fmt_layer)
      26              : //!         .init();
      27              : //! }
      28              : //! ```
      29              : #![deny(clippy::undocumented_unsafe_blocks)]
      30              : 
      31              : pub mod http;
      32              : pub mod perf_span;
      33              : 
      34              : use opentelemetry::trace::TracerProvider;
      35              : use opentelemetry_otlp::WithExportConfig;
      36              : pub use opentelemetry_otlp::{ExportConfig, Protocol};
      37              : use opentelemetry_sdk::trace::SdkTracerProvider;
      38              : use tracing::level_filters::LevelFilter;
      39              : use tracing::{Dispatch, Subscriber};
      40              : use tracing_subscriber::Layer;
      41              : use tracing_subscriber::layer::SubscriberExt;
      42              : use tracing_subscriber::registry::LookupSpan;
      43              : 
      44              : pub type Provider = SdkTracerProvider;
      45              : 
      46              : /// Set up OpenTelemetry exporter, using configuration from environment variables.
      47              : ///
      48              : /// `service_name` is set as the OpenTelemetry 'service.name' resource (see
      49              : /// <https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service>)
      50              : ///
      51              : /// We try to follow the conventions for the environment variables specified in
      52              : /// <https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/>
      53              : ///
      54              : /// However, we only support a subset of those options:
      55              : ///
      56              : /// - OTEL_SDK_DISABLED is supported. The default is "false", meaning tracing
      57              : ///   is enabled by default. Set it to "true" to disable.
      58              : ///
      59              : /// - We use the OTLP exporter, with HTTP protocol. Most of the OTEL_EXPORTER_OTLP_*
      60              : ///   settings specified in
      61              : ///   <https://opentelemetry.io/docs/reference/specification/protocol/exporter/>
      62              : ///   are supported, as they are handled by the `opentelemetry-otlp` crate.
      63              : ///   Settings related to other exporters have no effect.
      64              : ///
      65              : /// - Some other settings are supported by the `opentelemetry` crate.
      66              : ///
      67              : /// If you need some other setting, please test if it works first. And perhaps
      68              : /// add a comment in the list above to save the effort of testing for the next
      69              : /// person.
      70            0 : pub fn init_tracing(service_name: &str, export_config: ExportConfig) -> Option<Provider> {
      71            0 :     if std::env::var("OTEL_SDK_DISABLED") == Ok("true".to_string()) {
      72            0 :         return None;
      73            0 :     };
      74            0 :     Some(init_tracing_internal(
      75            0 :         service_name.to_string(),
      76            0 :         export_config,
      77            0 :     ))
      78            0 : }
      79              : 
      80            0 : pub fn layer<S>(p: &Provider) -> impl Layer<S>
      81            0 : where
      82            0 :     S: Subscriber + for<'span> LookupSpan<'span>,
      83              : {
      84            0 :     tracing_opentelemetry::layer().with_tracer(p.tracer("global"))
      85            0 : }
      86              : 
      87            0 : fn init_tracing_internal(service_name: String, export_config: ExportConfig) -> Provider {
      88              :     // Sets up exporter from the provided [`ExportConfig`] parameter.
      89              :     // If the endpoint is not specified, it is loaded from the
      90              :     // OTEL_EXPORTER_OTLP_ENDPOINT environment variable.
      91            0 :     let exporter = opentelemetry_otlp::SpanExporter::builder()
      92            0 :         .with_http()
      93            0 :         .with_export_config(export_config)
      94            0 :         .build()
      95            0 :         .expect("could not initialize opentelemetry exporter");
      96              : 
      97              :     // TODO: opentelemetry::global::set_error_handler() with custom handler that
      98              :     //       bypasses default tracing layers, but logs regular looking log
      99              :     //       messages.
     100              : 
     101              :     // Propagate trace information in the standard W3C TraceContext format.
     102            0 :     opentelemetry::global::set_text_map_propagator(
     103            0 :         opentelemetry_sdk::propagation::TraceContextPropagator::new(),
     104              :     );
     105              : 
     106            0 :     Provider::builder()
     107            0 :         .with_span_processor(
     108            0 :             opentelemetry_sdk::trace::span_processor_with_async_runtime::BatchSpanProcessor::builder(
     109            0 :                 exporter,
     110            0 :                 opentelemetry_sdk::runtime::Tokio,
     111              :             )
     112            0 :             .build(),
     113              :         )
     114            0 :         .with_resource(
     115            0 :             opentelemetry_sdk::Resource::builder()
     116            0 :                 .with_service_name(service_name)
     117            0 :                 .build(),
     118              :         )
     119            0 :         .build()
     120            0 : }
     121              : 
     122              : pub enum OtelEnablement {
     123              :     Disabled,
     124              :     Enabled {
     125              :         service_name: String,
     126              :         export_config: ExportConfig,
     127              :     },
     128              : }
     129              : 
     130              : pub struct OtelGuard {
     131              :     provider: Provider,
     132              :     pub dispatch: Dispatch,
     133              : }
     134              : 
     135              : impl Drop for OtelGuard {
     136            0 :     fn drop(&mut self) {
     137            0 :         _ = self.provider.shutdown();
     138            0 :     }
     139              : }
     140              : 
     141              : /// Initializes OTEL infrastructure for performance tracing according to the provided configuration
     142              : ///
     143              : /// Performance tracing is handled by a different [`tracing::Subscriber`]. This functions returns
     144              : /// an [`OtelGuard`] containing a [`tracing::Dispatch`] associated with a newly created subscriber.
     145              : /// Applications should use this dispatch for their performance traces.
     146              : ///
     147              : /// The lifetime of the guard should match taht of the application. On drop, it tears down the
     148              : /// OTEL infra.
     149            0 : pub fn init_performance_tracing(otel_enablement: OtelEnablement) -> Option<OtelGuard> {
     150            0 :     match otel_enablement {
     151            0 :         OtelEnablement::Disabled => None,
     152              :         OtelEnablement::Enabled {
     153            0 :             service_name,
     154            0 :             export_config,
     155              :         } => {
     156            0 :             let provider = init_tracing(&service_name, export_config)?;
     157              : 
     158            0 :             let otel_layer = layer(&provider).with_filter(LevelFilter::INFO);
     159            0 :             let otel_subscriber = tracing_subscriber::registry().with(otel_layer);
     160            0 :             let dispatch = Dispatch::new(otel_subscriber);
     161              : 
     162            0 :             Some(OtelGuard { dispatch, provider })
     163              :         }
     164              :     }
     165            0 : }
        

Generated by: LCOV version 2.1-beta