tracing_honeycomb/
trace_id.rs1use std::borrow::Cow;
2use std::convert::{Infallible, TryFrom};
3use std::fmt::{self, Display};
4use std::str::FromStr;
5
6use uuid::Uuid;
7
8#[derive(Clone, Debug, Eq, Hash, PartialEq)]
16pub struct TraceId(pub(crate) String);
17
18impl TraceId {
19 pub fn meta_field_name() -> &'static str {
21 "trace-id"
22 }
23
24 pub fn new() -> Self {
26 Uuid::new_v4().into()
27 }
28
29 #[deprecated(since = "0.2.0", note = "Use `TraceId::new()` instead.")]
30 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 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}