#![allow(dead_code)]
use http::HeaderMap;
use uuid::Uuid;
#[derive(Clone, Debug)]
pub struct UniKey {
pub agg_id: Uuid,
pub com_id: [u8; 16],
pub span_id: [u8; 8],
pub trace_flags: u8,
}
fn hex_char_to_byte(c: u8) -> Option<u8> {
match c {
b'0'..=b'9' => Some(c - b'0'),
b'a'..=b'f' => Some(c - b'a' + 10),
b'A'..=b'F' => Some(c - b'A' + 10),
_ => None,
}
}
fn parse_hex<const N: usize>(hex_str: &str) -> Option<[u8; N]> {
let bytes: Vec<u8> = hex_str
.as_bytes()
.chunks(2)
.map(|chunk| {
let high = hex_char_to_byte(chunk[0])?;
let low = hex_char_to_byte(chunk[1])?;
Some(high << 4 | low)
})
.collect::<Option<Vec<_>>>()?;
bytes.try_into().ok()
}
fn parse_traceparent(tp: &str) -> Option<([u8; 16], [u8; 8], u8)> {
let parts: Vec<&str> = tp.split('-').collect();
if parts.len() < 4 {
return None;
}
let version = u8::from_str_radix(parts[0], 16).ok()?;
if version > 254 || version == 0 && parts.len() != 4 {
return None;
}
let trace_id = parse_hex::<16>(parts[1])?;
let span_id = parse_hex::<8>(parts[2])?;
let opts = u8::from_str_radix(parts[3], 16).ok()?;
let trace_flags = opts & 1;
Some((trace_id, span_id, trace_flags))
}
pub(crate) fn extract_key(headers: &HeaderMap) -> Option<UniKey> {
headers
.get("traceparent")
.and_then(|v| v.to_str().ok())
.and_then(|tp| parse_traceparent(tp))
.and_then(|(com_id, span_id, trace_flags)| {
let agg_id = headers
.get("x-agg-id")
.and_then(|v| v.to_str().ok())
.and_then(|s| Uuid::parse_str(s).ok())
.unwrap_or(Uuid::new_v4());
Some(UniKey {
agg_id,
com_id,
span_id,
trace_flags,
})
})
}
pub struct JsonFormat;
pub struct RkyvFormat;