tracing_opentelemetry_ext/
tonic.rs

1use opentelemetry::propagation::{Injector, TextMapPropagator};
2use opentelemetry::sdk::propagation::TraceContextPropagator;
3use std::str::FromStr;
4use tonic::metadata::{AsciiMetadataKey, AsciiMetadataValue, MetadataMap};
5use tonic::service::Interceptor;
6use tracing::Span;
7use tracing_opentelemetry::OpenTelemetrySpanExt;
8
9#[derive(Clone)]
10pub struct TonicTraceInterceptor;
11
12impl Interceptor for TonicTraceInterceptor {
13    fn call(&mut self, mut req: tonic::Request<()>) -> tonic::Result<tonic::Request<()>> {
14        let ctx = Span::current().context();
15        TraceContextPropagator::new().inject_context(&ctx, &mut TonicMetadataInjector(req.metadata_mut()));
16        Ok(req)
17    }
18}
19
20struct TonicMetadataInjector<'a>(&'a mut MetadataMap);
21
22impl Injector for TonicMetadataInjector<'_> {
23    fn set(&mut self, key: &str, value: String) {
24        if let (Ok(key), Ok(value)) = (AsciiMetadataKey::from_str(key), AsciiMetadataValue::try_from(&value)) {
25            self.0.insert(key, value);
26        }
27    }
28}