Skip to main content

forge_runtime/gateway/
tracing.rs

1use uuid::Uuid;
2
3/// Header name for trace ID.
4#[allow(dead_code)]
5pub const TRACE_ID_HEADER: &str = "X-Trace-Id";
6/// Header name for request ID.
7#[allow(dead_code)]
8pub const REQUEST_ID_HEADER: &str = "X-Request-Id";
9/// Header name for parent span ID.
10#[allow(dead_code)]
11pub const SPAN_ID_HEADER: &str = "X-Span-Id";
12
13/// Request tracing state.
14#[derive(Debug, Clone)]
15pub struct TracingState {
16    /// Unique trace ID for distributed tracing.
17    pub trace_id: String,
18    /// Unique request ID.
19    pub request_id: String,
20    /// Parent span ID (if propagated).
21    #[allow(dead_code)]
22    pub parent_span_id: Option<String>,
23    /// When the request started.
24    #[allow(dead_code)]
25    pub start_time: std::time::Instant,
26}
27
28impl TracingState {
29    /// Create a new tracing state.
30    pub fn new() -> Self {
31        Self {
32            trace_id: Uuid::new_v4().to_string(),
33            request_id: Uuid::new_v4().to_string(),
34            parent_span_id: None,
35            start_time: std::time::Instant::now(),
36        }
37    }
38
39    /// Create with an existing trace ID (for propagation).
40    pub fn with_trace_id(trace_id: String) -> Self {
41        Self {
42            trace_id,
43            request_id: Uuid::new_v4().to_string(),
44            parent_span_id: None,
45            start_time: std::time::Instant::now(),
46        }
47    }
48
49    /// Set parent span ID.
50    #[allow(dead_code)]
51    pub fn with_parent_span(mut self, span_id: String) -> Self {
52        self.parent_span_id = Some(span_id);
53        self
54    }
55
56    /// Get elapsed time since request start.
57    #[allow(dead_code)]
58    pub fn elapsed(&self) -> std::time::Duration {
59        self.start_time.elapsed()
60    }
61}
62
63impl Default for TracingState {
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69/// Tracing middleware marker type.
70#[derive(Debug, Clone)]
71#[allow(dead_code)]
72pub struct TracingMiddleware;
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_tracing_state_new() {
80        let state = TracingState::new();
81        assert!(!state.trace_id.is_empty());
82        assert!(!state.request_id.is_empty());
83        assert!(state.parent_span_id.is_none());
84    }
85
86    #[test]
87    fn test_tracing_state_with_trace_id() {
88        let state = TracingState::with_trace_id("trace-123".to_string());
89        assert_eq!(state.trace_id, "trace-123");
90        assert!(!state.request_id.is_empty());
91    }
92
93    #[test]
94    fn test_tracing_state_with_parent_span() {
95        let state = TracingState::new().with_parent_span("span-456".to_string());
96        assert_eq!(state.parent_span_id, Some("span-456".to_string()));
97    }
98
99    #[test]
100    fn test_tracing_state_elapsed() {
101        let state = TracingState::new();
102        std::thread::sleep(std::time::Duration::from_millis(10));
103        let elapsed = state.elapsed();
104        assert!(elapsed.as_millis() >= 10);
105    }
106}