tracing_honeycomb/
trace_id.rs

1use std::borrow::Cow;
2use std::convert::{Infallible, TryFrom};
3use std::fmt::{self, Display};
4use std::str::FromStr;
5
6use uuid::Uuid;
7
8/// A Honeycomb Trace ID.
9///
10/// Uniquely identifies a single distributed trace.
11///
12/// Does no parsing on string input values. Can be generated new from a UUID V4.
13///
14/// `Display` and `FromStr` are guaranteed to round-trip.
15#[derive(Clone, Debug, Eq, Hash, PartialEq)]
16pub struct TraceId(pub(crate) String);
17
18impl TraceId {
19    /// Metadata field name associated with this `TraceId` values.
20    pub fn meta_field_name() -> &'static str {
21        "trace-id"
22    }
23
24    /// Generate a new `TraceId` from a UUID V4.
25    pub fn new() -> Self {
26        Uuid::new_v4().into()
27    }
28
29    #[deprecated(since = "0.2.0", note = "Use `TraceId::new()` instead.")]
30    /// Generate a new `TraceId` from a UUID V4.
31    ///
32    /// Prefer `TraceId::new()`.
33    pub fn generate() -> Self {
34        TraceId::new()
35    }
36}
37
38impl Default for TraceId {
39    fn default() -> Self {
40        TraceId::new()
41    }
42}
43
44impl AsRef<[u8]> for TraceId {
45    fn as_ref(&self) -> &[u8] {
46        self.0.as_bytes()
47    }
48}
49
50impl From<TraceId> for String {
51    fn from(trace_id: TraceId) -> String {
52        format!("{}", trace_id)
53    }
54}
55
56impl TryFrom<TraceId> for u128 {
57    type Error = uuid::Error;
58
59    fn try_from(trace_id: TraceId) -> Result<u128, Self::Error> {
60        Ok(Uuid::parse_str(&trace_id.0)?.as_u128())
61    }
62}
63
64impl TryFrom<TraceId> for Uuid {
65    type Error = uuid::Error;
66
67    fn try_from(trace_id: TraceId) -> Result<Uuid, Self::Error> {
68        Uuid::parse_str(&trace_id.0)
69    }
70}
71
72impl From<Cow<'_, &str>> for TraceId {
73    fn from(s: Cow<'_, &str>) -> Self {
74        Self(s.to_string())
75    }
76}
77
78impl From<&str> for TraceId {
79    fn from(s: &str) -> Self {
80        Self(s.to_string())
81    }
82}
83
84impl From<String> for TraceId {
85    fn from(s: String) -> Self {
86        Self(s)
87    }
88}
89
90impl From<Uuid> for TraceId {
91    fn from(uuid: Uuid) -> Self {
92        let buf = &mut [0; 36];
93        let id = uuid.to_simple().encode_lower(buf);
94        Self(id.to_owned())
95    }
96}
97
98impl From<u128> for TraceId {
99    fn from(u: u128) -> Self {
100        Uuid::from_u128(u).into()
101    }
102}
103
104impl FromStr for TraceId {
105    type Err = Infallible;
106
107    /// Is actually infalliable.
108    fn from_str(s: &str) -> Result<Self, Self::Err> {
109        Ok(Self(s.to_owned()))
110    }
111}
112
113impl Display for TraceId {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        write!(f, "{}", self.0)
116    }
117}
118
119#[cfg(test)]
120mod test {
121    use super::*;
122    use proptest::prelude::*;
123
124    proptest! {
125        #[test]
126        #[test]
127        fn trace_id_round_trip_u128(u in 1u128..) {
128            let trace_id: TraceId = u.into();
129            let s = trace_id.to_string();
130            let res = TraceId::from_str(&s);
131            assert_eq!(Ok(trace_id), res);
132        }
133    }
134
135    #[test]
136    fn trace_id_round_trip_str() {
137        let trace_id: TraceId = "a string".into();
138        let s = trace_id.to_string();
139        let res = TraceId::from_str(&s);
140        assert_eq!(Ok(trace_id), res);
141    }
142
143    #[test]
144    fn trace_id_round_trip_empty_str() {
145        let trace_id: TraceId = "".into();
146        let s = trace_id.to_string();
147        let res = TraceId::from_str(&s);
148        assert_eq!(Ok(trace_id), res);
149    }
150}