1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
use crate::layer::WithContext; use opentelemetry::Context; /// Utility functions to allow tracing [`Span`]s to accept and return /// [OpenTelemetry] [`Context`]s. /// /// [`Span`]: https://docs.rs/tracing/latest/tracing/struct.Span.html /// [OpenTelemetry]: https://opentelemetry.io /// [`Context`]: opentelemetry::Context pub trait OpenTelemetrySpanExt { /// Associates `self` with a given OpenTelemetry trace, using the provided /// parent [`Context`]. /// /// [`Context`]: opentelemetry::Context /// /// # Examples /// /// ```rust /// use opentelemetry::{propagation::TextMapPropagator, trace::TraceContextExt}; /// use opentelemetry::sdk::propagation::TraceContextPropagator; /// use tracing_opentelemetry::OpenTelemetrySpanExt; /// use std::collections::HashMap; /// use tracing::Span; /// /// // Example carrier, could be a framework header map that impls otel's `Extract`. /// let mut carrier = HashMap::new(); /// /// // Propagator can be swapped with b3 propagator, jaeger propagator, etc. /// let propagator = TraceContextPropagator::new(); /// /// // Extract otel parent context via the chosen propagator /// let parent_context = propagator.extract(&carrier); /// /// // Generate a tracing span as usual /// let app_root = tracing::span!(tracing::Level::INFO, "app_start"); /// /// // Assign parent trace from external context /// app_root.set_parent(parent_context.clone()); /// /// // Or if the current span has been created elsewhere: /// Span::current().set_parent(parent_context); /// ``` fn set_parent(&self, cx: Context); /// Extracts an OpenTelemetry [`Context`] from `self`. /// /// [`Context`]: opentelemetry::Context /// /// # Examples /// /// ```rust /// use opentelemetry::Context; /// use tracing_opentelemetry::OpenTelemetrySpanExt; /// use tracing::Span; /// /// fn make_request(cx: Context) { /// // perform external request after injecting context /// // e.g. if the request's headers impl `opentelemetry::propagation::Injector` /// // then `propagator.inject_context(cx, request.headers_mut())` /// } /// /// // Generate a tracing span as usual /// let app_root = tracing::span!(tracing::Level::INFO, "app_start"); /// /// // To include tracing context in client requests from _this_ app, /// // extract the current OpenTelemetry context. /// make_request(app_root.context()); /// /// // Or if the current span has been created elsewhere: /// make_request(Span::current().context()) /// ``` fn context(&self) -> Context; } impl OpenTelemetrySpanExt for tracing::Span { fn set_parent(&self, cx: Context) { let mut cx = Some(cx); self.with_subscriber(move |(id, subscriber)| { if let Some(get_context) = subscriber.downcast_ref::<WithContext>() { get_context.with_context(subscriber, id, move |builder, _tracer| { if let Some(cx) = cx.take() { builder.parent_context = cx; } }); } }); } fn context(&self) -> Context { let mut cx = None; self.with_subscriber(|(id, subscriber)| { if let Some(get_context) = subscriber.downcast_ref::<WithContext>() { get_context.with_context(subscriber, id, |builder, tracer| { cx = Some(tracer.sampled_context(builder)); }) } }); cx.unwrap_or_default() } }