sentry_opentelemetry/
propagator.rs1use std::sync::LazyLock;
16
17use opentelemetry::{
18 propagation::{text_map_propagator::FieldIter, Extractor, Injector, TextMapPropagator},
19 trace::TraceContextExt,
20 Context, SpanId, TraceId,
21};
22use sentry_core::parse_headers;
23use sentry_core::SentryTrace;
24
25use crate::converters::{convert_span_id, convert_trace_id};
26
27const SENTRY_TRACE_KEY: &str = "sentry-trace";
28
29static SENTRY_PROPAGATOR_FIELDS: LazyLock<[String; 1]> =
31 LazyLock::new(|| [SENTRY_TRACE_KEY.to_owned()]);
32
33#[derive(Debug, Copy, Clone)]
36pub struct SentryPropagator {}
37
38impl SentryPropagator {
39 pub fn new() -> Self {
41 Self {}
42 }
43}
44
45impl Default for SentryPropagator {
46 fn default() -> Self {
48 Self::new()
49 }
50}
51
52impl TextMapPropagator for SentryPropagator {
53 fn inject_context(&self, ctx: &Context, injector: &mut dyn Injector) {
54 let trace_id = ctx.span().span_context().trace_id();
55 let span_id = ctx.span().span_context().span_id();
56 let sampled = ctx.span().span_context().is_sampled();
57 if trace_id == TraceId::INVALID || span_id == SpanId::INVALID {
58 return;
59 }
60 let sentry_trace = SentryTrace::new(
61 convert_trace_id(&trace_id),
62 convert_span_id(&span_id),
63 Some(sampled),
64 );
65 injector.set(SENTRY_TRACE_KEY, sentry_trace.to_string());
66 }
67
68 fn extract_with_context(&self, ctx: &Context, extractor: &dyn Extractor) -> Context {
69 let keys = extractor.keys();
70 let pairs = keys
71 .iter()
72 .filter_map(|&key| extractor.get(key).map(|value| (key, value)));
73 if let Some(sentry_trace) = parse_headers(pairs) {
74 return ctx.with_value(sentry_trace);
75 }
76 ctx.clone()
77 }
78
79 fn fields(&self) -> FieldIter<'_> {
80 FieldIter::new(&*SENTRY_PROPAGATOR_FIELDS)
81 }
82}