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
use crate::layer::{build_context, WithContext}; use opentelemetry::api; /// `OpenTelemetrySpanExt` allows tracing spans to accept and return /// OpenTelemetry `SpanContext`s. pub trait OpenTelemetrySpanExt { /// Associates `self` with a given `OpenTelemetry` trace, using /// the provided parent context. /// /// ```rust /// use opentelemetry::api::{self, HttpTextFormat}; /// use tracing_opentelemetry::OpenTelemetrySpanExt; /// use std::collections::HashMap; /// use tracing::Span; /// /// // Example carrier, could be a framework header map that impls `api::Carrier`. /// let mut carrier = HashMap::new(); /// /// // Propagator can be swapped with trace context propagator binary propagator, etc. /// let propagator = api::B3Propagator::new(true); /// /// // Extract otel parent span 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); /// /// // Or if the current span has been created elsewhere: /// Span::current().set_parent(propagator.extract(&carrier)); /// ``` fn set_parent(&self, span_context: api::SpanContext); /// Extracts an `OpenTelemetry` context from `self`. /// /// ```rust /// use opentelemetry::api; /// use tracing_opentelemetry::OpenTelemetrySpanExt; /// use tracing::Span; /// /// fn make_request(span_context: api::SpanContext) { /// // perform external request after injecting context /// // e.g. if there are request headers that impl `opentelemetry::api::Carrier` /// // then `propagator.inject(span_context, request.headers_mut())` /// } /// /// // Generate a tracing span as usual /// let app_root = tracing::span!(tracing::Level::INFO, "app_start"); /// /// // To include tracing span context in client requests from _this_ app, /// // extract the current OpenTelemetry span context. /// make_request(app_root.context()); /// /// // Or if the current span has been created elsewhere: /// make_request(Span::current().context()) /// ``` fn context(&self) -> api::SpanContext; } impl OpenTelemetrySpanExt for tracing::Span { fn set_parent(&self, parent_context: api::SpanContext) { self.with_subscriber(move |(id, subscriber)| { let mut parent_context = Some(parent_context); if let Some(get_context) = subscriber.downcast_ref::<WithContext>() { get_context.with_context(subscriber, id, move |builder| { builder.parent_context = parent_context.take() }); } }); } fn context(&self) -> api::SpanContext { let mut span_context = None; self.with_subscriber(|(id, subscriber)| { if let Some(get_context) = subscriber.downcast_ref::<WithContext>() { get_context.with_context(subscriber, id, |builder| { span_context = Some(build_context(builder)); }) } }); span_context.unwrap_or_else(api::SpanContext::empty_context) } }