1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Utilities for distributed tracing support.
//!
//! Handles extraction of W3C Trace Context headers from HTTP requests
//! and provides functions for trace context propagation.
use axum::http::HeaderMap;
use fraiseql_core::federation::FederationTraceContext;
/// Extract W3C traceparent header from HTTP headers.
///
/// Parses the standard W3C Trace Context header format:
/// `version-trace_id-parent_span_id-trace_flags`
///
/// Example: `00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01`
///
/// # Arguments
///
/// * `headers` - HTTP headers from the request
///
/// # Returns
///
/// `Some(FederationTraceContext)` if a valid traceparent header is present,
/// `None` otherwise (caller should generate a new trace context).
pub fn extract_trace_context(headers: &HeaderMap) -> Option<FederationTraceContext> {
headers
.get("traceparent")
.and_then(|h| h.to_str().ok())
.and_then(FederationTraceContext::from_traceparent)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_valid_traceparent() {
let mut headers = HeaderMap::new();
headers.insert(
"traceparent",
"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01".parse().unwrap(),
);
let ctx = extract_trace_context(&headers);
assert!(ctx.is_some());
let ctx = ctx.unwrap();
assert_eq!(ctx.trace_id, "4bf92f3577b34da6a3ce929d0e0e4736");
assert_eq!(ctx.parent_span_id, "00f067aa0ba902b7");
assert_eq!(ctx.trace_flags, "01");
}
#[test]
fn test_extract_invalid_traceparent() {
let mut headers = HeaderMap::new();
headers.insert("traceparent", "invalid-header".parse().unwrap());
let ctx = extract_trace_context(&headers);
assert!(ctx.is_none());
}
#[test]
fn test_extract_missing_traceparent() {
let headers = HeaderMap::new();
let ctx = extract_trace_context(&headers);
assert!(ctx.is_none());
}
#[test]
fn test_extract_invalid_utf8_traceparent() {
// This would only happen in very unusual circumstances
// The test mainly ensures the code handles the error gracefully
let headers = HeaderMap::new();
let ctx = extract_trace_context(&headers);
assert!(ctx.is_none());
}
}