Skip to main content

systemprompt_identifiers/
trace.rs

1//! Distributed-tracing identifier with a `system` constant.
2//!
3//! A [`TraceId`] is whatever the caller sent in `x-trace-id`, else the trace id
4//! of an inbound W3C `traceparent`, else a generated UUID. [`TraceId::w3c_hex`]
5//! is the 32-hex form an outbound `traceparent` needs: the id itself when it is
6//! already W3C, the UUID's hex digits when it is a UUID, and `None` for any
7//! other shape (such as `system`), which is then not propagated. An outbound
8//! `traceparent` carries the caller's sampled flag when the trace arrived in a
9//! valid inbound `traceparent`, and marks the trace sampled only when this
10//! process originated it.
11//!
12//! Copyright (c) systemprompt.io — Business Source License 1.1.
13//! See <https://systemprompt.io> for licensing details.
14
15crate::define_id!(TraceId, generate, schema);
16
17const W3C_TRACE_ID_LEN: usize = 32;
18const W3C_SPAN_ID_LEN: usize = 16;
19const SAMPLED_FLAG: u8 = 0x01;
20
21impl TraceId {
22    pub fn system() -> Self {
23        Self("system".to_owned())
24    }
25
26    #[must_use]
27    pub fn from_traceparent(header: &str) -> Option<Self> {
28        let mut parts = header.trim().split('-');
29        let version = parts.next()?;
30        let trace_id = parts.next()?;
31        let parent_id = parts.next()?;
32        let flags = parts.next()?;
33        if version.len() != 2 || !is_lower_hex(version) || version == "ff" {
34            return None;
35        }
36        if version == "00" && parts.next().is_some() {
37            return None;
38        }
39        if trace_id.len() != W3C_TRACE_ID_LEN || !is_lower_hex(trace_id) || is_all_zero(trace_id) {
40            return None;
41        }
42        if parent_id.len() != W3C_SPAN_ID_LEN || !is_lower_hex(parent_id) || is_all_zero(parent_id)
43        {
44            return None;
45        }
46        if flags.len() != 2 || !is_lower_hex(flags) {
47            return None;
48        }
49        Some(Self(trace_id.to_owned()))
50    }
51
52    #[must_use]
53    pub fn w3c_hex(&self) -> Option<String> {
54        if self.0.len() == W3C_TRACE_ID_LEN && is_lower_hex(&self.0) && !is_all_zero(&self.0) {
55            return Some(self.0.clone());
56        }
57        let uuid = uuid::Uuid::parse_str(&self.0).ok()?;
58        (!uuid.is_nil()).then(|| uuid.simple().to_string())
59    }
60
61    #[must_use]
62    pub fn sampled_in_traceparent(&self, header: &str) -> Option<bool> {
63        let carried = Self::from_traceparent(header)?;
64        if carried.0 != self.w3c_hex()? {
65            return None;
66        }
67        let flags = header.trim().split('-').nth(3)?;
68        let flags = u8::from_str_radix(flags, 16).ok()?;
69        Some(flags & SAMPLED_FLAG != 0)
70    }
71
72    #[must_use]
73    pub fn traceparent(&self) -> Option<String> {
74        self.traceparent_sampled(true)
75    }
76
77    #[must_use]
78    pub fn traceparent_sampled(&self, sampled: bool) -> Option<String> {
79        let trace_id = self.w3c_hex()?;
80        let span = uuid::Uuid::new_v4().simple().to_string();
81        let span_id = &span[..W3C_SPAN_ID_LEN];
82        let flags = if sampled { "01" } else { "00" };
83        Some(format!("00-{trace_id}-{span_id}-{flags}"))
84    }
85}
86
87fn is_lower_hex(value: &str) -> bool {
88    value
89        .bytes()
90        .all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))
91}
92
93fn is_all_zero(value: &str) -> bool {
94    value.bytes().all(|b| b == b'0')
95}