use opentelemetry::propagation::{Extractor, Injector};
use opentelemetry::Context;
use tracing_opentelemetry_instrumentation_sdk as otel;
pub struct HeaderInjector<'a>(pub &'a mut http::HeaderMap);
impl<'a> Injector for HeaderInjector<'a> {
fn set(&mut self, key: &str, value: String) {
if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) {
if let Ok(val) = http::header::HeaderValue::from_str(&value) {
self.0.insert(name, val);
}
}
}
}
pub struct HeaderExtractor<'a>(pub &'a http::HeaderMap);
impl<'a> Extractor for HeaderExtractor<'a> {
fn get(&self, key: &str) -> Option<&str> {
self.0.get(key).and_then(|value| value.to_str().ok())
}
fn keys(&self) -> Vec<&str> {
self.0
.keys()
.map(http::HeaderName::as_str)
.collect::<Vec<_>>()
}
}
pub fn inject_context_on_context(context: &Context, headers: &mut http::HeaderMap) {
let mut injector = HeaderInjector(headers);
opentelemetry::global::get_text_map_propagator(|propagator| {
propagator.inject_context(context, &mut injector);
});
}
pub fn inject_context(headers: &mut http::HeaderMap) {
let mut injector = HeaderInjector(headers);
opentelemetry::global::get_text_map_propagator(|propagator| {
propagator.inject_context(&otel::find_current_context(), &mut injector);
});
}
#[must_use]
pub fn extract_context(headers: &http::HeaderMap) -> Context {
let extractor = HeaderExtractor(headers);
opentelemetry::global::get_text_map_propagator(|propagator| {
propagator.extract(&extractor)
})
}