use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SpanContextCarrier {
headers: HashMap<String, String>,
}
impl SpanContextCarrier {
pub fn get(&self, key: &str) -> Option<&str> {
self.headers.get(key).map(String::as_str)
}
pub fn set(&mut self, key: impl Into<String>, value: impl Into<String>) {
self.headers.insert(key.into(), value.into());
}
pub fn keys(&self) -> impl Iterator<Item = &str> {
self.headers.keys().map(String::as_str)
}
pub(crate) fn set_parent_of(&self, span: &tracing::Span) {
#[cfg(not(feature = "tracing-subscriber-03"))]
let _ = span;
#[cfg(feature = "tracing-subscriber-03")]
span.with_subscriber(|(_id, dispatch)| {
if let Some(propagator) = dispatch.downcast_ref::<PropagatorLayer>() {
propagator.0.set_parent(span, self);
}
});
}
pub(crate) fn from_span_or_current(span: &tracing::Span) -> Option<Self> {
#[cfg(not(feature = "tracing-subscriber-03"))]
{
let _ = span;
None
}
#[cfg(feature = "tracing-subscriber-03")]
{
let current = tracing::Span::current();
tracing::dispatcher::get_default(|dispatch| {
let propagator = dispatch.downcast_ref::<PropagatorLayer>()?;
let mut carrier = Self::default();
propagator.0.inject(span, &mut carrier);
if carrier.headers.is_empty() {
propagator.0.inject(¤t, &mut carrier);
}
Some(carrier)
})
}
}
}
#[cfg(feature = "tracing-subscriber-03")]
pub trait Propagator: Send + Sync + 'static {
fn inject(&self, span: &tracing::Span, carrier: &mut SpanContextCarrier);
fn set_parent(&self, span: &tracing::Span, carrier: &SpanContextCarrier);
}
#[cfg(feature = "tracing-subscriber-03")]
pub fn layer<S>(propagator: impl Propagator) -> impl tracing_subscriber::Layer<S>
where
S: tracing::Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
{
use tracing_subscriber::Layer;
PropagatorLayer(Box::new(propagator)).with_filter(tracing::level_filters::LevelFilter::OFF)
}
#[cfg(feature = "tracing-subscriber-03")]
struct PropagatorLayer(Box<dyn Propagator>);
#[cfg(feature = "tracing-subscriber-03")]
impl<S: tracing::Subscriber> tracing_subscriber::Layer<S> for PropagatorLayer {}