datadog_formatting_layer/
datadog_ids.rs

1use opentelemetry::trace::{SpanId, TraceContextExt, TraceId};
2use tracing::Subscriber;
3use tracing_opentelemetry::OtelData;
4use tracing_subscriber::{layer::Context, registry::LookupSpan};
5
6#[derive(serde::Serialize)]
7#[cfg_attr(test, derive(Debug, Clone, Copy, serde::Deserialize, PartialEq, Eq))]
8pub struct DatadogTraceId(pub(crate) u64);
9
10#[allow(clippy::fallible_impl_from)]
11impl From<TraceId> for DatadogTraceId {
12    // TraceId are u128 -> 16 Bytes
13    // but datadog needs u64 -> 8 Bytes
14    // Therefore we just take the 8 most significant bytes
15    // This is not ideal and may lead to duplicate trace correlations,
16    // but we cannot do anything against that anyway.
17    fn from(value: TraceId) -> Self {
18        let bytes = value.to_bytes();
19        // this cannot fail
20        #[allow(clippy::unwrap_used)]
21        let most_significant_8_bytes = bytes.get(8..16).unwrap();
22
23        // this also cannot fail because we checked the range one line above
24        #[allow(clippy::unwrap_used)]
25        let bytes_as_sized_slice: [u8; 8] = most_significant_8_bytes.try_into().unwrap();
26
27        Self(u64::from_be_bytes(bytes_as_sized_slice))
28    }
29}
30
31#[derive(serde::Serialize)]
32#[cfg_attr(test, derive(Debug, Clone, Copy, serde::Deserialize, PartialEq, Eq))]
33pub struct DatadogSpanId(pub u64);
34
35impl From<SpanId> for DatadogSpanId {
36    fn from(value: SpanId) -> Self {
37        Self(u64::from_be_bytes(value.to_bytes()))
38    }
39}
40
41pub fn read_from_context<S>(ctx: &Context<'_, S>) -> Option<(DatadogTraceId, DatadogSpanId)>
42where
43    S: Subscriber + for<'a> LookupSpan<'a>,
44{
45    ctx.lookup_current().and_then(|span_ref| {
46        span_ref.extensions().get::<OtelData>().map(|o| {
47            let trace_id = if o.parent_cx.has_active_span() {
48                o.parent_cx.span().span_context().trace_id()
49            } else {
50                o.builder.trace_id.unwrap_or(TraceId::INVALID)
51            };
52
53            (
54                trace_id.into(),
55                o.builder.span_id.unwrap_or(SpanId::INVALID).into(),
56            )
57        })
58    })
59}