datadog-formatting-layer 7.0.0

A crate providing a tracing-subscriber layer for formatting events so Datadog can parse them
Documentation
use opentelemetry::trace::{SpanId, TraceId};
use tracing::Subscriber;
use tracing_opentelemetry::OtelData;
use tracing_subscriber::{layer::Context, registry::LookupSpan};

#[derive(serde::Serialize)]
#[cfg_attr(test, derive(Debug, Clone, Copy, serde::Deserialize, PartialEq, Eq))]
pub struct DatadogTraceId(pub(crate) u64);

#[allow(clippy::fallible_impl_from)]
impl From<TraceId> for DatadogTraceId {
    // TraceId are u128 -> 16 Bytes
    // but datadog needs u64 -> 8 Bytes
    // Therefore we just take the 8 most significant bytes
    // This is not ideal and may lead to duplicate trace correlations,
    // but we cannot do anything against that anyway.
    fn from(value: TraceId) -> Self {
        let bytes = value.to_bytes();
        // this cannot fail
        #[allow(clippy::unwrap_used)]
        let most_significant_8_bytes = bytes.get(8..16).unwrap();

        // this also cannot fail because we checked the range one line above
        #[allow(clippy::unwrap_used)]
        let bytes_as_sized_slice: [u8; 8] = most_significant_8_bytes.try_into().unwrap();

        Self(u64::from_be_bytes(bytes_as_sized_slice))
    }
}

#[derive(serde::Serialize)]
#[cfg_attr(test, derive(Debug, Clone, Copy, serde::Deserialize, PartialEq, Eq))]
pub struct DatadogSpanId(pub u64);

impl From<SpanId> for DatadogSpanId {
    fn from(value: SpanId) -> Self {
        Self(u64::from_be_bytes(value.to_bytes()))
    }
}

pub fn read_from_context<S>(ctx: &Context<'_, S>) -> Option<(DatadogTraceId, DatadogSpanId)>
where
    S: Subscriber + for<'a> LookupSpan<'a>,
{
    ctx.lookup_current().and_then(|span_ref| {
        span_ref.extensions().get::<OtelData>().map(|otel| {
            let trace_id = otel.trace_id().unwrap_or(TraceId::INVALID);
            let span_id = otel.span_id().unwrap_or(SpanId::INVALID);

            (trace_id.into(), span_id.into())
        })
    })
}