wasmcloud_control_interface/
otel.rs1use std::str::FromStr;
8
9use async_nats::header::{HeaderMap, HeaderName, HeaderValue};
10use opentelemetry::propagation::{Injector, TextMapPropagator};
11use opentelemetry_sdk::propagation::TraceContextPropagator;
12use tracing::span::Span;
13use tracing_opentelemetry::OpenTelemetrySpanExt;
14
15use crate::Result;
16
17#[derive(Debug, Default)]
19#[non_exhaustive]
20pub struct HeaderInjector {
21 inner: HeaderMap,
22}
23
24impl HeaderInjector {
25 pub fn from(headers: impl IntoIterator<Item = (String, String)>) -> Result<Self> {
27 let inner = headers
28 .into_iter()
29 .map(
30 |(h, v)| match (HeaderName::from_str(&h), HeaderValue::from_str(&v)) {
31 (Ok(h), Ok(v)) => Ok((h, v)),
32 (Err(e), _) => Err(format!("failed to build header name: {e}").into()),
33 (_, Err(e)) => Err(format!("failed to build header name: {e}").into()),
34 },
35 )
36 .collect::<Result<HeaderMap>>()?;
37 Ok(HeaderInjector { inner })
38 }
39
40 pub fn new(headers: HeaderMap) -> Self {
42 HeaderInjector { inner: headers }
43 }
44
45 pub fn new_with_span(headers: HeaderMap) -> Self {
48 let mut header_map = Self::new(headers);
49 header_map.inject_context();
50 header_map
51 }
52
53 pub fn default_with_span() -> Self {
56 let mut header_map = Self::default();
57 header_map.inject_context();
58 header_map
59 }
60
61 pub fn inject_context(&mut self) {
63 let ctx_propagator = TraceContextPropagator::new();
64 ctx_propagator.inject_context(&Span::current().context(), self);
65 }
66}
67
68impl Injector for HeaderInjector {
69 fn set(&mut self, key: &str, value: String) {
70 self.inner.insert(key, value.as_ref());
71 }
72}
73
74impl AsRef<HeaderMap> for HeaderInjector {
75 fn as_ref(&self) -> &HeaderMap {
76 &self.inner
77 }
78}
79
80impl From<HeaderMap> for HeaderInjector {
81 fn from(headers: HeaderMap) -> Self {
82 HeaderInjector::new(headers)
83 }
84}
85
86impl From<HeaderInjector> for HeaderMap {
87 fn from(inj: HeaderInjector) -> Self {
88 inj.inner
89 }
90}