1use crate::{Annotation, Endpoint, SpanId, TraceId};
17use std::collections::HashMap;
18use std::time::{Duration, SystemTime};
19
20#[derive(Debug, Copy, Clone)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26#[cfg_attr(feature = "serde", serde(rename_all = "SCREAMING_SNAKE_CASE"))]
27#[non_exhaustive]
28pub enum Kind {
29 Client,
35
36 Server,
42
43 Producer,
49
50 Consumer,
57}
58
59#[derive(Debug, Clone)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
74pub struct Span {
75 trace_id: TraceId,
76 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
77 name: Option<String>,
78 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
79 parent_id: Option<SpanId>,
80 id: SpanId,
81 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
82 kind: Option<Kind>,
83 #[cfg_attr(
84 feature = "serde",
85 serde(
86 skip_serializing_if = "Option::is_none",
87 with = "crate::opt_time_micros"
88 )
89 )]
90 timestamp: Option<SystemTime>,
91 #[cfg_attr(
92 feature = "serde",
93 serde(
94 skip_serializing_if = "Option::is_none",
95 with = "crate::opt_duration_micros"
96 )
97 )]
98 duration: Option<Duration>,
99 #[cfg_attr(
100 feature = "serde",
101 serde(skip_serializing_if = "is_false", default = "value_false")
102 )]
103 debug: bool,
104 #[cfg_attr(
105 feature = "serde",
106 serde(skip_serializing_if = "is_false", default = "value_false")
107 )]
108 shared: bool,
109 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
110 local_endpoint: Option<Endpoint>,
111 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
112 remote_endpoint: Option<Endpoint>,
113 #[cfg_attr(
114 feature = "serde",
115 serde(skip_serializing_if = "Vec::is_empty", default)
116 )]
117 annotations: Vec<Annotation>,
118 #[cfg_attr(
119 feature = "serde",
120 serde(skip_serializing_if = "HashMap::is_empty", default)
121 )]
122 tags: HashMap<String, String>,
123}
124
125#[cfg(feature = "serde")]
126#[inline]
127fn is_false(v: &bool) -> bool {
128 !*v
129}
130
131#[cfg(feature = "serde")]
132#[inline]
133fn value_false() -> bool {
134 false
135}
136
137impl Span {
138 #[inline]
140 pub fn builder() -> Builder {
141 Builder {
142 trace_id: None,
143 name: None,
144 parent_id: None,
145 id: None,
146 kind: None,
147 timestamp: None,
148 duration: None,
149 debug: false,
150 shared: false,
151 local_endpoint: None,
152 remote_endpoint: None,
153 annotations: vec![],
154 tags: HashMap::new(),
155 }
156 }
157
158 #[inline]
160 pub fn trace_id(&self) -> TraceId {
161 self.trace_id
162 }
163
164 #[inline]
171 pub fn name(&self) -> Option<&str> {
172 self.name.as_deref()
173 }
174
175 #[inline]
177 pub fn parent_id(&self) -> Option<SpanId> {
178 self.parent_id
179 }
180
181 #[inline]
183 pub fn id(&self) -> SpanId {
184 self.id
185 }
186
187 #[inline]
191 pub fn kind(&self) -> Option<Kind> {
192 self.kind
193 }
194
195 #[inline]
197 pub fn timestamp(&self) -> Option<SystemTime> {
198 self.timestamp
199 }
200
201 #[inline]
206 pub fn duration(&self) -> Option<Duration> {
207 self.duration
208 }
209
210 #[inline]
214 pub fn debug(&self) -> bool {
215 self.debug
216 }
217
218 #[inline]
220 pub fn shared(&self) -> bool {
221 self.shared
222 }
223
224 #[inline]
229 pub fn local_endpoint(&self) -> Option<&Endpoint> {
230 self.local_endpoint.as_ref()
231 }
232
233 #[inline]
235 pub fn remote_endpoint(&self) -> Option<&Endpoint> {
236 self.remote_endpoint.as_ref()
237 }
238
239 #[inline]
241 pub fn annotations(&self) -> &[Annotation] {
242 &self.annotations
243 }
244
245 #[inline]
247 pub fn tags(&self) -> &HashMap<String, String> {
248 &self.tags
249 }
250}
251
252pub struct Builder {
254 trace_id: Option<TraceId>,
255 name: Option<String>,
256 parent_id: Option<SpanId>,
257 id: Option<SpanId>,
258 kind: Option<Kind>,
259 timestamp: Option<SystemTime>,
260 duration: Option<Duration>,
261 debug: bool,
262 shared: bool,
263 local_endpoint: Option<Endpoint>,
264 remote_endpoint: Option<Endpoint>,
265 annotations: Vec<Annotation>,
266 tags: HashMap<String, String>,
267}
268
269impl From<Span> for Builder {
270 #[inline]
271 fn from(s: Span) -> Builder {
272 Builder {
273 trace_id: Some(s.trace_id),
274 name: s.name,
275 parent_id: s.parent_id,
276 id: Some(s.id),
277 kind: s.kind,
278 timestamp: s.timestamp,
279 duration: s.duration,
280 debug: s.debug,
281 shared: s.shared,
282 local_endpoint: s.local_endpoint,
283 remote_endpoint: s.remote_endpoint,
284 annotations: s.annotations,
285 tags: s.tags,
286 }
287 }
288}
289
290impl Builder {
291 #[inline]
293 pub fn trace_id(&mut self, trace_id: TraceId) -> &mut Builder {
294 self.trace_id = Some(trace_id);
295 self
296 }
297
298 #[inline]
302 pub fn name(&mut self, name: &str) -> &mut Builder {
303 self.name = Some(name.to_lowercase());
304 self
305 }
306
307 #[inline]
311 pub fn parent_id(&mut self, parent_id: SpanId) -> &mut Builder {
312 self.parent_id = Some(parent_id);
313 self
314 }
315
316 #[inline]
318 pub fn id(&mut self, id: SpanId) -> &mut Builder {
319 self.id = Some(id);
320 self
321 }
322
323 #[inline]
327 pub fn kind(&mut self, kind: Kind) -> &mut Builder {
328 self.kind = Some(kind);
329 self
330 }
331
332 #[inline]
336 pub fn timestamp(&mut self, timestamp: SystemTime) -> &mut Builder {
337 self.timestamp = Some(timestamp);
338 self
339 }
340
341 #[inline]
345 pub fn duration(&mut self, duration: Duration) -> &mut Builder {
346 self.duration = Some(duration);
347 self
348 }
349
350 #[inline]
354 pub fn debug(&mut self, debug: bool) -> &mut Builder {
355 self.debug = debug;
356 self
357 }
358
359 #[inline]
363 pub fn shared(&mut self, shared: bool) -> &mut Builder {
364 self.shared = shared;
365 self
366 }
367
368 #[inline]
372 pub fn local_endpoint(&mut self, local_endpoint: Endpoint) -> &mut Builder {
373 self.local_endpoint = Some(local_endpoint);
374 self
375 }
376
377 #[inline]
381 pub fn remote_endpoint(&mut self, remote_endpoint: Endpoint) -> &mut Builder {
382 self.remote_endpoint = Some(remote_endpoint);
383 self
384 }
385
386 #[inline]
388 pub fn annotation(&mut self, annotation: Annotation) -> &mut Builder {
389 self.annotations.push(annotation);
390 self
391 }
392
393 #[inline]
395 pub fn annotations<I>(&mut self, annotations: I) -> &mut Builder
396 where
397 I: IntoIterator<Item = Annotation>,
398 {
399 self.annotations.extend(annotations);
400 self
401 }
402
403 #[inline]
405 pub fn tag(&mut self, key: &str, value: &str) -> &mut Builder {
406 self.tags.insert(key.to_string(), value.to_string());
407 self
408 }
409
410 #[inline]
412 pub fn tags<I>(&mut self, tags: I) -> &mut Builder
413 where
414 I: IntoIterator<Item = (String, String)>,
415 {
416 self.tags.extend(tags);
417 self
418 }
419
420 #[inline]
426 pub fn build(&self) -> Span {
427 Span {
428 trace_id: self.trace_id.expect("trace ID not set"),
429 name: self.name.clone(),
430 id: self.id.expect("span ID not set"),
431 kind: self.kind,
432 parent_id: self.parent_id,
433 timestamp: self.timestamp,
434 duration: self.duration,
435 debug: self.debug,
436 shared: self.shared,
437 local_endpoint: self.local_endpoint.clone(),
438 remote_endpoint: self.remote_endpoint.clone(),
439 annotations: self.annotations.clone(),
440 tags: self.tags.clone(),
441 }
442 }
443}