datadog_formatting_layer/
datadog_ids.rs1use 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 fn from(value: TraceId) -> Self {
18 let bytes = value.to_bytes();
19 #[allow(clippy::unwrap_used)]
21 let most_significant_8_bytes = bytes.get(8..16).unwrap();
22
23 #[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}