use uuid::Uuid;
#[allow(dead_code)]
pub const TRACE_ID_HEADER: &str = "X-Trace-Id";
#[allow(dead_code)]
pub const REQUEST_ID_HEADER: &str = "X-Request-Id";
#[allow(dead_code)]
pub const SPAN_ID_HEADER: &str = "X-Span-Id";
#[derive(Debug, Clone)]
pub struct TracingState {
pub trace_id: String,
pub request_id: String,
#[allow(dead_code)]
pub parent_span_id: Option<String>,
#[allow(dead_code)]
pub start_time: std::time::Instant,
}
impl TracingState {
pub fn new() -> Self {
Self {
trace_id: Uuid::new_v4().to_string(),
request_id: Uuid::new_v4().to_string(),
parent_span_id: None,
start_time: std::time::Instant::now(),
}
}
pub fn with_trace_id(trace_id: String) -> Self {
Self {
trace_id,
request_id: Uuid::new_v4().to_string(),
parent_span_id: None,
start_time: std::time::Instant::now(),
}
}
#[allow(dead_code)]
pub fn with_parent_span(mut self, span_id: String) -> Self {
self.parent_span_id = Some(span_id);
self
}
#[allow(dead_code)]
pub fn elapsed(&self) -> std::time::Duration {
self.start_time.elapsed()
}
}
impl Default for TracingState {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct TracingMiddleware;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tracing_state_new() {
let state = TracingState::new();
assert!(!state.trace_id.is_empty());
assert!(!state.request_id.is_empty());
assert!(state.parent_span_id.is_none());
}
#[test]
fn test_tracing_state_with_trace_id() {
let state = TracingState::with_trace_id("trace-123".to_string());
assert_eq!(state.trace_id, "trace-123");
assert!(!state.request_id.is_empty());
}
#[test]
fn test_tracing_state_with_parent_span() {
let state = TracingState::new().with_parent_span("span-456".to_string());
assert_eq!(state.parent_span_id, Some("span-456".to_string()));
}
#[test]
fn test_tracing_state_elapsed() {
let state = TracingState::new();
std::thread::sleep(std::time::Duration::from_millis(10));
let elapsed = state.elapsed();
assert!(elapsed.as_millis() >= 10);
}
}