use celers_core::{CelersError, Result};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct TraceContext {
pub trace_id: String,
pub span_id: String,
#[serde(default = "default_trace_flags")]
pub trace_flags: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub trace_state: Option<String>,
}
pub(crate) fn default_trace_flags() -> String {
"01".to_string()
}
impl TraceContext {
pub fn new(trace_id: impl Into<String>, span_id: impl Into<String>) -> Self {
Self {
trace_id: trace_id.into(),
span_id: span_id.into(),
trace_flags: default_trace_flags(),
trace_state: None,
}
}
pub fn from_traceparent(traceparent: &str) -> Result<Self> {
let parts: Vec<&str> = traceparent.split('-').collect();
if parts.len() != 4 || parts[0] != "00" {
return Err(CelersError::Other(format!(
"Invalid traceparent format: {}",
traceparent
)));
}
Ok(Self {
trace_id: parts[1].to_string(),
span_id: parts[2].to_string(),
trace_flags: parts[3].to_string(),
trace_state: None,
})
}
pub fn to_traceparent(&self) -> String {
format!("00-{}-{}-{}", self.trace_id, self.span_id, self.trace_flags)
}
pub fn is_sampled(&self) -> bool {
self.trace_flags == "01"
}
pub fn create_child_span(&self) -> Self {
let span_id = format!(
"{:016x}",
uuid::Uuid::new_v4().as_u128() & 0xFFFFFFFFFFFFFFFF
);
Self {
trace_id: self.trace_id.clone(),
span_id,
trace_flags: self.trace_flags.clone(),
trace_state: self.trace_state.clone(),
}
}
}