1use std::{fmt, sync::Arc};
2
3macro_rules! string_id {
4 ($name:ident) => {
5 #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
6 pub struct $name(Arc<str>);
7
8 impl $name {
9 pub fn new(value: impl Into<Arc<str>>) -> Self {
10 Self(value.into())
11 }
12
13 pub fn as_str(&self) -> &str {
14 &self.0
15 }
16 }
17
18 impl From<&str> for $name {
19 fn from(value: &str) -> Self {
20 Self::new(value)
21 }
22 }
23
24 impl From<String> for $name {
25 fn from(value: String) -> Self {
26 Self::new(value)
27 }
28 }
29
30 impl fmt::Display for $name {
31 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
32 formatter.write_str(&self.0)
33 }
34 }
35 };
36}
37
38string_id!(ApplicationId);
39string_id!(ModuleId);
40string_id!(ServiceId);
41string_id!(OperationId);
42
43#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
44pub struct TraceId(u128);
45
46impl TraceId {
47 pub const fn from_u128(value: u128) -> Self {
48 Self(value)
49 }
50
51 pub const fn as_u128(self) -> u128 {
52 self.0
53 }
54}
55
56impl fmt::Display for TraceId {
57 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(formatter, "{:032x}", self.0)
59 }
60}
61
62#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
63pub struct SpanId(u64);
64
65impl SpanId {
66 pub const fn from_u64(value: u64) -> Self {
67 Self(value)
68 }
69
70 pub const fn as_u64(self) -> u64 {
71 self.0
72 }
73}
74
75impl fmt::Display for SpanId {
76 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(formatter, "{:016x}", self.0)
78 }
79}
80
81#[derive(Clone, Debug, Eq, PartialEq)]
86pub struct CallContext {
87 application: ApplicationId,
88 module: ModuleId,
89 service: ServiceId,
90 operation: OperationId,
91 trace_id: TraceId,
92 span_id: SpanId,
93}
94
95impl CallContext {
96 pub fn new(
97 application: ApplicationId,
98 module: ModuleId,
99 service: ServiceId,
100 operation: OperationId,
101 trace_id: TraceId,
102 span_id: SpanId,
103 ) -> Self {
104 Self {
105 application,
106 module,
107 service,
108 operation,
109 trace_id,
110 span_id,
111 }
112 }
113
114 pub fn application(&self) -> &ApplicationId {
115 &self.application
116 }
117
118 pub fn module(&self) -> &ModuleId {
119 &self.module
120 }
121
122 pub fn service(&self) -> &ServiceId {
123 &self.service
124 }
125
126 pub fn operation(&self) -> &OperationId {
127 &self.operation
128 }
129
130 pub const fn trace_id(&self) -> TraceId {
131 self.trace_id
132 }
133
134 pub const fn span_id(&self) -> SpanId {
135 self.span_id
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn identifiers_have_stable_display_forms() {
145 assert_eq!(TraceId::from_u128(42).to_string().len(), 32);
146 assert_eq!(SpanId::from_u64(42).to_string().len(), 16);
147 assert_eq!(ServiceId::from("orders").to_string(), "orders");
148 }
149}