1use std::{collections::HashMap, time::SystemTime};
2
3use tracing::{field::Visit, span::Attributes, Metadata};
4
5pub trait Resettable {
6 fn reset(&mut self);
7}
8
9#[derive(Debug, Clone, Copy)]
10pub enum TraceKind {
11 Client,
12 Server,
13}
14impl Default for TraceKind {
15 fn default() -> Self {
16 Self::Server
17 }
18}
19
20#[derive(Debug, Clone, Copy)]
21pub enum SpanStatus {
22 Ok,
23 Error,
24}
25impl Default for SpanStatus {
26 fn default() -> Self {
27 Self::Ok
28 }
29}
30
31#[derive(Debug, Clone)]
32pub struct ActionSpan {
33 pub ref_count: usize,
34
35 pub trace_id: [u8; 16],
38
39 pub span_id: [u8; 8],
42
43 pub trace_state: String,
47
48 pub parent_span_id: Option<[u8; 8]>,
51
52 pub metadata: Option<&'static Metadata<'static>>,
54
55 pub kind: TraceKind,
59
60 pub start: SystemTime,
67
68 pub end: SystemTime,
75
76 pub attributes: HashMap<&'static str, AttributeValue>,
83
84 pub events: Vec<ActionEvent>,
86
87 pub status: SpanStatus,
88}
89
90impl Default for ActionSpan {
91 fn default() -> Self {
92 Self {
93 ref_count: 0,
94 trace_id: Default::default(),
95 span_id: Default::default(),
96 trace_state: Default::default(),
97 parent_span_id: Default::default(),
98 metadata: Default::default(),
99 kind: Default::default(),
100 start: SystemTime::now(),
101 end: SystemTime::now(),
102 attributes: Default::default(),
103 events: Default::default(),
104 status: Default::default(),
105 }
106 }
107}
108
109impl Resettable for ActionSpan {
110 fn reset(&mut self) {
111 self.ref_count = 0;
112 self.trace_id.fill(0);
113 self.span_id.fill(0);
114 self.trace_state = Default::default();
115 self.parent_span_id = None;
116 self.metadata = Default::default();
117 self.kind = Default::default();
118 self.attributes.clear();
119 self.events.clear();
120 self.status = Default::default();
121 }
122}
123
124impl ActionSpan {
125 pub fn start_root(&mut self, attributes: &Attributes) {
126 self.trace_id = rand::random();
127 self.span_id = rand::random();
128
129 self.start = SystemTime::now();
130
131 self.attach_attributes(attributes);
132 }
133
134 pub fn start_child(
135 &mut self,
136 attributes: &Attributes,
137 trace_id: &[u8; 16],
138 parent_span_id: &[u8; 8],
139 ) {
140 self.trace_id.copy_from_slice(trace_id);
141 self.span_id = rand::random();
142 self.parent_span_id = Some(*parent_span_id); self.start = SystemTime::now();
145
146 self.attach_attributes(attributes);
147 }
148
149 pub fn end(&mut self) {
150 self.end = SystemTime::now();
151 }
152
153 fn attach_attributes(&mut self, attributes: &Attributes) {
154 let metadata = attributes.metadata();
155 self.metadata = Some(metadata);
156 attributes.values().record(self)
157 }
158}
159
160#[derive(Debug, Clone)]
161pub struct ActionEvent {
162 pub metadata: &'static Metadata<'static>,
163 pub attributes: HashMap<&'static str, AttributeValue>,
164 pub timestamp: SystemTime,
165}
166
167impl<'a> From<&'a tracing::Event<'a>> for ActionEvent {
168 fn from(event: &'a tracing::Event<'a>) -> Self {
169 let mut selff = Self {
170 metadata: event.metadata(),
171 attributes: HashMap::new(),
172 timestamp: SystemTime::now(),
173 };
174 event.record(&mut selff);
175 selff
176 }
177}
178
179#[derive(Debug, Clone)]
180pub enum AttributeValue {
181 String(String),
182 F64(f64),
183 I64(i64),
184 U64(u64),
185 I128(i128),
186 U128(u128),
187 Bool(bool),
188 Error(String),
189}
190
191impl Visit for ActionSpan {
192 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
193 self.attributes
194 .insert(field.name(), AttributeValue::String(format!("{value:?}")));
195 }
196
197 fn record_f64(&mut self, field: &tracing::field::Field, value: f64) {
198 self.attributes
199 .insert(field.name(), AttributeValue::F64(value));
200 }
201
202 fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
203 self.attributes
204 .insert(field.name(), AttributeValue::I64(value));
205 }
206
207 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
208 self.attributes
209 .insert(field.name(), AttributeValue::U64(value));
210 }
211
212 fn record_i128(&mut self, field: &tracing::field::Field, value: i128) {
213 self.attributes
214 .insert(field.name(), AttributeValue::I128(value));
215 }
216
217 fn record_u128(&mut self, field: &tracing::field::Field, value: u128) {
218 self.attributes
219 .insert(field.name(), AttributeValue::U128(value));
220 }
221
222 fn record_bool(&mut self, field: &tracing::field::Field, value: bool) {
223 self.attributes
224 .insert(field.name(), AttributeValue::Bool(value));
225 }
226
227 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
228 self.attributes
229 .insert(field.name(), AttributeValue::String(value.to_owned()));
230 }
231
232 fn record_error(
233 &mut self,
234 field: &tracing::field::Field,
235 value: &(dyn std::error::Error + 'static),
236 ) {
237 self.status = SpanStatus::Error;
239 self.attributes
240 .insert(field.name(), AttributeValue::Error(format!("{value:?}")));
241 }
242}
243
244impl Visit for ActionEvent {
245 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
246 self.attributes
247 .insert(field.name(), AttributeValue::String(format!("{value:?}")));
248 }
249
250 fn record_f64(&mut self, field: &tracing::field::Field, value: f64) {
251 self.attributes
252 .insert(field.name(), AttributeValue::F64(value));
253 }
254
255 fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
256 self.attributes
257 .insert(field.name(), AttributeValue::I64(value));
258 }
259
260 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
261 self.attributes
262 .insert(field.name(), AttributeValue::U64(value));
263 }
264
265 fn record_i128(&mut self, field: &tracing::field::Field, value: i128) {
266 self.attributes
267 .insert(field.name(), AttributeValue::I128(value));
268 }
269
270 fn record_u128(&mut self, field: &tracing::field::Field, value: u128) {
271 self.attributes
272 .insert(field.name(), AttributeValue::U128(value));
273 }
274
275 fn record_bool(&mut self, field: &tracing::field::Field, value: bool) {
276 self.attributes
277 .insert(field.name(), AttributeValue::Bool(value));
278 }
279
280 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
281 self.attributes
282 .insert(field.name(), AttributeValue::String(value.to_owned()));
283 }
284
285 fn record_error(
286 &mut self,
287 field: &tracing::field::Field,
288 value: &(dyn std::error::Error + 'static),
289 ) {
290 self.attributes
291 .insert(field.name(), AttributeValue::Error(format!("{value:?}")));
292 }
293}