mas_tower/
trace_context.rs1use http::Request;
8use opentelemetry::propagation::Injector;
9use opentelemetry_http::HeaderInjector;
10use tower::{Layer, Service};
11use tracing::Span;
12use tracing_opentelemetry::OpenTelemetrySpanExt;
13
14trait AsInjector {
16 type Injector<'a>: Injector
17 where
18 Self: 'a;
19
20 fn as_injector(&mut self) -> Self::Injector<'_>;
21}
22
23impl<B> AsInjector for Request<B> {
24 type Injector<'a>
25 = HeaderInjector<'a>
26 where
27 Self: 'a;
28
29 fn as_injector(&mut self) -> Self::Injector<'_> {
30 HeaderInjector(self.headers_mut())
31 }
32}
33
34#[derive(Debug, Clone, Copy, Default)]
36pub struct TraceContextLayer {
37 _private: (),
38}
39
40impl TraceContextLayer {
41 #[must_use]
43 pub fn new() -> Self {
44 Self::default()
45 }
46}
47
48impl<S> Layer<S> for TraceContextLayer {
49 type Service = TraceContextService<S>;
50
51 fn layer(&self, inner: S) -> Self::Service {
52 TraceContextService::new(inner)
53 }
54}
55
56#[derive(Debug, Clone)]
58pub struct TraceContextService<S> {
59 inner: S,
60}
61
62impl<S> TraceContextService<S> {
63 pub fn new(inner: S) -> Self {
65 Self { inner }
66 }
67}
68
69impl<S, R> Service<R> for TraceContextService<S>
70where
71 S: Service<R>,
72 R: AsInjector,
73{
74 type Response = S::Response;
75 type Error = S::Error;
76 type Future = S::Future;
77
78 fn poll_ready(
79 &mut self,
80 cx: &mut std::task::Context<'_>,
81 ) -> std::task::Poll<Result<(), Self::Error>> {
82 self.inner.poll_ready(cx)
83 }
84
85 fn call(&mut self, mut req: R) -> Self::Future {
86 let context = Span::current().context();
88
89 {
93 let mut injector = req.as_injector();
94 opentelemetry::global::get_text_map_propagator(|propagator| {
95 propagator.inject_context(&context, &mut injector);
96 });
97 }
98
99 self.inner.call(req)
100 }
101}