Skip to main content

emit/
span.rs

1/*!
2The [`Span`] type.
3*/
4
5/*
6Parts of this file are adapted from other libraries:
7
8uuid:
9https://github.com/uuid-rs/uuid/blob/main/src/parser.rs
10Licensed under Apache 2.0
11*/
12
13use emit_core::{
14    and::And,
15    clock::Clock,
16    ctxt::Ctxt,
17    emitter::Emitter,
18    empty::Empty,
19    event::{Event, ToEvent},
20    extent::{Extent, ToExtent},
21    filter::Filter,
22    path::Path,
23    props::{ErasedProps, Props},
24    rng::Rng,
25    runtime::Runtime,
26    str::{Str, ToStr},
27    template::{self, Template},
28    timestamp::Timestamp,
29    value::{FromValue, ToValue, Value},
30    well_known::{
31        KEY_EVT_KIND, KEY_SPAN_ID, KEY_SPAN_KIND, KEY_SPAN_NAME, KEY_SPAN_PARENT, KEY_TRACE_ID,
32        SPAN_KIND_CLIENT, SPAN_KIND_CONSUMER, SPAN_KIND_INTERNAL, SPAN_KIND_PRODUCER,
33        SPAN_KIND_SERVER,
34    },
35};
36
37#[cfg(feature = "alloc")]
38use emit_core::well_known::KEY_SPAN_LINKS;
39
40use crate::{Frame, Timer, kind::Kind, level::Level};
41use core::{
42    fmt, mem,
43    num::{NonZeroU64, NonZeroU128},
44    ops::ControlFlow,
45    str::{self, FromStr},
46};
47
48pub use self::completion::Completion;
49
50/**
51A [W3C Trace Id](https://www.w3.org/TR/trace-context/#trace-id).
52*/
53#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
54pub struct TraceId(NonZeroU128);
55
56impl fmt::Debug for TraceId {
57    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58        fmt::Debug::fmt(str::from_utf8(&self.to_hex()).unwrap(), f)
59    }
60}
61
62impl fmt::Display for TraceId {
63    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64        f.write_str(str::from_utf8(&self.to_hex()).unwrap())
65    }
66}
67
68impl FromStr for TraceId {
69    type Err = ParseIdError;
70
71    fn from_str(s: &str) -> Result<Self, Self::Err> {
72        Self::try_from_hex_slice(s.as_bytes())
73    }
74}
75
76impl ToValue for TraceId {
77    fn to_value(&self) -> Value<'_> {
78        Value::capture_display(self)
79    }
80}
81
82impl<'v> FromValue<'v> for TraceId {
83    fn from_value(value: Value<'v>) -> Option<Self> {
84        value
85            .downcast_ref::<TraceId>()
86            .copied()
87            .or_else(|| u128::from_value(value.by_ref()).and_then(TraceId::from_u128))
88            .or_else(|| TraceId::try_from_hex(value).ok())
89    }
90}
91
92#[cfg(feature = "sval")]
93impl sval::Value for TraceId {
94    fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
95        sval::stream_display(stream, self)
96    }
97}
98
99#[cfg(feature = "serde")]
100impl serde::Serialize for TraceId {
101    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
102        serializer.collect_str(self)
103    }
104}
105
106impl TraceId {
107    /**
108    Create a random trace id.
109
110    This method will return `None` if the given [`Rng`] fails to produce a random value, or if it produces the value `0`.
111    */
112    pub fn random<R: Rng>(rng: R) -> Option<Self> {
113        Some(TraceId::new(NonZeroU128::new(rng.gen_u128()?)?))
114    }
115
116    /**
117    Create a trace id from a non-zero integer.
118    */
119    pub const fn new(v: NonZeroU128) -> Self {
120        TraceId(v)
121    }
122
123    /**
124    Try create a trace id from an integer.
125
126    This method will return `None` if `v` is `0`.
127    */
128    pub fn from_u128(v: u128) -> Option<Self> {
129        Some(TraceId(NonZeroU128::new(v)?))
130    }
131
132    /**
133    Get the value of the trace id as an integer.
134    */
135    pub const fn to_u128(&self) -> u128 {
136        self.0.get()
137    }
138
139    /**
140    Get a trace id from a 16 byte big-endian array.
141    */
142    pub fn from_bytes(v: [u8; 16]) -> Option<Self> {
143        Self::from_u128(u128::from_be_bytes(v))
144    }
145
146    /**
147    Convert the trace id into a 16 byte big-endian array.
148    */
149    pub fn to_bytes(&self) -> [u8; 16] {
150        self.0.get().to_be_bytes()
151    }
152
153    /**
154    Convert the trace id into a 32 byte ASCII-compatible hex string, like `4bf92f3577b34da6a3ce929d0e0e4736`.
155    */
156    pub fn to_hex(&self) -> [u8; 32] {
157        let mut dst = [0; 32];
158        let src: [u8; 16] = self.0.get().to_be_bytes();
159
160        for i in 0..src.len() {
161            let b = src[i];
162
163            dst[i * 2] = HEX_ENCODE_TABLE[(b >> 4) as usize];
164            dst[i * 2 + 1] = HEX_ENCODE_TABLE[(b & 0x0f) as usize];
165        }
166
167        dst
168    }
169
170    /**
171    Try parse a slice of ASCII hex bytes into a trace id.
172
173    If `hex` is not a 32 byte array of valid hex characters (`[a-fA-F0-9]`) then this method will fail.
174    */
175    pub fn try_from_hex_slice(hex: &[u8]) -> Result<Self, ParseIdError> {
176        let hex: &[u8; 32] = hex.try_into().map_err(|_| ParseIdError {})?;
177
178        let mut dst = [0; 16];
179
180        let mut i = 0;
181        while i < 16 {
182            // Convert a two-char hex value (like `A8`)
183            // into a byte (like `10101000`)
184            let h1 = HEX_DECODE_TABLE[hex[i * 2] as usize];
185            let h2 = HEX_DECODE_TABLE[hex[i * 2 + 1] as usize];
186
187            // We use `0xff` as a sentinel value to indicate
188            // an invalid hex character sequence (like the letter `G`)
189            if h1 | h2 == 0xff {
190                return Err(ParseIdError {});
191            }
192
193            // The upper nibble needs to be shifted into position
194            // to produce the final byte value
195            dst[i] = SHL4_TABLE[h1 as usize] | h2;
196            i += 1;
197        }
198
199        Ok(TraceId::new(
200            NonZeroU128::new(u128::from_be_bytes(dst)).ok_or_else(|| ParseIdError {})?,
201        ))
202    }
203
204    /**
205    Try parse ASCII hex characters into a trace id.
206
207    If `hex` is not exactly 32 valid hex characters (`[a-fA-F0-9]`) then this method will fail.
208    */
209    pub fn try_from_hex(hex: impl fmt::Display) -> Result<Self, ParseIdError> {
210        let mut buf = crate::buf::Buffer::<32>::new();
211
212        Self::try_from_hex_slice(buf.buffer(hex).map_err(|_| ParseIdError {})?)
213    }
214}
215
216/**
217A [W3C Span Id](https://www.w3.org/TR/trace-context/#parent-id).
218*/
219#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
220pub struct SpanId(NonZeroU64);
221
222impl fmt::Debug for SpanId {
223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224        fmt::Debug::fmt(str::from_utf8(&self.to_hex()).unwrap(), f)
225    }
226}
227
228impl fmt::Display for SpanId {
229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230        f.write_str(str::from_utf8(&self.to_hex()).unwrap())
231    }
232}
233
234impl FromStr for SpanId {
235    type Err = ParseIdError;
236
237    fn from_str(s: &str) -> Result<Self, Self::Err> {
238        Self::try_from_hex_slice(s.as_bytes())
239    }
240}
241
242impl ToValue for SpanId {
243    fn to_value(&self) -> Value<'_> {
244        Value::capture_display(self)
245    }
246}
247
248impl<'v> FromValue<'v> for SpanId {
249    fn from_value(value: Value<'v>) -> Option<Self> {
250        value
251            .downcast_ref::<SpanId>()
252            .copied()
253            .or_else(|| u64::from_value(value.by_ref()).and_then(SpanId::from_u64))
254            .or_else(|| SpanId::try_from_hex(value).ok())
255    }
256}
257
258#[cfg(feature = "sval")]
259impl sval::Value for SpanId {
260    fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
261        sval::stream_display(stream, self)
262    }
263}
264
265#[cfg(feature = "serde")]
266impl serde::Serialize for SpanId {
267    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
268        serializer.collect_str(self)
269    }
270}
271
272impl SpanId {
273    /**
274    Create a new random span id.
275
276    This method will return `None` if the given [`Rng`] fails to produce a random value, or if it produces the value `0`.
277    */
278    pub fn random<R: Rng>(rng: R) -> Option<Self> {
279        Some(SpanId::new(NonZeroU64::new(rng.gen_u64()?)?))
280    }
281
282    /**
283    Create a span id from a non-zero integer.
284    */
285    pub const fn new(v: NonZeroU64) -> Self {
286        SpanId(v)
287    }
288
289    /**
290    Create a span id from an integer.
291
292    This method will return `None` if `v` is `0`.
293    */
294    pub fn from_u64(v: u64) -> Option<Self> {
295        Some(SpanId(NonZeroU64::new(v)?))
296    }
297
298    /**
299    Get the value of the span id as an integer.
300    */
301    pub const fn to_u64(&self) -> u64 {
302        self.0.get()
303    }
304
305    /**
306    Get a span id from an 8 byte big-endian array.
307    */
308    pub fn from_bytes(v: [u8; 8]) -> Option<Self> {
309        Self::from_u64(u64::from_be_bytes(v))
310    }
311
312    /**
313    Convert the span id into an 8 byte big-endian array.
314    */
315    pub fn to_bytes(&self) -> [u8; 8] {
316        self.0.get().to_be_bytes()
317    }
318
319    /**
320    Convert the span id into a 16 byte ASCII-compatible hex string, like `00f067aa0ba902b7`.
321    */
322    pub fn to_hex(&self) -> [u8; 16] {
323        let mut dst = [0; 16];
324        let src: [u8; 8] = self.0.get().to_be_bytes();
325
326        for i in 0..src.len() {
327            let b = src[i];
328
329            dst[i * 2] = HEX_ENCODE_TABLE[(b >> 4) as usize];
330            dst[i * 2 + 1] = HEX_ENCODE_TABLE[(b & 0x0f) as usize];
331        }
332
333        dst
334    }
335
336    /**
337    Try parse a slice of ASCII hex bytes into a span id.
338
339    If `hex` is not a 16 byte array of valid hex characters (`[a-fA-F0-9]`) then this method will fail.
340    */
341    pub fn try_from_hex_slice(hex: &[u8]) -> Result<Self, ParseIdError> {
342        let hex: &[u8; 16] = hex.try_into().map_err(|_| ParseIdError {})?;
343
344        let mut dst = [0; 8];
345
346        let mut i = 0;
347        while i < 8 {
348            // Convert a two-char hex value (like `A8`)
349            // into a byte (like `10101000`)
350            let h1 = HEX_DECODE_TABLE[hex[i * 2] as usize];
351            let h2 = HEX_DECODE_TABLE[hex[i * 2 + 1] as usize];
352
353            // We use `0xff` as a sentinel value to indicate
354            // an invalid hex character sequence (like the letter `G`)
355            if h1 | h2 == 0xff {
356                return Err(ParseIdError {});
357            }
358
359            // The upper nibble needs to be shifted into position
360            // to produce the final byte value
361            dst[i] = SHL4_TABLE[h1 as usize] | h2;
362            i += 1;
363        }
364
365        Ok(SpanId::new(
366            NonZeroU64::new(u64::from_be_bytes(dst)).ok_or_else(|| ParseIdError {})?,
367        ))
368    }
369
370    /**
371    Try parse ASCII hex characters into a span id.
372
373    If `hex` is not exactly 16 valid hex characters (`[a-fA-F0-9]`) then this method will fail.
374    */
375    pub fn try_from_hex(hex: impl fmt::Display) -> Result<Self, ParseIdError> {
376        let mut buf = crate::buf::Buffer::<16>::new();
377
378        Self::try_from_hex_slice(buf.buffer(hex).map_err(|_| ParseIdError {})?)
379    }
380}
381
382/*
383Original implementation: https://github.com/uuid-rs/uuid/blob/main/src/parser.rs
384
385Licensed under Apache 2.0
386*/
387
388const HEX_ENCODE_TABLE: [u8; 16] = [
389    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f',
390];
391
392const HEX_DECODE_TABLE: &[u8; 256] = &{
393    let mut buf = [0; 256];
394    let mut i: u8 = 0;
395
396    loop {
397        buf[i as usize] = match i {
398            b'0'..=b'9' => i - b'0',
399            b'a'..=b'f' => i - b'a' + 10,
400            b'A'..=b'F' => i - b'A' + 10,
401            _ => 0xff,
402        };
403
404        if i == 255 {
405            break buf;
406        }
407
408        i += 1
409    }
410};
411
412const SHL4_TABLE: &[u8; 256] = &{
413    let mut buf = [0; 256];
414    let mut i: u8 = 0;
415
416    loop {
417        buf[i as usize] = i.wrapping_shl(4);
418
419        if i == 255 {
420            break buf;
421        }
422
423        i += 1;
424    }
425};
426
427/**
428An error encountered attempting to parse a [`TraceId`] or [`SpanId`].
429*/
430#[derive(Debug)]
431pub struct ParseIdError {}
432
433impl fmt::Display for ParseIdError {
434    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435        write!(f, "the input was not a valid id")
436    }
437}
438
439#[cfg(feature = "std")]
440impl std::error::Error for ParseIdError {}
441
442/**
443A diagnostic event that represents a span in a distributed trace.
444
445Spans are an extension of [`Event`]s that explicitly take the well-known properties that signal an event as being a span. See the [`mod@crate::span`] module for details.
446
447A `SpanEvent` can be converted into an [`Event`] through its [`ToEvent`] implemenation, or passed directly to a [`crate::Emitter`] to emit it.
448*/
449pub struct Span<'a, P> {
450    mdl: Path<'a>,
451    extent: Option<Extent>,
452    tpl: Option<Template<'a>>,
453    props: P,
454}
455
456impl<'a, P: Props> Span<'a, P> {
457    /**
458    Create a new span event from its parts.
459
460    Each span consists of:
461
462    - `mdl`: The module that executed the operation the span is tracking.
463    - `extent`: The time the operation spent executing. The extent should be a span.
464    - `props`: Additional [`Props`] to associate with the span. These may include the [`SpanCtxt`] with the trace and span ids for the span, or they may be part of the ambient context.
465    */
466    pub fn new(mdl: impl Into<Path<'a>>, extent: impl ToExtent, props: P) -> Self {
467        Span {
468            mdl: mdl.into(),
469            extent: extent.to_extent(),
470            tpl: None,
471            props,
472        }
473    }
474
475    /**
476    Get the module that executed the operation.
477    */
478    pub fn mdl(&self) -> &Path<'a> {
479        &self.mdl
480    }
481
482    /**
483    Set the module of the span.
484    */
485    pub fn with_mdl(mut self, mdl: impl Into<Path<'a>>) -> Self {
486        self.mdl = mdl.into();
487        self
488    }
489
490    /**
491    Get the name of the executing operation.
492    */
493    pub fn name(&self) -> Option<Str<'_>> {
494        self.props.pull(KEY_SPAN_NAME)
495    }
496
497    /**
498    Set the name of the executing operation.
499    */
500    pub fn with_name(self, name: impl Into<Str<'a>>) -> Span<'a, And<(&'static str, Str<'a>), P>> {
501        self.map_props(|props| (KEY_SPAN_NAME, name.into()).and_props(props))
502    }
503
504    /**
505    Get the kind of the executing operation.
506    */
507    pub fn kind(&self) -> Option<SpanKind> {
508        self.props.pull(KEY_SPAN_KIND)
509    }
510
511    /**
512    Set the kind of the executing operation.
513    */
514    pub fn with_kind(
515        self,
516        kind: impl Into<SpanKind>,
517    ) -> Span<'a, And<(&'static str, SpanKind), P>> {
518        self.map_props(|props| (KEY_SPAN_KIND, kind.into()).and_props(props))
519    }
520
521    /**
522    Get the ctxt of the executing operation.
523
524    This method accepts a [`Ctxt`], which will be used to pull the [`SpanCtxt`] if this span doesn't carry them in its own local props.
525    */
526    pub fn ctxt(&self, ctxt: impl Ctxt) -> SpanCtxt {
527        ctxt.with_current(|props| {
528            let props = (&self.props).and_props(props);
529
530            let trace_id = props.pull(KEY_TRACE_ID);
531            let span_id = props.pull(KEY_SPAN_ID);
532            let span_parent = props.pull(KEY_SPAN_PARENT);
533
534            SpanCtxt::new(trace_id, span_parent, span_id)
535        })
536    }
537
538    /**
539    Get the set of spans linked to the executing operation.
540    */
541    #[cfg(feature = "alloc")]
542    pub fn links(&self) -> Option<SpanLinkSet> {
543        self.props.pull(KEY_SPAN_LINKS)
544    }
545
546    /**
547    Set the set of spans linked to the executing operation.
548    */
549    #[cfg(feature = "alloc")]
550    pub fn with_links(
551        self,
552        links: impl Into<SpanLinkSet>,
553    ) -> Span<'a, And<(&'static str, SpanLinkSet), P>> {
554        self.map_props(|props| (KEY_SPAN_LINKS, links.into()).and_props(props))
555    }
556
557    /**
558    Get the time the operation spent executing.
559    */
560    pub fn extent(&self) -> Option<&Extent> {
561        self.extent.as_ref()
562    }
563
564    /**
565    Set the extent of the span.
566    */
567    pub fn with_extent(mut self, extent: impl ToExtent) -> Self {
568        self.extent = extent.to_extent();
569        self
570    }
571
572    /**
573    Get the extent of the metric as a point in time.
574
575    If the span has an extent then this method will return `Some`, with the result of [`Extent::as_point`]. If the span doesn't have an extent then this method will return `None`.
576    */
577    pub fn ts(&self) -> Option<&Timestamp> {
578        self.extent.as_ref().map(|extent| extent.as_point())
579    }
580
581    /**
582    Get the start point of the extent of the span.
583
584    If the span has an extent, and that extent covers a timespan then this method will return `Some`. Otherwise this method will return `None`.
585    */
586    pub fn ts_start(&self) -> Option<&Timestamp> {
587        self.extent
588            .as_ref()
589            .and_then(|extent| extent.as_range())
590            .map(|span| &span.start)
591    }
592
593    /**
594    Get the additional properties associated with the span.
595    */
596    pub fn props(&self) -> &P {
597        &self.props
598    }
599
600    /**
601    Get exclusive access to the additional properties on the span.
602    */
603    pub fn props_mut(&mut self) -> &mut P {
604        &mut self.props
605    }
606
607    /**
608    Set the properties of the span.
609    */
610    pub fn with_props<U>(self, props: U) -> Span<'a, U> {
611        Span {
612            mdl: self.mdl,
613            extent: self.extent,
614            tpl: self.tpl,
615            props,
616        }
617    }
618
619    /**
620    Map the properties of the span.
621    */
622    pub fn map_props<U>(self, map: impl FnOnce(P) -> U) -> Span<'a, U> {
623        Span {
624            mdl: self.mdl,
625            extent: self.extent,
626            tpl: self.tpl,
627            props: map(self.props),
628        }
629    }
630
631    /**
632    Get the template that will be used to render the span.
633    */
634    pub fn tpl(&self) -> &Template<'a> {
635        self.tpl.as_ref().unwrap_or(&END_TEMPLATE)
636    }
637
638    /**
639    Set the template of the span.
640    */
641    pub fn with_tpl(mut self, tpl: impl Into<Template<'a>>) -> Self {
642        self.tpl = Some(tpl.into());
643        self
644    }
645
646    /**
647    Get a type-erased span, borrowing data from this one.
648    */
649    pub fn erase<'b>(&'b self) -> Span<'b, &'b dyn ErasedProps> {
650        Span {
651            mdl: self.mdl.by_ref(),
652            extent: self.extent.clone(),
653            tpl: self.tpl.as_ref().map(|tpl| tpl.by_ref()),
654            props: &self.props,
655        }
656    }
657}
658
659impl<'a, P: Props> fmt::Debug for Span<'a, P> {
660    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
661        fmt::Debug::fmt(&self.to_event(), f)
662    }
663}
664
665// "{span_name} started"
666const START_TEMPLATE_PARTS: &'static [template::Part<'static>] = &[
667    template::Part::hole("span_name"),
668    template::Part::text(" started"),
669];
670
671static START_TEMPLATE: Template<'static> = Template::new(&START_TEMPLATE_PARTS);
672
673// "{span_name} completed"
674const END_TEMPLATE_PARTS: &'static [template::Part<'static>] = &[
675    template::Part::hole("span_name"),
676    template::Part::text(" completed"),
677];
678
679static END_TEMPLATE: Template<'static> = Template::new(&END_TEMPLATE_PARTS);
680
681impl<'a, P: Props> ToEvent for Span<'a, P> {
682    type Props<'b>
683        = &'b Self
684    where
685        Self: 'b;
686
687    fn to_event<'b>(&'b self) -> Event<'b, Self::Props<'b>> {
688        Event::new(
689            self.mdl.by_ref(),
690            self.tpl().by_ref(),
691            self.extent.clone(),
692            &self,
693        )
694    }
695}
696
697impl<'a, P: Props> ToExtent for Span<'a, P> {
698    fn to_extent(&self) -> Option<Extent> {
699        self.extent().cloned()
700    }
701}
702
703impl<'a, P: Props> Props for Span<'a, P> {
704    fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
705        &'kv self,
706        mut for_each: F,
707    ) -> ControlFlow<()> {
708        for_each(KEY_EVT_KIND.to_str(), Kind::Span.to_value())?;
709
710        self.props.for_each(&mut for_each)
711    }
712}
713
714/**
715The trace id, span id, and parent span id of a span.
716
717These ids can be used to identify the distributed trace a span belongs to, and to identify the span itself within that trace.
718
719The `SpanCtxt` for the currently executing span can be pulled from the ambient context with [`SpanCtxt::current`]. Once a `SpanCtxt` is constructed, a new child context can be generated by [`SpanCtxt::new_child`].
720
721`SpanCtxt` should be pushed onto the ambient context with [`SpanCtxt::push`] so any events emitted during its execution are correlated to it.
722*/
723#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
724pub struct SpanCtxt {
725    trace_id: Option<TraceId>,
726    span_parent: Option<SpanId>,
727    span_id: Option<SpanId>,
728}
729
730impl SpanCtxt {
731    /**
732    Create the context from a set of identifiers.
733
734    The `trace_id` and `span_id` should both be `Some`, but `span_parent` may be `None` if the span is at the root of the distributed trace.
735
736    If `trace_id` or `span_id` are `None` then the context is invalid, but can still be used.
737    */
738    pub const fn new(
739        trace_id: Option<TraceId>,
740        span_parent: Option<SpanId>,
741        span_id: Option<SpanId>,
742    ) -> Self {
743        SpanCtxt {
744            trace_id,
745            span_parent,
746            span_id,
747        }
748    }
749
750    /**
751    Create a context where all identifiers are `None`.
752    */
753    pub const fn empty() -> Self {
754        Self {
755            trace_id: None,
756            span_parent: None,
757            span_id: None,
758        }
759    }
760
761    /**
762    Generate a new context.
763    */
764    pub fn new_root(rng: impl Rng) -> Self {
765        let trace_id = TraceId::random(&rng);
766        let span_parent = None;
767        let span_id = SpanId::random(&rng);
768
769        SpanCtxt::new(trace_id, span_parent, span_id)
770    }
771
772    /**
773    Read the current context from an ambient [`Ctxt`].
774
775    This method will pull the [`TraceId`] from [`KEY_TRACE_ID`], the `SpanId` from [`KEY_SPAN_ID`], and the parent [`SpanId`] from [`KEY_SPAN_PARENT`].
776    */
777    pub fn current(ctxt: impl Ctxt) -> Self {
778        ctxt.with_current(|current| {
779            SpanCtxt::new(
780                current.pull::<TraceId, _>(KEY_TRACE_ID),
781                current.pull::<SpanId, _>(KEY_SPAN_PARENT),
782                current.pull::<SpanId, _>(KEY_SPAN_ID),
783            )
784        })
785    }
786
787    /**
788    Generate a new context that is a child of `self`.
789
790    The new context will share the same trace id as `self`, use the span id of `self` as its parent span id, and generate a new random span id as its own through [`SpanId::random`].
791
792    If [`Self::trace_id`] is `None` then a new trace id will be generated through [`TraceId::random`].
793    */
794    pub fn new_child(&self, rng: impl Rng) -> Self {
795        let trace_id = self.trace_id.or_else(|| TraceId::random(&rng));
796        let span_parent = self.span_id;
797        let span_id = SpanId::random(&rng);
798
799        SpanCtxt::new(trace_id, span_parent, span_id)
800    }
801
802    /**
803    Get the trace id for the span.
804    */
805    pub fn trace_id(&self) -> Option<&TraceId> {
806        self.trace_id.as_ref()
807    }
808
809    /**
810    Get the parent of the span.
811    */
812    pub fn span_parent(&self) -> Option<&SpanId> {
813        self.span_parent.as_ref()
814    }
815
816    /**
817    Get the id of the span.
818    */
819    pub fn span_id(&self) -> Option<&SpanId> {
820        self.span_id.as_ref()
821    }
822
823    /**
824    Push the [`SpanCtxt`] onto the ambient context.
825
826    The trace id, span id, and parent span id will be pushed to the context. This ensures diagnostics emitted during the execution of this span are properly linked to it.
827    */
828    pub fn push<T: Ctxt>(&self, ctxt: T) -> Frame<T> {
829        Frame::push(ctxt, self)
830    }
831}
832
833impl Props for SpanCtxt {
834    fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
835        &'kv self,
836        mut for_each: F,
837    ) -> ControlFlow<()> {
838        if let Some(ref trace_id) = self.trace_id {
839            for_each(KEY_TRACE_ID.to_str(), trace_id.to_value())?;
840        }
841
842        if let Some(ref span_id) = self.span_id {
843            for_each(KEY_SPAN_ID.to_str(), span_id.to_value())?;
844        }
845
846        if let Some(ref span_parent) = self.span_parent {
847            for_each(KEY_SPAN_PARENT.to_str(), span_parent.to_value())?;
848        }
849
850        ControlFlow::Continue(())
851    }
852}
853
854/**
855An error encountered attempting to parse a [`TraceId`] or [`SpanId`].
856*/
857#[derive(Debug)]
858pub struct ParseKindError {}
859
860impl fmt::Display for ParseKindError {
861    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
862        write!(f, "the input was not a valid kind")
863    }
864}
865
866#[cfg(feature = "std")]
867impl std::error::Error for ParseKindError {}
868
869/**
870A hint about the way a span and its child are linked.
871*/
872#[non_exhaustive]
873#[derive(Clone, Copy, PartialEq, Eq)]
874pub enum SpanKind {
875    /**
876    Internal spans represent operations which do not cross a process boundary.
877    */
878    Internal,
879    /**
880    Server-side handling of an RPC or other remote network request.
881
882    Paired with a `Client`.
883    */
884    Server,
885    /**
886    A request to some remote service.
887
888    Paired with a `Server`.
889    */
890    Client,
891    /**
892    A producer sending a message to a broker.
893
894    Paired with a `Consumer`.
895    */
896    Producer,
897    /**
898    A consumer receiving a message from a broker.
899
900    Paired with a `Producer`.
901    */
902    Consumer,
903}
904
905impl SpanKind {
906    /**
907    Try parse a span kind from a formatted representation.
908    */
909    pub fn try_from_str(s: &str) -> Result<Self, ParseKindError> {
910        s.parse()
911    }
912
913    /**
914    Get the value of the span kind as a string.
915    */
916    pub fn as_str(&self) -> &'static str {
917        match self {
918            SpanKind::Internal => SPAN_KIND_INTERNAL,
919            SpanKind::Server => SPAN_KIND_SERVER,
920            SpanKind::Client => SPAN_KIND_CLIENT,
921            SpanKind::Producer => SPAN_KIND_PRODUCER,
922            SpanKind::Consumer => SPAN_KIND_CONSUMER,
923        }
924    }
925}
926
927impl FromStr for SpanKind {
928    type Err = ParseKindError;
929
930    fn from_str(s: &str) -> Result<Self, Self::Err> {
931        let s = s.trim();
932
933        if s.eq_ignore_ascii_case(SPAN_KIND_INTERNAL) {
934            return Ok(SpanKind::Internal);
935        }
936
937        if s.eq_ignore_ascii_case(SPAN_KIND_SERVER) {
938            return Ok(SpanKind::Server);
939        }
940
941        if s.eq_ignore_ascii_case(SPAN_KIND_CLIENT) {
942            return Ok(SpanKind::Client);
943        }
944
945        if s.eq_ignore_ascii_case(SPAN_KIND_PRODUCER) {
946            return Ok(SpanKind::Producer);
947        }
948
949        if s.eq_ignore_ascii_case(SPAN_KIND_CONSUMER) {
950            return Ok(SpanKind::Consumer);
951        }
952
953        Err(ParseKindError {})
954    }
955}
956
957impl fmt::Debug for SpanKind {
958    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959        write!(f, "\"{}\"", self)
960    }
961}
962
963impl fmt::Display for SpanKind {
964    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
965        f.write_str(self.as_str())
966    }
967}
968
969#[cfg(feature = "sval")]
970impl sval::Value for SpanKind {
971    fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
972        stream.value(self.as_str())
973    }
974}
975
976#[cfg(feature = "serde")]
977impl serde::Serialize for SpanKind {
978    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
979        self.as_str().serialize(serializer)
980    }
981}
982
983impl ToValue for SpanKind {
984    fn to_value(&self) -> Value<'_> {
985        Value::capture_display(self)
986    }
987}
988
989impl<'v> FromValue<'v> for SpanKind {
990    fn from_value(value: Value<'v>) -> Option<Self> {
991        value
992            .downcast_ref::<SpanKind>()
993            .copied()
994            .or_else(|| value.parse())
995    }
996}
997
998/**
999A link between two spans in potentially different traces.
1000
1001A link belongs to a span, and contains the [`TraceId`] and [`SpanId`] of the span being linked to.
1002Links are usually created on the downstream span.
1003
1004Links relate spans outside of the normal parent-child hierarchy.
1005Links are largely informative and may not be understood by downstream consumers.
1006In order to create a generic DAG out of span links, the spans would need to belong to separate traces, since the parent-child relationship is still required.
1007*/
1008#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
1009pub struct SpanLink {
1010    trace_id: TraceId,
1011    span_id: SpanId,
1012}
1013
1014impl SpanLink {
1015    /**
1016    Create a new link to the target span.
1017    */
1018    pub const fn new(trace_id: TraceId, span_id: SpanId) -> Self {
1019        SpanLink { trace_id, span_id }
1020    }
1021
1022    /**
1023    Try parse a span link from a formatted representation.
1024    */
1025    pub fn try_from_str(s: &str) -> Result<Self, ParseLinkError> {
1026        Self::try_from_slice(s.as_bytes())
1027    }
1028
1029    fn try_from_slice(s: &[u8]) -> Result<Self, ParseLinkError> {
1030        if s.len() != 49 {
1031            return Err(ParseLinkError {});
1032        }
1033
1034        if s[32] != b'-' {
1035            return Err(ParseLinkError {});
1036        }
1037
1038        let trace_id = TraceId::try_from_hex_slice(&s[0..32]).map_err(|_| ParseLinkError {})?;
1039        let span_id = SpanId::try_from_hex_slice(&s[33..49]).map_err(|_| ParseLinkError {})?;
1040
1041        Ok(SpanLink::new(trace_id, span_id))
1042    }
1043
1044    /**
1045    Try parse a span link from a formatted representation.
1046    */
1047    pub fn parse(s: impl fmt::Display) -> Result<Self, ParseLinkError> {
1048        let mut buf = crate::buf::Buffer::<49>::new();
1049
1050        Self::try_from_slice(buf.buffer(s).map_err(|_| ParseLinkError {})?)
1051    }
1052
1053    /**
1054    The [`TraceId`] of the linked span.
1055    */
1056    pub fn trace_id(&self) -> &TraceId {
1057        &self.trace_id
1058    }
1059
1060    /**
1061    The [`SpanId`] of the linked span.
1062    */
1063    pub fn span_id(&self) -> &SpanId {
1064        &self.span_id
1065    }
1066}
1067
1068impl FromStr for SpanLink {
1069    type Err = ParseLinkError;
1070
1071    fn from_str(s: &str) -> Result<Self, Self::Err> {
1072        Self::try_from_str(s)
1073    }
1074}
1075
1076impl fmt::Debug for SpanLink {
1077    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1078        write!(f, "\"{}\"", self)
1079    }
1080}
1081
1082impl fmt::Display for SpanLink {
1083    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1084        let mut buf = [0; 49];
1085
1086        buf[0..32].copy_from_slice(&self.trace_id.to_hex());
1087        buf[32] = b'-';
1088        buf[33..49].copy_from_slice(&self.span_id.to_hex());
1089
1090        f.write_str(str::from_utf8(&buf).unwrap())
1091    }
1092}
1093
1094#[cfg(feature = "sval")]
1095impl sval::Value for SpanLink {
1096    fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
1097        sval::stream_display(stream, self)
1098    }
1099}
1100
1101#[cfg(feature = "serde")]
1102impl serde::Serialize for SpanLink {
1103    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1104        serializer.collect_str(self)
1105    }
1106}
1107
1108impl ToValue for SpanLink {
1109    fn to_value(&self) -> Value<'_> {
1110        Value::capture_display(self)
1111    }
1112}
1113
1114impl<'v> FromValue<'v> for SpanLink {
1115    fn from_value(value: Value<'v>) -> Option<Self> {
1116        value
1117            .downcast_ref::<SpanLink>()
1118            .copied()
1119            .or_else(|| SpanLink::parse(value).ok())
1120    }
1121}
1122
1123/**
1124An error encountered attempting to parse a [`TraceId`] or [`SpanId`].
1125*/
1126#[derive(Debug)]
1127pub struct ParseLinkError {}
1128
1129impl fmt::Display for ParseLinkError {
1130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1131        write!(f, "the input was not a valid span link")
1132    }
1133}
1134
1135#[cfg(feature = "std")]
1136impl std::error::Error for ParseLinkError {}
1137
1138#[cfg(feature = "alloc")]
1139pub mod span_link_set {
1140    /*!
1141    The [`SpanLinkSet`] type.
1142    */
1143
1144    use super::*;
1145
1146    #[cfg(not(feature = "std"))]
1147    use alloc::collections::{BTreeSet as Set, btree_set as set};
1148    #[cfg(feature = "std")]
1149    use std::collections::{HashSet as Set, hash_set as set};
1150
1151    use core::{fmt::Write, str::FromStr};
1152
1153    use crate::buf::trim_start;
1154    use emit_core::value::{FromValue, ToValue, Value};
1155
1156    /**
1157    An error encountered attempting to parse a [`SpanLinkSet`].
1158    */
1159    #[derive(Debug)]
1160    pub struct ParseSpanLinkSetError {}
1161
1162    impl fmt::Display for ParseSpanLinkSetError {
1163        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164            write!(f, "the input was not a valid span link set")
1165        }
1166    }
1167
1168    #[cfg(feature = "std")]
1169    impl std::error::Error for ParseSpanLinkSetError {}
1170
1171    /**
1172    A collection of [`SpanLink`]s.
1173    */
1174    #[derive(Clone, PartialEq, Eq)]
1175    pub struct SpanLinkSet {
1176        links: Set<SpanLink>,
1177    }
1178
1179    impl fmt::Debug for SpanLinkSet {
1180        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1181            fmt::Display::fmt(self, f)
1182        }
1183    }
1184
1185    impl fmt::Display for SpanLinkSet {
1186        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1187            f.write_char('[')?;
1188
1189            let mut first = true;
1190            for link in &self.links {
1191                if !first {
1192                    f.write_char(',')?;
1193                }
1194                first = false;
1195
1196                fmt::Display::fmt(link, f)?;
1197            }
1198
1199            f.write_char(']')
1200        }
1201    }
1202
1203    impl SpanLinkSet {
1204        /**
1205        Create a new empty `SpanLinkSet`.
1206
1207        This method does not allocate.
1208        */
1209        pub fn new() -> Self {
1210            SpanLinkSet { links: Set::new() }
1211        }
1212
1213        /**
1214        Parse a `SpanLinkSet` from its raw textual representation.
1215
1216        The input must be enclosed in matching brackets (`[]`, `()`, or `{}`), with comma-separated [`SpanLink`] strings inside.
1217        */
1218        pub fn try_from_str(s: &str) -> Result<Self, ParseSpanLinkSetError> {
1219            Self::try_from_slice(s.as_bytes())
1220        }
1221
1222        fn try_from_slice(mut s: &[u8]) -> Result<Self, ParseSpanLinkSetError> {
1223            let mut set = SpanLinkSet::new();
1224
1225            if s.len() < 2 {
1226                return Err(ParseSpanLinkSetError {});
1227            }
1228
1229            // Must be enclosed by `[]`, `()`, or `{}`
1230            match (s.first(), s.last()) {
1231                (Some(&b'['), Some(&b']')) => (),
1232                (Some(&b'('), Some(&b')')) => (),
1233                (Some(&b'{'), Some(&b'}')) => (),
1234                _ => return Err(ParseSpanLinkSetError {}),
1235            };
1236            s = &s[1..];
1237            s = trim_start(s);
1238
1239            let mut first = true;
1240
1241            while s.len() > 1 {
1242                // Parse each link
1243                if !first {
1244                    if s.first() != Some(&b',') {
1245                        // Invalid link: expected `,`
1246                        return Err(ParseSpanLinkSetError {});
1247                    }
1248                    s = &s[1..];
1249                    s = trim_start(s);
1250                }
1251                first = false;
1252
1253                let link = match s.first() {
1254                    Some(&b'"') => {
1255                        // Parse a link surrounded by quotes
1256                        if s.get(50) != Some(&b'"') {
1257                            // Unquoted
1258                            return Err(ParseSpanLinkSetError {});
1259                        }
1260
1261                        let link = &s[1..50];
1262                        s = &s[51..];
1263
1264                        link
1265                    }
1266                    _ => {
1267                        if s.len() < 49 {
1268                            // Unexpected EOF parsing link: not enough chars for `$link`
1269                            return Err(ParseSpanLinkSetError {});
1270                        }
1271
1272                        // Parse an unquoted span link
1273                        let link = &s[0..49];
1274                        s = &s[49..];
1275
1276                        link
1277                    }
1278                };
1279
1280                let link = SpanLink::try_from_slice(link).map_err(|_| ParseSpanLinkSetError {})?;
1281                if !set.links.insert(link) {
1282                    // Duplicate link
1283                    return Err(ParseSpanLinkSetError {});
1284                }
1285
1286                s = trim_start(s);
1287            }
1288
1289            if s.len() != 1 {
1290                // Unexpected EOF
1291                return Err(ParseSpanLinkSetError {});
1292            }
1293
1294            Ok(set)
1295        }
1296
1297        /**
1298        Insert a [`SpanLink`] into the set.
1299
1300        Returns `true` if the link was not already present.
1301        */
1302        pub fn insert(&mut self, link: SpanLink) -> bool {
1303            self.links.insert(link)
1304        }
1305
1306        /**
1307        Get the number of links in the set.
1308        */
1309        pub fn len(&self) -> usize {
1310            self.links.len()
1311        }
1312
1313        /**
1314        Returns `true` if the set contains no links.
1315        */
1316        pub fn is_empty(&self) -> bool {
1317            self.links.is_empty()
1318        }
1319
1320        /**
1321        Clear all links, allowing the allocation to be re-used.
1322        */
1323        pub fn clear(&mut self) {
1324            self.links.clear();
1325        }
1326
1327        /**
1328        Returns `true` if the set contains the given link.
1329        */
1330        pub fn contains(&self, link: SpanLink) -> bool {
1331            self.links.contains(&link)
1332        }
1333
1334        /**
1335        Iterate over links in sorted order.
1336        */
1337        pub fn iter(&self) -> Iter<'_> {
1338            Iter(self.links.iter())
1339        }
1340    }
1341
1342    impl Default for SpanLinkSet {
1343        fn default() -> Self {
1344            Self::new()
1345        }
1346    }
1347
1348    impl<'a> IntoIterator for &'a SpanLinkSet {
1349        type IntoIter = Iter<'a>;
1350        type Item = SpanLink;
1351
1352        fn into_iter(self) -> Self::IntoIter {
1353            self.iter()
1354        }
1355    }
1356
1357    impl<'a> FromIterator<SpanLink> for SpanLinkSet {
1358        fn from_iter<I: IntoIterator<Item = SpanLink>>(iter: I) -> Self {
1359            let mut set = SpanLinkSet::new();
1360            set.extend(iter);
1361
1362            set
1363        }
1364    }
1365
1366    impl<'a> Extend<SpanLink> for SpanLinkSet {
1367        fn extend<I: IntoIterator<Item = SpanLink>>(&mut self, iter: I) {
1368            for link in iter {
1369                self.insert(link);
1370            }
1371        }
1372    }
1373
1374    impl<'a> FromIterator<(TraceId, SpanId)> for SpanLinkSet {
1375        fn from_iter<I: IntoIterator<Item = (TraceId, SpanId)>>(iter: I) -> Self {
1376            Self::from_iter(
1377                iter.into_iter()
1378                    .map(|(trace_id, span_id)| SpanLink::new(trace_id, span_id)),
1379            )
1380        }
1381    }
1382
1383    impl<'a> Extend<(TraceId, SpanId)> for SpanLinkSet {
1384        fn extend<I: IntoIterator<Item = (TraceId, SpanId)>>(&mut self, iter: I) {
1385            self.extend(
1386                iter.into_iter()
1387                    .map(|(trace_id, span_id)| SpanLink::new(trace_id, span_id)),
1388            )
1389        }
1390    }
1391
1392    /**
1393    An iterator over sorted links from a [`SpanLinkSet`].
1394
1395    This is the result of calling [`SpanLinkSet::iter`].
1396    */
1397    pub struct Iter<'a>(set::Iter<'a, SpanLink>);
1398
1399    impl<'a> Iterator for Iter<'a> {
1400        type Item = SpanLink;
1401
1402        fn next(&mut self) -> Option<Self::Item> {
1403            self.0.next().copied()
1404        }
1405    }
1406
1407    #[cfg(feature = "sval")]
1408    impl sval::Value for SpanLinkSet {
1409        fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(
1410            &'sval self,
1411            stream: &mut S,
1412        ) -> sval::Result {
1413            stream.seq_begin(Some(self.links.len()))?;
1414
1415            for link in &self.links {
1416                stream.seq_value_begin()?;
1417                stream.value(link)?;
1418                stream.seq_value_end()?;
1419            }
1420
1421            stream.seq_end()
1422        }
1423    }
1424
1425    #[cfg(feature = "serde")]
1426    impl serde::Serialize for SpanLinkSet {
1427        fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1428            use serde::ser::SerializeSeq as _;
1429
1430            let mut seq = serializer.serialize_seq(Some(self.links.len()))?;
1431
1432            for link in &self.links {
1433                seq.serialize_element(link)?;
1434            }
1435
1436            seq.end()
1437        }
1438    }
1439
1440    impl FromStr for SpanLinkSet {
1441        type Err = ParseSpanLinkSetError;
1442
1443        fn from_str(s: &str) -> Result<Self, Self::Err> {
1444            Self::try_from_str(s)
1445        }
1446    }
1447
1448    impl ToValue for SpanLinkSet {
1449        fn to_value(&self) -> Value<'_> {
1450            #[cfg(feature = "sval")]
1451            {
1452                Value::capture_sval(self)
1453            }
1454            #[cfg(all(feature = "serde", not(feature = "sval")))]
1455            {
1456                Value::capture_serde(self)
1457            }
1458            #[cfg(all(not(feature = "serde"), not(feature = "sval")))]
1459            {
1460                Value::capture_display(self)
1461            }
1462        }
1463    }
1464
1465    impl<'a> FromValue<'a> for SpanLinkSet {
1466        fn from_value(v: Value<'a>) -> Option<Self> {
1467            if let Some(link_set) = v.downcast_ref::<Self>() {
1468                return Some(link_set.clone());
1469            }
1470
1471            #[cfg(feature = "sval")]
1472            {
1473                if let Some(link_set) = from_sval(v.by_ref()) {
1474                    return Some(link_set);
1475                }
1476            }
1477
1478            #[cfg(all(not(feature = "sval"), feature = "serde"))]
1479            {
1480                if let Some(link_set) = from_serde(v.by_ref()) {
1481                    return Some(link_set);
1482                }
1483            }
1484
1485            v.parse()
1486        }
1487    }
1488
1489    #[cfg(any(feature = "sval", feature = "serde"))]
1490    struct Extract {
1491        depth: usize,
1492        links: Set<SpanLink>,
1493        text_buf: crate::buf::Buffer<49>,
1494    }
1495
1496    #[cfg(any(feature = "sval", feature = "serde"))]
1497    impl Default for Extract {
1498        fn default() -> Self {
1499            Extract {
1500                depth: 0,
1501                links: Set::new(),
1502                text_buf: crate::buf::Buffer::new(),
1503            }
1504        }
1505    }
1506
1507    #[cfg(any(feature = "sval", feature = "serde"))]
1508    #[derive(Debug)]
1509    struct Incompatible;
1510
1511    #[cfg(any(feature = "sval", feature = "serde"))]
1512    impl Extract {
1513        fn push_link_fragment(&mut self, fragment: &str) -> Result<(), Incompatible> {
1514            if self.depth != 1 {
1515                return Err(Incompatible);
1516            }
1517
1518            if !self.text_buf.push_str(fragment) {
1519                return Err(Incompatible);
1520            }
1521
1522            Ok(())
1523        }
1524
1525        fn push_link(&mut self) -> Result<(), Incompatible> {
1526            if self.depth != 1 {
1527                return Err(Incompatible);
1528            }
1529
1530            let link_bytes = self.text_buf.as_bytes();
1531            let link = SpanLink::try_from_slice(link_bytes).map_err(|_| Incompatible)?;
1532
1533            self.links.insert(link);
1534            self.text_buf.reset();
1535
1536            Ok(())
1537        }
1538
1539        fn down(&mut self) -> Result<(), Incompatible> {
1540            self.depth += 1;
1541
1542            if self.depth > 1 {
1543                Err(Incompatible)
1544            } else {
1545                Ok(())
1546            }
1547        }
1548
1549        fn up(&mut self) -> Result<(), Incompatible> {
1550            self.depth -= 1;
1551
1552            Ok(())
1553        }
1554
1555        fn end(self) -> SpanLinkSet {
1556            SpanLinkSet { links: self.links }
1557        }
1558    }
1559
1560    #[cfg(feature = "sval")]
1561    fn from_sval(value: Value) -> Option<SpanLinkSet> {
1562        #[allow(non_local_definitions)]
1563        impl From<Incompatible> for sval::Error {
1564            fn from(_: Incompatible) -> sval::Error {
1565                sval::Error::new()
1566            }
1567        }
1568
1569        #[allow(non_local_definitions)]
1570        impl<'sval> sval::Stream<'sval> for Extract {
1571            fn null(&mut self) -> sval::Result {
1572                sval::error()
1573            }
1574
1575            fn bool(&mut self, _: bool) -> sval::Result {
1576                sval::error()
1577            }
1578
1579            fn text_begin(&mut self, _: Option<usize>) -> sval::Result {
1580                Ok(())
1581            }
1582
1583            fn text_fragment_computed(&mut self, fragment: &str) -> sval::Result {
1584                self.push_link_fragment(fragment).map_err(Into::into)
1585            }
1586
1587            fn text_end(&mut self) -> sval::Result {
1588                Ok(self.push_link()?)
1589            }
1590
1591            fn i64(&mut self, _: i64) -> sval::Result {
1592                sval::error()
1593            }
1594
1595            fn f64(&mut self, _: f64) -> sval::Result {
1596                sval::error()
1597            }
1598
1599            fn seq_begin(&mut self, _: Option<usize>) -> sval::Result {
1600                Ok(self.down()?)
1601            }
1602
1603            fn seq_value_begin(&mut self) -> sval::Result {
1604                Ok(())
1605            }
1606
1607            fn seq_value_end(&mut self) -> sval::Result {
1608                Ok(())
1609            }
1610
1611            fn seq_end(&mut self) -> sval::Result {
1612                Ok(self.up()?)
1613            }
1614        }
1615
1616        let mut extract = Extract::default();
1617        sval::stream(&mut extract, &value).ok()?;
1618
1619        Some(extract.end())
1620    }
1621
1622    #[cfg(all(not(feature = "sval"), feature = "serde"))]
1623    fn from_serde(value: Value) -> Option<SpanLinkSet> {
1624        use serde::Serialize as _;
1625
1626        #[allow(non_local_definitions)]
1627        impl fmt::Display for Incompatible {
1628            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1629                f.write_str("incompatible")
1630            }
1631        }
1632
1633        #[allow(non_local_definitions)]
1634        impl serde::ser::StdError for Incompatible {}
1635
1636        #[allow(non_local_definitions)]
1637        impl serde::ser::Error for Incompatible {
1638            fn custom<T>(_: T) -> Self
1639            where
1640                T: fmt::Display,
1641            {
1642                Incompatible
1643            }
1644        }
1645
1646        #[allow(non_local_definitions)]
1647        impl<'a> serde::Serializer for &'a mut Extract {
1648            type Ok = ();
1649            type Error = Incompatible;
1650            type SerializeSeq = Self;
1651            type SerializeTuple = Self;
1652            type SerializeTupleStruct = Self;
1653            type SerializeTupleVariant = Self;
1654            type SerializeMap = Self;
1655            type SerializeStruct = Self;
1656            type SerializeStructVariant = Self;
1657
1658            fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
1659                Err(Incompatible)
1660            }
1661
1662            fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
1663                Err(Incompatible)
1664            }
1665
1666            fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
1667                Err(Incompatible)
1668            }
1669
1670            fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
1671                Err(Incompatible)
1672            }
1673
1674            fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
1675                Err(Incompatible)
1676            }
1677
1678            fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
1679                Err(Incompatible)
1680            }
1681
1682            fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
1683                Err(Incompatible)
1684            }
1685
1686            fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
1687                Err(Incompatible)
1688            }
1689
1690            fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
1691                Err(Incompatible)
1692            }
1693
1694            fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
1695                Err(Incompatible)
1696            }
1697
1698            fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
1699                Err(Incompatible)
1700            }
1701
1702            fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
1703                Err(Incompatible)
1704            }
1705
1706            fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
1707                if self.depth == 1 {
1708                    self.text_buf.reset();
1709                    self.push_link_fragment(value)?;
1710                    self.push_link()
1711                } else {
1712                    Err(Incompatible)
1713                }
1714            }
1715
1716            fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
1717                Err(Incompatible)
1718            }
1719
1720            fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
1721                Err(Incompatible)
1722            }
1723
1724            fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
1725            where
1726                T: ?Sized + serde::Serialize,
1727            {
1728                value.serialize(self)
1729            }
1730
1731            fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
1732                Err(Incompatible)
1733            }
1734
1735            fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
1736                name.serialize(self)
1737            }
1738
1739            fn serialize_newtype_struct<T>(
1740                self,
1741                _: &'static str,
1742                value: &T,
1743            ) -> Result<Self::Ok, Self::Error>
1744            where
1745                T: ?Sized + serde::Serialize,
1746            {
1747                value.serialize(self)
1748            }
1749
1750            fn serialize_newtype_variant<T>(
1751                self,
1752                _: &'static str,
1753                _: u32,
1754                _: &'static str,
1755                value: &T,
1756            ) -> Result<Self::Ok, Self::Error>
1757            where
1758                T: ?Sized + serde::Serialize,
1759            {
1760                value.serialize(self)
1761            }
1762
1763            fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
1764                self.down()?;
1765                Ok(self)
1766            }
1767
1768            fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
1769                self.down()?;
1770                Ok(self)
1771            }
1772
1773            fn serialize_tuple_struct(
1774                self,
1775                _: &'static str,
1776                _: usize,
1777            ) -> Result<Self::SerializeTupleStruct, Self::Error> {
1778                self.down()?;
1779                Ok(self)
1780            }
1781
1782            fn serialize_tuple_variant(
1783                self,
1784                _: &'static str,
1785                _: u32,
1786                _: &'static str,
1787                _: usize,
1788            ) -> Result<Self::SerializeTupleVariant, Self::Error> {
1789                self.down()?;
1790                Ok(self)
1791            }
1792
1793            fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
1794                self.down()?;
1795                Ok(self)
1796            }
1797
1798            fn serialize_struct(
1799                self,
1800                _: &'static str,
1801                _: usize,
1802            ) -> Result<Self::SerializeStruct, Self::Error> {
1803                self.down()?;
1804                Ok(self)
1805            }
1806
1807            fn serialize_struct_variant(
1808                self,
1809                _: &'static str,
1810                _: u32,
1811                _: &'static str,
1812                _: usize,
1813            ) -> Result<Self::SerializeStructVariant, Self::Error> {
1814                self.down()?;
1815                Ok(self)
1816            }
1817
1818            fn serialize_unit_variant(
1819                self,
1820                _: &'static str,
1821                _: u32,
1822                variant: &'static str,
1823            ) -> Result<Self::Ok, Self::Error> {
1824                variant.serialize(self)
1825            }
1826        }
1827
1828        #[allow(non_local_definitions)]
1829        impl<'a> serde::ser::SerializeSeq for &'a mut Extract {
1830            type Ok = ();
1831            type Error = Incompatible;
1832
1833            fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
1834            where
1835                T: ?Sized + serde::Serialize,
1836            {
1837                value.serialize(&mut **self)
1838            }
1839
1840            fn end(self) -> Result<Self::Ok, Self::Error> {
1841                self.up()?;
1842                Ok(())
1843            }
1844        }
1845
1846        #[allow(non_local_definitions)]
1847        impl<'a> serde::ser::SerializeTuple for &'a mut Extract {
1848            type Ok = ();
1849            type Error = Incompatible;
1850
1851            fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
1852            where
1853                T: ?Sized + serde::Serialize,
1854            {
1855                value.serialize(&mut **self)
1856            }
1857
1858            fn end(self) -> Result<Self::Ok, Self::Error> {
1859                self.up()?;
1860                Ok(())
1861            }
1862        }
1863
1864        #[allow(non_local_definitions)]
1865        impl<'a> serde::ser::SerializeTupleStruct for &'a mut Extract {
1866            type Ok = ();
1867            type Error = Incompatible;
1868
1869            fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
1870            where
1871                T: ?Sized + serde::Serialize,
1872            {
1873                value.serialize(&mut **self)
1874            }
1875
1876            fn end(self) -> Result<Self::Ok, Self::Error> {
1877                self.up()?;
1878                Ok(())
1879            }
1880        }
1881
1882        #[allow(non_local_definitions)]
1883        impl<'a> serde::ser::SerializeTupleVariant for &'a mut Extract {
1884            type Ok = ();
1885            type Error = Incompatible;
1886
1887            fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
1888            where
1889                T: ?Sized + serde::Serialize,
1890            {
1891                value.serialize(&mut **self)
1892            }
1893
1894            fn end(self) -> Result<Self::Ok, Self::Error> {
1895                self.up()?;
1896                Ok(())
1897            }
1898        }
1899
1900        #[allow(non_local_definitions)]
1901        impl<'a> serde::ser::SerializeMap for &'a mut Extract {
1902            type Ok = ();
1903            type Error = Incompatible;
1904
1905            fn serialize_key<T>(&mut self, _: &T) -> Result<(), Self::Error>
1906            where
1907                T: ?Sized + serde::Serialize,
1908            {
1909                Err(Incompatible)
1910            }
1911
1912            fn serialize_value<T>(&mut self, _: &T) -> Result<(), Self::Error>
1913            where
1914                T: ?Sized + serde::Serialize,
1915            {
1916                Err(Incompatible)
1917            }
1918
1919            fn end(self) -> Result<Self::Ok, Self::Error> {
1920                self.up()?;
1921                Ok(())
1922            }
1923        }
1924
1925        #[allow(non_local_definitions)]
1926        impl<'a> serde::ser::SerializeStruct for &'a mut Extract {
1927            type Ok = ();
1928            type Error = Incompatible;
1929
1930            fn serialize_field<T>(&mut self, _: &'static str, _: &T) -> Result<(), Self::Error>
1931            where
1932                T: ?Sized + serde::Serialize,
1933            {
1934                Err(Incompatible)
1935            }
1936
1937            fn end(self) -> Result<Self::Ok, Self::Error> {
1938                self.up()?;
1939                Ok(())
1940            }
1941        }
1942
1943        #[allow(non_local_definitions)]
1944        impl<'a> serde::ser::SerializeStructVariant for &'a mut Extract {
1945            type Ok = ();
1946            type Error = Incompatible;
1947
1948            fn serialize_field<T>(&mut self, _: &'static str, _: &T) -> Result<(), Self::Error>
1949            where
1950                T: ?Sized + serde::Serialize,
1951            {
1952                Err(Incompatible)
1953            }
1954
1955            fn end(self) -> Result<Self::Ok, Self::Error> {
1956                self.up()?;
1957                Ok(())
1958            }
1959        }
1960
1961        let mut extract = Extract::default();
1962        value.serialize(&mut extract).ok()?;
1963
1964        Some(extract.end())
1965    }
1966
1967    #[cfg(test)]
1968    mod tests {
1969        use super::*;
1970
1971        use std::collections::BTreeSet;
1972
1973        #[test]
1974        fn span_link_set() {
1975            let mut set = SpanLinkSet::new();
1976
1977            assert_eq!(0, set.len());
1978            assert!(set.is_empty());
1979            assert!(!set.contains(SpanLink::new(
1980                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
1981                SpanId::from_u64(0x0123456789abcdef).unwrap(),
1982            )));
1983
1984            set.insert(SpanLink::new(
1985                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
1986                SpanId::from_u64(0x0123456789abcdef).unwrap(),
1987            ));
1988
1989            assert_eq!(1, set.len());
1990            assert!(set.contains(SpanLink::new(
1991                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
1992                SpanId::from_u64(0x0123456789abcdef).unwrap(),
1993            )));
1994
1995            set.insert(SpanLink::new(
1996                TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
1997                SpanId::from_u64(0xfedcba9876543210).unwrap(),
1998            ));
1999
2000            assert_eq!(2, set.len());
2001
2002            assert!(!set.insert(SpanLink::new(
2003                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2004                SpanId::from_u64(0x0123456789abcdef).unwrap(),
2005            )));
2006            assert_eq!(2, set.len());
2007
2008            set.clear();
2009
2010            assert_eq!(0, set.len());
2011            assert!(set.is_empty());
2012        }
2013
2014        #[test]
2015        fn span_link_set_roundtrip() {
2016            for case in [
2017                SpanLinkSet::new(),
2018                {
2019                    let mut set = SpanLinkSet::new();
2020                    set.insert(SpanLink::new(
2021                        TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2022                        SpanId::from_u64(0x0123456789abcdef).unwrap(),
2023                    ));
2024                    set
2025                },
2026                {
2027                    let mut set = SpanLinkSet::new();
2028                    set.insert(SpanLink::new(
2029                        TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2030                        SpanId::from_u64(0x0123456789abcdef).unwrap(),
2031                    ));
2032                    set.insert(SpanLink::new(
2033                        TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2034                        SpanId::from_u64(0xfedcba9876543210).unwrap(),
2035                    ));
2036                    set
2037                },
2038            ] {
2039                let fmt = case.to_string();
2040                assert_eq!(Some(case), SpanLinkSet::try_from_str(&fmt).ok(), "{fmt}");
2041            }
2042        }
2043
2044        #[test]
2045        fn span_link_set_from_iter() {
2046            let mut set = SpanLinkSet::from_iter([
2047                SpanLink::new(
2048                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2049                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
2050                ),
2051                SpanLink::new(
2052                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2053                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
2054                ),
2055            ]);
2056
2057            assert!(set.contains(SpanLink::new(
2058                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2059                SpanId::from_u64(0x0123456789abcdef).unwrap(),
2060            )));
2061
2062            set.extend([SpanLink::new(
2063                TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2064                SpanId::from_u64(0xfedcba9876543210).unwrap(),
2065            )]);
2066
2067            assert!(set.contains(SpanLink::new(
2068                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2069                SpanId::from_u64(0x0123456789abcdef).unwrap(),
2070            )));
2071            assert!(set.contains(SpanLink::new(
2072                TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2073                SpanId::from_u64(0xfedcba9876543210).unwrap(),
2074            )));
2075        }
2076
2077        #[test]
2078        fn span_link_set_parse() {
2079            for (case, expected) in [
2080                (
2081                    format!("{:?}", [
2082                        SpanLink::new(
2083                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2084                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2085                        ), SpanLink::new(
2086                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2087                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2088                        )]
2089                    ),
2090                    {
2091                        let mut set = SpanLinkSet::new();
2092                        set.insert(SpanLink::new(
2093                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2094                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2095                        ));
2096                        set.insert(SpanLink::new(
2097                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2098                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2099                        ));
2100                        set
2101                    },
2102                ),
2103                (
2104                    format!("{:?}", ["0123456789abcdef0123456789abcdef-0123456789abcdef", "fedcba9876543210fedcba9876543210-fedcba9876543210"]),
2105                    {
2106                        let mut set = SpanLinkSet::new();
2107                        set.insert(SpanLink::new(
2108                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2109                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2110                        ));
2111                        set.insert(SpanLink::new(
2112                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2113                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2114                        ));
2115                        set
2116                    },
2117                ),
2118                (
2119                    format!("{:?}", (
2120                        SpanLink::new(
2121                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2122                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2123                        ), SpanLink::new(
2124                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2125                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2126                        ))
2127                    ),
2128                    {
2129                        let mut set = SpanLinkSet::new();
2130                        set.insert(SpanLink::new(
2131                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2132                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2133                        ));
2134                        set.insert(SpanLink::new(
2135                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2136                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2137                        ));
2138                        set
2139                    },
2140                ),
2141                (
2142                    format!("{:?}", {
2143                        let mut set = BTreeSet::new();
2144                        set.insert(SpanLink::new(
2145                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2146                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2147                        ));
2148                        set.insert(SpanLink::new(
2149                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2150                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2151                        ));
2152                        set
2153                    }),
2154                    {
2155                        let mut set = SpanLinkSet::new();
2156                        set.insert(SpanLink::new(
2157                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2158                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2159                        ));
2160                        set.insert(SpanLink::new(
2161                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2162                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2163                        ));
2164                        set
2165                    },
2166                ),
2167                (
2168                    format!("{:?}", {
2169                        let mut set = BTreeSet::new();
2170                        set.insert("0123456789abcdef0123456789abcdef-0123456789abcdef");
2171                        set.insert("fedcba9876543210fedcba9876543210-fedcba9876543210");
2172                        set
2173                    }),
2174                    {
2175                        let mut set = SpanLinkSet::new();
2176                        set.insert(SpanLink::new(
2177                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2178                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2179                        ));
2180                        set.insert(SpanLink::new(
2181                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2182                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2183                        ));
2184                        set
2185                    },
2186                ),
2187                (
2188                    "[ 0123456789abcdef0123456789abcdef-0123456789abcdef , fedcba9876543210fedcba9876543210-fedcba9876543210 ]".to_string(),
2189                    {
2190                        let mut set = SpanLinkSet::new();
2191                        set.insert(SpanLink::new(
2192                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2193                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2194                        ));
2195                        set.insert(SpanLink::new(
2196                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2197                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2198                        ));
2199                        set
2200                    },
2201                ),
2202                (
2203                    "[ \"0123456789abcdef0123456789abcdef-0123456789abcdef\" , \"fedcba9876543210fedcba9876543210-fedcba9876543210\" ]".to_string(),
2204                    {
2205                        let mut set = SpanLinkSet::new();
2206                        set.insert(SpanLink::new(
2207                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2208                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
2209                        ));
2210                        set.insert(SpanLink::new(
2211                            TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2212                            SpanId::from_u64(0xfedcba9876543210).unwrap(),
2213                        ));
2214                        set
2215                    },
2216                ),
2217                ("[]".to_string(), SpanLinkSet::new()),
2218            ] {
2219                assert_eq!(
2220                    Some(expected),
2221                    SpanLinkSet::try_from_str(&case).ok(),
2222                    "{case}"
2223                );
2224            }
2225        }
2226
2227        #[test]
2228        fn span_link_set_to_from_value() {
2229            for case in [{
2230                let mut set = SpanLinkSet::new();
2231                set.insert(SpanLink::new(
2232                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2233                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
2234                ));
2235                set.insert(SpanLink::new(
2236                    TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2237                    SpanId::from_u64(0xfedcba9876543210).unwrap(),
2238                ));
2239                set
2240            }] {
2241                assert_eq!(case, SpanLinkSet::from_value(case.to_value()).unwrap());
2242            }
2243        }
2244
2245        #[test]
2246        fn span_link_set_from_value_string() {
2247            for (case, expected) in [(
2248                "[0123456789abcdef0123456789abcdef-0123456789abcdef,fedcba9876543210fedcba9876543210-fedcba9876543210]",
2249                {
2250                    let mut set = SpanLinkSet::new();
2251                    set.insert(SpanLink::new(
2252                        TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2253                        SpanId::from_u64(0x0123456789abcdef).unwrap(),
2254                    ));
2255                    set.insert(SpanLink::new(
2256                        TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2257                        SpanId::from_u64(0xfedcba9876543210).unwrap(),
2258                    ));
2259                    set
2260                },
2261            )] {
2262                assert_eq!(expected, Value::from(case).cast().unwrap());
2263            }
2264        }
2265
2266        #[test]
2267        fn span_link_set_from_value_structured() {
2268            #[cfg(feature = "sval")]
2269            trait CaseSval: sval::Value {}
2270            #[cfg(feature = "sval")]
2271            impl<T: sval::Value> CaseSval for T {}
2272            #[cfg(not(feature = "sval"))]
2273            trait CaseSval {}
2274            #[cfg(not(feature = "sval"))]
2275            impl<T> CaseSval for T {}
2276
2277            #[cfg(feature = "serde")]
2278            trait CaseSerde: serde::Serialize {}
2279            #[cfg(feature = "serde")]
2280            impl<T: serde::Serialize> CaseSerde for T {}
2281            #[cfg(not(feature = "serde"))]
2282            trait CaseSerde {}
2283            #[cfg(not(feature = "serde"))]
2284            impl<T> CaseSerde for T {}
2285
2286            trait Case: CaseSval + CaseSerde + fmt::Debug {}
2287            impl<T: fmt::Debug + CaseSval + CaseSerde> Case for T {}
2288
2289            fn case(case: &impl Case, expected: &SpanLinkSet) {
2290                assert_eq!(expected, &Value::from_debug(case).cast().unwrap());
2291
2292                #[cfg(feature = "sval")]
2293                {
2294                    assert_eq!(expected, &Value::from_sval(case).cast().unwrap());
2295                }
2296
2297                #[cfg(feature = "serde")]
2298                {
2299                    assert_eq!(expected, &Value::from_serde(case).cast().unwrap());
2300                }
2301            }
2302
2303            let expected = {
2304                let mut set = SpanLinkSet::new();
2305                set.insert(SpanLink::new(
2306                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2307                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
2308                ));
2309                set.insert(SpanLink::new(
2310                    TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2311                    SpanId::from_u64(0xfedcba9876543210).unwrap(),
2312                ));
2313                set
2314            };
2315
2316            case(
2317                &[
2318                    "0123456789abcdef0123456789abcdef-0123456789abcdef",
2319                    "fedcba9876543210fedcba9876543210-fedcba9876543210",
2320                ],
2321                &expected,
2322            );
2323            case(
2324                &[
2325                    SpanLink::new(
2326                        TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2327                        SpanId::from_u64(0x0123456789abcdef).unwrap(),
2328                    ),
2329                    SpanLink::new(
2330                        TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2331                        SpanId::from_u64(0xfedcba9876543210).unwrap(),
2332                    ),
2333                ],
2334                &expected,
2335            );
2336
2337            let mut btree_set = alloc::collections::BTreeSet::new();
2338            btree_set.insert(SpanLink::new(
2339                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
2340                SpanId::from_u64(0x0123456789abcdef).unwrap(),
2341            ));
2342            btree_set.insert(SpanLink::new(
2343                TraceId::from_u128(0xfedcba9876543210fedcba9876543210).unwrap(),
2344                SpanId::from_u64(0xfedcba9876543210).unwrap(),
2345            ));
2346            case(&btree_set, &expected);
2347        }
2348
2349        #[test]
2350        fn err_span_link_set_invalid() {
2351            for case in [
2352                "",
2353                "<>",
2354                "0123456789abcdef0123456789abcdef-0123456789abcdef",
2355                "[0123456789abcdef0123456789abcdef-0123456789abcdef,",
2356                "[0123456789abcdef0123456789abcdef-0123456789abcdef)",
2357                "[,]",
2358                "[,,]",
2359                "[invalid]",
2360                "[0123456789abcdef0123456789abcdef-0123456789abcdef,invalid]",
2361                "{]",
2362                "([",
2363                "[0123456789abcdef0123456789abcdef-0123456789abcdef,0123456789abcdef0123456789abcdef-0123456789abcdef]",
2364                "{0123456789abcdef0123456789Cbcdef-0123456A89abcdef,  fba9876543210fedcba9876543210-fedcba9876543210\"}",
2365            ] {
2366                assert!(SpanLinkSet::try_from_str(case).is_err(), "{case}");
2367            }
2368        }
2369    }
2370}
2371
2372#[cfg(feature = "alloc")]
2373pub use self::span_link_set::SpanLinkSet;
2374
2375/**
2376An active span in a distributed trace.
2377
2378## Creating active spans automatically
2379
2380This type is created by the [`macro@crate::span!`] macro with the `guard` control parameter, or with the [`macro@crate::new_span!`] macro.
2381
2382Call [`SpanGuard::complete_with`], or just drop the guard to complete it, passing the resulting [`Span`] to a [`Completion`].
2383
2384## Creating active spans manually
2385
2386The [`SpanGuard::new`] method can be used to construct a `SpanGuard` and [`Frame`] manually.
2387
2388Call [`SpanGuard::start`] in the closure of [`Frame::call`] or async block of [`Frame::in_future`] on the returned [`Frame`] to begin the span. Once the span is started, it will complete automatically on drop, or manually through [`SpanGuard::complete`].
2389
2390**Make sure you pass ownership of the returned `SpanGuard` into the closure in [`Frame::call`] or async block in [`Frame::in_future`]**. If you don't, the span will complete early, without its ambient context.
2391*/
2392pub struct SpanGuard<'a, T: Clock, P: Props, F: Completion> {
2393    state: SpanGuardState<T>,
2394    // `data` is `None` if the span is completed
2395    data: Option<SpanGuardData<'a, P>>,
2396    // `completion` is `None` if the span is disabled
2397    completion: Option<F>,
2398}
2399
2400struct SpanGuardData<'a, P: Props> {
2401    mdl: Path<'a>,
2402    ctxt: SpanCtxt,
2403    props: P,
2404}
2405
2406enum SpanGuardState<T: Clock> {
2407    Initial(T),
2408    Started(Timer<T>),
2409    Completed,
2410}
2411
2412impl<T: Clock> SpanGuardState<T> {
2413    fn take(&mut self) -> Self {
2414        mem::replace(self, SpanGuardState::Completed)
2415    }
2416}
2417
2418impl<'a, T: Clock, P: Props, F: Completion> Drop for SpanGuard<'a, T, P, F> {
2419    fn drop(&mut self) {
2420        self.complete_default();
2421    }
2422}
2423
2424impl<'a, 'b, P: Props, E: Emitter, C: Ctxt, T: Clock>
2425    SpanGuard<'a, &'b T, P, completion::Default<'a, &'b E, &'b C, Level>>
2426{
2427    /**
2428    Create a new active span.
2429
2430    This method defers to [`SpanGuard::new`], using the components of the given [`Runtime`]. See the docs for [`SpanGuard::new`] for details on using the returned [`SpanGuard`] and [`Frame`].
2431    */
2432    pub fn from_runtime<F: Filter, R: Rng>(
2433        rt: &'b Runtime<E, F, C, T, R>,
2434        ctxt_props: impl Props,
2435        span_mdl: impl Into<Path<'a>>,
2436        span_props: P,
2437    ) -> (Self, Frame<&'b C>) {
2438        Self::new(
2439            rt.filter(),
2440            rt.ctxt(),
2441            rt.clock(),
2442            rt.rng(),
2443            completion::default(rt.emitter(), rt.ctxt()),
2444            ctxt_props,
2445            span_mdl,
2446            span_props,
2447        )
2448    }
2449}
2450
2451impl<'a, T: Clock, P: Props, F: Completion> SpanGuard<'a, T, P, F> {
2452    /**
2453    Create a new active span.
2454
2455    This method takes a number of parameters to construct a span. They are:
2456
2457    - `filter`, `ctxt`, `clock`, `rng`: These typically come from a [`crate::runtime::Runtime`], like [`crate::runtime::shared`].
2458    - `completion`: A [`Completion`] that will be used by default when the returned `SpanGuard` is completed.
2459    - `ctxt_props`: A set of [`Props`] that will be pushed to the ambient context.
2460    - `span_mdl`, `span_props`: The input parameters to [`Span::new`] used to construct a span when the guard is completed.
2461
2462    This method constructs a span based on the input properties and current context as follows:
2463
2464    - A [`SpanCtxt`] for the span is generated using [`SpanCtxt::new_child`].
2465    - The filter is checked to see if the span should be enabled or disabled. The event passed to the filter is a [`Span`] carrying the generated span context, as well as `ctxt_props` and `span_props`, but without an extent.
2466
2467    This method returns a tuple of a `SpanGuard` for starting and completing the span, and a [`Frame`] carrying the generated [`SpanCtxt`] and `ctxt_props`.
2468
2469    Call [`SpanGuard::start`] in the closure of [`Frame::call`] or async block of [`Frame::in_future`] on the returned [`Frame`] to begin the span. Once the span is started, it will complete automatically on drop, or manually through [`SpanGuard::complete`].
2470
2471    **Make sure you pass ownership of the returned `SpanGuard` into the closure in [`Frame::call`] or async block in [`Frame::in_future`]**. If you don't, the span will complete early, without its ambient context.
2472    */
2473    pub fn new<C: Ctxt>(
2474        filter: impl Filter,
2475        ctxt: C,
2476        clock: T,
2477        rng: impl Rng,
2478        completion: F,
2479        ctxt_props: impl Props,
2480        span_mdl: impl Into<Path<'a>>,
2481        span_props: P,
2482    ) -> (Self, Frame<C>) {
2483        let span_mdl = span_mdl.into();
2484
2485        let span_ctxt = SpanCtxt::current(&ctxt).new_child(rng);
2486
2487        // Check whether the span should be constructed using a dummy event
2488        let is_enabled = ctxt.with_current(|current_ctxt_props| {
2489            filter.matches(
2490                Span::new(
2491                    span_mdl.by_ref(),
2492                    Empty,
2493                    (&span_props)
2494                        .and_props(&ctxt_props)
2495                        .and_props(span_ctxt)
2496                        .and_props(current_ctxt_props),
2497                )
2498                .to_event()
2499                .with_tpl(START_TEMPLATE.by_ref()),
2500            )
2501        });
2502
2503        // Create a guard for the span
2504        // This can be completed automatically by dropping
2505        // or manually through the `complete` method
2506        let guard = SpanGuard {
2507            state: SpanGuardState::Initial(clock),
2508            data: Some(SpanGuardData {
2509                mdl: span_mdl,
2510                ctxt: span_ctxt,
2511                props: span_props,
2512            }),
2513            completion: if is_enabled { Some(completion) } else { None },
2514        };
2515
2516        // Create a frame for the span props
2517        // This includes the trace and span ids
2518        let frame = guard.push_ctxt(ctxt, ctxt_props);
2519
2520        (guard, frame)
2521    }
2522
2523    fn push_ctxt<C: Ctxt>(&self, ctxt: C, ctxt_props: impl Props) -> Frame<C> {
2524        let span_ctxt = self.data.as_ref().expect("span is already complete").ctxt;
2525
2526        if self.is_enabled() {
2527            Frame::push(ctxt, ctxt_props.and_props(span_ctxt))
2528        } else {
2529            Frame::disabled(ctxt, ctxt_props.and_props(span_ctxt))
2530        }
2531    }
2532
2533    /**
2534    Start the span.
2535
2536    From this point the span can be completed by either dropping this value, or by calling [`SpanGuard::complete`].
2537    */
2538    pub fn start(&mut self) {
2539        let state = mem::replace(&mut self.state, SpanGuardState::Completed);
2540
2541        let SpanGuardState::Initial(clock) = state else {
2542            self.state = state;
2543            return;
2544        };
2545
2546        self.state = SpanGuardState::Started(Timer::start(clock));
2547    }
2548
2549    /**
2550    Whether the span will call its completion.
2551
2552    If the filter called in [`SpanGuard::start`] evaluated to `false` then this method will also return `false`.
2553    */
2554    pub fn is_enabled(&self) -> bool {
2555        self.completion.is_some()
2556    }
2557
2558    /**
2559    Set the default completion that will be called when the span is dropped or [`SpanGuard::complete`] is called.
2560
2561    Note that the [`Span`] passed to the [`Completion`] *will not* include properties from the ambient context.
2562    This means getting the [`SpanCtxt`] via [`Span::ctxt`] will likely return `None`.
2563    You can pull the [`SpanCtxt`] from the ambient [`Ctxt`]
2564    */
2565    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2566    pub fn with_completion<U: Completion>(mut self, completion: U) -> SpanGuard<'a, T, P, U> {
2567        // Ensure this guard won't complete on drop
2568        self.completion.take();
2569
2570        SpanGuard {
2571            state: self.state.take(),
2572            data: self.data.take(),
2573            completion: Some(completion),
2574        }
2575    }
2576
2577    /**
2578    Set the module of the span.
2579    */
2580    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2581    pub fn with_mdl(mut self, mdl: impl Into<Path<'a>>) -> Self {
2582        if let Some(ref mut data) = self.data {
2583            data.mdl = mdl.into();
2584        }
2585        self
2586    }
2587
2588    /**
2589    Set the name of the span.
2590    */
2591    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2592    pub fn with_name(
2593        self,
2594        name: impl Into<Str<'a>>,
2595    ) -> SpanGuard<'a, T, And<(&'static str, Str<'a>), P>, F> {
2596        self.map_props(|props| (KEY_SPAN_NAME, name.into()).and_props(props))
2597    }
2598
2599    /**
2600    Set the kind of the span.
2601    */
2602    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2603    pub fn with_kind(
2604        self,
2605        kind: impl Into<SpanKind>,
2606    ) -> SpanGuard<'a, T, And<(&'static str, SpanKind), P>, F> {
2607        self.map_props(|props| (KEY_SPAN_KIND, kind.into()).and_props(props))
2608    }
2609
2610    /**
2611    Set the links of the span.
2612    */
2613    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2614    #[cfg(feature = "alloc")]
2615    pub fn with_links(
2616        self,
2617        links: impl Into<SpanLinkSet>,
2618    ) -> SpanGuard<'a, T, And<(&'static str, SpanLinkSet), P>, F> {
2619        self.map_props(|props| (KEY_SPAN_LINKS, links.into()).and_props(props))
2620    }
2621
2622    /**
2623    Set the properties of the span.
2624
2625    If the span is disabled then this method is a no-op.
2626    */
2627    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2628    pub fn with_props<U: Props>(self, props: U) -> SpanGuard<'a, T, U, F> {
2629        self.map_props(|_| props)
2630    }
2631
2632    /**
2633    Map the properties of the span.
2634
2635    If the span is disabled then this method is a no-op.
2636    */
2637    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2638    pub fn map_props<U: Props>(mut self, map: impl FnOnce(P) -> U) -> SpanGuard<'a, T, U, F> {
2639        let data = self.data.take().map(|data| SpanGuardData {
2640            mdl: data.mdl,
2641            ctxt: data.ctxt,
2642            props: map(data.props),
2643        });
2644
2645        SpanGuard {
2646            state: self.state.take(),
2647            data,
2648            completion: self.completion.take(),
2649        }
2650    }
2651
2652    /**
2653    Push a property onto the span.
2654    */
2655    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2656    pub fn push_prop<K: ToStr, V: ToValue>(
2657        self,
2658        key: K,
2659        value: V,
2660    ) -> SpanGuard<'a, T, And<(K, V), P>, F> {
2661        self.push_props((key, value))
2662    }
2663
2664    /**
2665    Push a set of properties onto the span.
2666    */
2667    #[must_use = "this method returns a new `SpanGuard` that will be immediately dropped unless used"]
2668    pub fn push_props<U: Props>(self, props: U) -> SpanGuard<'a, T, And<U, P>, F> {
2669        self.map_props(|current| props.and_props(current))
2670    }
2671
2672    /**
2673    Get exclusive access to the properties of the span.
2674
2675    If the span is disabled this method will return `None`.
2676    */
2677    pub fn props_mut(&mut self) -> Option<&mut P> {
2678        self.data.as_mut().map(|data| &mut data.props)
2679    }
2680
2681    /**
2682    Complete the span.
2683
2684    If the span is disabled then this method is a no-op and will return `false`.
2685    */
2686    pub fn complete(mut self) -> bool {
2687        self.complete_default()
2688    }
2689
2690    fn complete_default(&mut self) -> bool {
2691        if let (SpanGuardState::Started(timer), Some(data), Some(completion)) =
2692            (self.state.take(), self.data.take(), self.completion.take())
2693        {
2694            completion.complete(Span::new(data.mdl, timer, data.props));
2695
2696            true
2697        } else {
2698            false
2699        }
2700    }
2701
2702    /**
2703    Complete the span with the given closure.
2704
2705    If the span is disabled then the `complete` closure won't be called and this method will return `false`.
2706    */
2707    pub fn complete_with(mut self, completion: impl Completion) -> bool {
2708        if let (SpanGuardState::Started(timer), Some(data), Some(_)) =
2709            (self.state.take(), self.data.take(), self.completion.take())
2710        {
2711            completion.complete(Span::new(data.mdl, timer, data.props));
2712
2713            true
2714        } else {
2715            false
2716        }
2717    }
2718}
2719
2720pub mod completion {
2721    /*!
2722    The [`Completion`] type.
2723
2724    A [`Completion`] is a visitor for a [`Span`] that's called by a [`crate::span::SpanGuard`] when it completes.
2725    */
2726
2727    use emit_core::{
2728        ctxt::Ctxt,
2729        emitter::Emitter,
2730        empty::Empty,
2731        event::ToEvent,
2732        props::{ErasedProps, Props},
2733        runtime::Runtime,
2734        template::Template,
2735        value::{ToValue, Value},
2736        well_known::{KEY_ERR, KEY_LVL},
2737    };
2738
2739    use crate::{level::Level, span::Span};
2740
2741    use core::fmt;
2742
2743    /**
2744    A receiver of [`Span`]s as they're completed by [`crate::span::SpanGuard`]s.
2745    */
2746    pub trait Completion {
2747        /**
2748        Receive a completing span.
2749        */
2750        fn complete<P: Props>(&self, span: Span<P>);
2751    }
2752
2753    impl<'a, C: Completion + ?Sized> Completion for &'a C {
2754        fn complete<P: Props>(&self, span: Span<P>) {
2755            (**self).complete(span)
2756        }
2757    }
2758
2759    impl Completion for Empty {
2760        fn complete<P: Props>(&self, _: Span<P>) {}
2761    }
2762
2763    /**
2764    A default [`Completion`] that emits spans through an [`Emitter`].
2765
2766    This type is a more sophisticated variant of [`FromEmitter`] that will:
2767
2768    - Include ambient context from `C` on span events.
2769    - Detect panics and assign an error if it observes one.
2770
2771    This type can be created directly, or via [`default`].
2772    */
2773    pub struct Default<'a, E, C, L = Level> {
2774        emitter: E,
2775        ctxt: C,
2776        tpl: Option<Template<'a>>,
2777        lvl: Option<L>,
2778        panic_lvl: Option<L>,
2779    }
2780
2781    impl<'a, E: Emitter, C: Ctxt, L: ToValue> Completion for Default<'a, E, C, L> {
2782        fn complete<P: Props>(&self, span: Span<P>) {
2783            fn is_panicking() -> bool {
2784                #[cfg(feature = "std")]
2785                {
2786                    std::thread::panicking()
2787                }
2788                #[cfg(not(feature = "std"))]
2789                {
2790                    false
2791                }
2792            }
2793
2794            let completion_props = if is_panicking() {
2795                [
2796                    self.panic_lvl
2797                        .as_ref()
2798                        .map(|lvl| Value::from_any(lvl))
2799                        .or_else(|| Some(Value::from_any(&Level::Error)))
2800                        .map(|lvl| (KEY_LVL, lvl)),
2801                    Some((KEY_ERR, Value::from_any(&PanicError::UNKNOWN))),
2802                ]
2803            } else {
2804                [
2805                    self.lvl
2806                        .as_ref()
2807                        .map(|lvl| Value::from_any(lvl))
2808                        .map(|lvl| (KEY_LVL, lvl)),
2809                    None,
2810                ]
2811            };
2812
2813            let tpl = self.tpl.as_ref().unwrap_or_else(|| span.tpl()).by_ref();
2814
2815            let evt = span
2816                .to_event()
2817                .with_tpl(tpl)
2818                .map_props(|span_props| completion_props.and_props(span_props));
2819
2820            emit_core::emit(&self.emitter, Empty, &self.ctxt, Empty, evt);
2821        }
2822    }
2823
2824    impl<'a, 'b, E: Emitter, C: Ctxt, L> Default<'a, &'b E, &'b C, L> {
2825        /**
2826        Create a default completion from the given runtime.
2827        */
2828        pub fn from_runtime<F, T, R>(rt: &'b Runtime<E, F, C, T, R>) -> Self {
2829            Self::new(rt.emitter(), rt.ctxt())
2830        }
2831    }
2832
2833    impl<'a, E, C, L> Default<'a, E, C, L> {
2834        /**
2835        Wrap the given emitter and context.
2836        */
2837        pub const fn new(emitter: E, ctxt: C) -> Self {
2838            Default {
2839                emitter,
2840                ctxt,
2841                tpl: None,
2842                lvl: None,
2843                panic_lvl: None,
2844            }
2845        }
2846
2847        /**
2848        A level to assign to the span on completion.
2849
2850        If the completion is called outside of a panic, this level will be used.
2851        */
2852        pub fn with_lvl(self, lvl: L) -> Self {
2853            Default {
2854                emitter: self.emitter,
2855                ctxt: self.ctxt,
2856                tpl: self.tpl,
2857                lvl: Some(lvl),
2858                panic_lvl: self.panic_lvl,
2859            }
2860        }
2861
2862        /**
2863        A level to assign to the span on completion during a panic.
2864        */
2865        pub fn with_panic_lvl(self, lvl: L) -> Self {
2866            Default {
2867                emitter: self.emitter,
2868                ctxt: self.ctxt,
2869                tpl: self.tpl,
2870                lvl: self.lvl,
2871                panic_lvl: Some(lvl),
2872            }
2873        }
2874
2875        /**
2876        A template to use for the span on completion.
2877        */
2878        pub fn with_tpl<'b>(self, tpl: impl Into<Template<'b>>) -> Default<'b, E, C, L> {
2879            Default {
2880                emitter: self.emitter,
2881                ctxt: self.ctxt,
2882                tpl: Some(tpl.into()),
2883                lvl: self.lvl,
2884                panic_lvl: self.panic_lvl,
2885            }
2886        }
2887    }
2888
2889    /**
2890    Create a default [`Completion`] from an [`Emitter`] and [`Ctxt`].
2891
2892    On completion, a [`Span`] will be emitted as an event using [`Span::to_event`].
2893
2894    If the completion is called during a panic, it will attach an error to the span.
2895    */
2896    pub const fn default<'a, E: Emitter, C: Ctxt>(emitter: E, ctxt: C) -> Default<'a, E, C> {
2897        Default::new(emitter, ctxt)
2898    }
2899
2900    /**
2901    Create a default [`Completion`] from a [`Runtime`].
2902
2903    On completion, a [`Span`] will be emitted as an event using [`Span::to_event`].
2904
2905    If the completion is called during a panic, it will attach an error to the span.
2906    */
2907    pub fn default_from_runtime<'a, 'b, E: Emitter, F, C: Ctxt, T, R>(
2908        rt: &'b Runtime<E, F, C, T, R>,
2909    ) -> Default<'a, &'b E, &'b C> {
2910        Default::from_runtime(rt)
2911    }
2912
2913    pub(crate) struct PanicError {
2914        #[cfg(feature = "std")]
2915        payload: Option<std::borrow::Cow<'static, str>>,
2916        #[cfg(not(feature = "std"))]
2917        payload: Option<&'static str>,
2918    }
2919
2920    impl PanicError {
2921        const UNKNOWN: Self = PanicError { payload: None };
2922
2923        #[cfg(feature = "std")]
2924        pub(crate) fn extract(payload: &Box<dyn std::any::Any + Send>) -> Self {
2925            if let Some(payload) = payload.downcast_ref::<&str>() {
2926                return PanicError {
2927                    payload: Some(std::borrow::Cow::Borrowed(payload)),
2928                };
2929            }
2930
2931            if let Some(payload) = payload.downcast_ref::<std::string::String>() {
2932                return PanicError {
2933                    payload: Some(std::borrow::Cow::Owned(payload.clone())),
2934                };
2935            }
2936
2937            PanicError { payload: None }
2938        }
2939
2940        pub(crate) fn get(&self) -> &str {
2941            let Some(ref payload) = self.payload else {
2942                return "panicked";
2943            };
2944
2945            payload
2946        }
2947    }
2948
2949    impl fmt::Debug for PanicError {
2950        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2951            fmt::Debug::fmt(self.get(), f)
2952        }
2953    }
2954
2955    impl fmt::Display for PanicError {
2956        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2957            fmt::Display::fmt(self.get(), f)
2958        }
2959    }
2960
2961    #[cfg(feature = "std")]
2962    impl std::error::Error for PanicError {}
2963
2964    impl ToValue for PanicError {
2965        fn to_value(&self) -> Value<'_> {
2966            #[cfg(feature = "std")]
2967            {
2968                Value::capture_error(self)
2969            }
2970            #[cfg(not(feature = "std"))]
2971            {
2972                Value::capture_display(self)
2973            }
2974        }
2975    }
2976
2977    /**
2978    A [`Completion`] from an [`Emitter`].
2979
2980    On completion, a [`Span`] will be emitted as an event using [`Span::to_event`].
2981
2982    This type can be created directly, or via [`from_emitter`].
2983    */
2984    pub struct FromEmitter<E>(E);
2985
2986    impl<E: Emitter> Completion for FromEmitter<E> {
2987        fn complete<P: Props>(&self, span: Span<P>) {
2988            self.0.emit(span)
2989        }
2990    }
2991
2992    impl<E> FromEmitter<E> {
2993        /**
2994        Wrap the given emitter.
2995        */
2996        pub const fn new(emitter: E) -> Self {
2997            FromEmitter(emitter)
2998        }
2999    }
3000
3001    /**
3002    Create a [`Completion`] from an [`Emitter`].
3003
3004    On completion, a [`Span`] will be emitted as an event using [`Span::to_event`].
3005    */
3006    pub const fn from_emitter<E: Emitter>(emitter: E) -> FromEmitter<E> {
3007        FromEmitter(emitter)
3008    }
3009
3010    /**
3011    A [`Completion`] from a function.
3012
3013    This type can be created directly, or via [`from_fn`].
3014    */
3015    pub struct FromFn<F = fn(Span<&dyn ErasedProps>)>(F);
3016
3017    /**
3018    Create a [`Completion`] from a function.
3019    */
3020    pub const fn from_fn<F: Fn(Span<&dyn ErasedProps>)>(f: F) -> FromFn<F> {
3021        FromFn(f)
3022    }
3023
3024    impl<F> FromFn<F> {
3025        /**
3026        Wrap the given completion function.
3027        */
3028        pub const fn new(completion: F) -> FromFn<F> {
3029            FromFn(completion)
3030        }
3031    }
3032
3033    impl<F: Fn(Span<&dyn ErasedProps>)> Completion for FromFn<F> {
3034        fn complete<P: Props>(&self, span: Span<P>) {
3035            (self.0)(span.erase())
3036        }
3037    }
3038
3039    mod internal {
3040        use super::*;
3041
3042        pub trait DispatchCompletion {
3043            fn dispatch_complete(&self, span: Span<&dyn ErasedProps>);
3044        }
3045
3046        pub trait SealedCompletion {
3047            fn erase_completion(&self) -> crate::internal::Erased<&dyn DispatchCompletion>;
3048        }
3049    }
3050
3051    /**
3052    An object-safe [`Completion`].
3053
3054    A `dyn ErasedCompletion` can be treated as `impl Completion`.
3055    */
3056    pub trait ErasedCompletion: internal::SealedCompletion {}
3057
3058    impl<T: Completion> ErasedCompletion for T {}
3059
3060    impl<T: Completion> internal::SealedCompletion for T {
3061        fn erase_completion(&self) -> crate::internal::Erased<&dyn internal::DispatchCompletion> {
3062            crate::internal::Erased(self)
3063        }
3064    }
3065
3066    impl<T: Completion> internal::DispatchCompletion for T {
3067        fn dispatch_complete(&self, span: Span<&dyn ErasedProps>) {
3068            self.complete(span)
3069        }
3070    }
3071
3072    impl<'a> Completion for dyn ErasedCompletion + 'a {
3073        fn complete<P: Props>(&self, span: Span<P>) {
3074            self.erase_completion().0.dispatch_complete(span.erase())
3075        }
3076    }
3077
3078    impl<'a> Completion for dyn ErasedCompletion + Send + Sync + 'a {
3079        fn complete<P: Props>(&self, span: Span<P>) {
3080            (self as &(dyn ErasedCompletion + 'a)).complete(span)
3081        }
3082    }
3083
3084    #[cfg(test)]
3085    mod tests {
3086        use super::*;
3087        use std::cell::Cell;
3088
3089        use emit_core::{emitter, path::Path};
3090
3091        #[test]
3092        fn from_fn_completion() {
3093            let called = Cell::new(false);
3094
3095            let completion = from_fn(|span| {
3096                assert_eq!("test", span.name().unwrap());
3097
3098                called.set(true);
3099            });
3100
3101            completion.complete(Span::new(
3102                Path::new_raw("test"),
3103                Empty,
3104                ("span_name", "test"),
3105            ));
3106
3107            assert!(called.get());
3108        }
3109
3110        #[test]
3111        fn erased_completion() {
3112            let called = Cell::new(false);
3113
3114            let completion = from_fn(|span| {
3115                assert_eq!("test", span.name().unwrap());
3116
3117                called.set(true);
3118            });
3119
3120            let completion = &completion as &dyn ErasedCompletion;
3121
3122            completion.complete(Span::new(
3123                Path::new_raw("test"),
3124                Empty,
3125                ("span_name", "test"),
3126            ));
3127
3128            assert!(called.get());
3129        }
3130
3131        #[test]
3132        fn default_completion() {
3133            let called = Cell::new(false);
3134
3135            let completion = default(
3136                emitter::from_fn(|_| {
3137                    called.set(true);
3138                }),
3139                Empty,
3140            );
3141
3142            completion.complete(Span::new(Path::new_raw("test"), Empty, Empty));
3143
3144            assert!(called.get());
3145        }
3146
3147        #[test]
3148        fn default_completion_from_runtime() {
3149            let called = Cell::new(false);
3150
3151            let rt = Runtime::default().with_emitter(emitter::from_fn(|_| {
3152                called.set(true);
3153            }));
3154
3155            let completion = default_from_runtime(&rt);
3156
3157            completion.complete(Span::new(Path::new_raw("test"), Empty, Empty));
3158
3159            assert!(called.get());
3160        }
3161
3162        #[test]
3163        fn default_completion_uses_lvl() {
3164            let called = Cell::new(false);
3165
3166            let completion = default(
3167                emitter::from_fn(|evt| {
3168                    assert_eq!(Level::Info, evt.props().pull("lvl").unwrap());
3169
3170                    called.set(true);
3171                }),
3172                Empty,
3173            )
3174            .with_lvl(Level::Info);
3175
3176            completion.complete(Span::new(Path::new_raw("test"), Empty, Empty));
3177
3178            assert!(called.get());
3179        }
3180
3181        #[test]
3182        fn default_completion_uses_tpl() {
3183            let called = Cell::new(false);
3184
3185            let completion = default(
3186                emitter::from_fn(|evt| {
3187                    assert_eq!("test template", evt.msg().to_string());
3188
3189                    called.set(true);
3190                }),
3191                Empty,
3192            )
3193            .with_lvl(Level::Info)
3194            .with_tpl(Template::literal("test template"));
3195
3196            completion.complete(Span::new(Path::new_raw("test"), Empty, Empty));
3197
3198            assert!(called.get());
3199        }
3200
3201        #[cfg(feature = "std")]
3202        #[cfg(not(target_arch = "wasm32"))]
3203        struct Guard<T: Completion>(T);
3204
3205        #[cfg(feature = "std")]
3206        #[cfg(not(target_arch = "wasm32"))]
3207        impl<T: Completion> Drop for Guard<T> {
3208            fn drop(&mut self) {
3209                self.0
3210                    .complete(Span::new(Path::new_raw("test"), Empty, Empty));
3211            }
3212        }
3213
3214        #[test]
3215        #[cfg(feature = "std")]
3216        #[cfg(not(target_arch = "wasm32"))]
3217        fn default_completion_detects_panics() {
3218            let called = Cell::new(false);
3219
3220            let completion = default(
3221                emitter::from_fn(|evt| {
3222                    assert_eq!(Level::Error, evt.props().pull("lvl").unwrap());
3223                    assert!(evt.props().get("err").is_some());
3224
3225                    called.set(true);
3226                }),
3227                Empty,
3228            );
3229
3230            let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || {
3231                let _guard = Guard(completion);
3232
3233                panic!("explicit panic")
3234            }));
3235
3236            assert!(called.get());
3237        }
3238
3239        #[test]
3240        #[cfg(feature = "std")]
3241        #[cfg(not(target_arch = "wasm32"))]
3242        fn default_completion_uses_panic_lvl() {
3243            let called = Cell::new(false);
3244
3245            let completion = default(
3246                emitter::from_fn(|evt| {
3247                    assert_eq!(Level::Warn, evt.props().pull("lvl").unwrap());
3248
3249                    called.set(true);
3250                }),
3251                Empty,
3252            )
3253            .with_panic_lvl(Level::Warn);
3254
3255            let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || {
3256                let _guard = Guard(completion);
3257
3258                panic!("explicit panic")
3259            }));
3260
3261            assert!(called.get());
3262        }
3263    }
3264}
3265
3266#[cfg(test)]
3267mod tests {
3268    use super::*;
3269
3270    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3271    use emit_core::filter;
3272
3273    use std::time::Duration;
3274
3275    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3276    use std::cell::Cell;
3277
3278    use crate::Timestamp;
3279
3280    #[test]
3281    fn span_id_parse() {
3282        for (case, expected) in [
3283            (
3284                "0123456789abcdef",
3285                Ok(SpanId::from_u64(0x0123456789abcdef).unwrap()),
3286            ),
3287            (
3288                "0000000000000001",
3289                Ok(SpanId::from_u64(0x0000000000000001).unwrap()),
3290            ),
3291            ("0000000000000000", Err(ParseIdError {})),
3292            ("0x00000000000001", Err(ParseIdError {})),
3293            ("0x0000000000000001", Err(ParseIdError {})),
3294            ("1", Err(ParseIdError {})),
3295            ("", Err::<SpanId, ParseIdError>(ParseIdError {})),
3296        ] {
3297            match expected {
3298                Ok(expected) => {
3299                    assert_eq!(expected, SpanId::try_from_hex(case).unwrap());
3300                    assert_eq!(expected, SpanId::try_from_hex(case).unwrap());
3301                }
3302                Err(e) => assert_eq!(
3303                    e.to_string(),
3304                    SpanId::try_from_hex(case).unwrap_err().to_string()
3305                ),
3306            }
3307        }
3308    }
3309
3310    #[test]
3311    fn trace_id_parse() {
3312        for (case, expected) in [
3313            (
3314                "0123456789abcdef0123456789abcdef",
3315                Ok(TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap()),
3316            ),
3317            (
3318                "00000000000000000000000000000001",
3319                Ok(TraceId::from_u128(0x00000000000000000000000000000001).unwrap()),
3320            ),
3321            ("00000000000000000000000000000000", Err(ParseIdError {})),
3322            ("0x000000000000000000000000000001", Err(ParseIdError {})),
3323            ("0x00000000000000000000000000000001", Err(ParseIdError {})),
3324            ("1", Err(ParseIdError {})),
3325            ("", Err::<TraceId, ParseIdError>(ParseIdError {})),
3326        ] {
3327            match expected {
3328                Ok(expected) => assert_eq!(expected, TraceId::try_from_hex(case).unwrap()),
3329                Err(e) => assert_eq!(
3330                    e.to_string(),
3331                    TraceId::try_from_hex(case).unwrap_err().to_string()
3332                ),
3333            }
3334        }
3335    }
3336
3337    #[test]
3338    fn span_id_fmt() {
3339        for (case, expected) in [
3340            (SpanId::from_u64(1).unwrap(), "0000000000000001"),
3341            (
3342                SpanId::from_u64(0x0123456789abcdef).unwrap(),
3343                "0123456789abcdef",
3344            ),
3345        ] {
3346            assert_eq!(expected, case.to_string());
3347            assert_eq!(expected, str::from_utf8(&case.to_hex()).unwrap());
3348        }
3349    }
3350
3351    #[test]
3352    fn trace_id_fmt() {
3353        for (case, expected) in [
3354            (
3355                TraceId::from_u128(1).unwrap(),
3356                "00000000000000000000000000000001",
3357            ),
3358            (
3359                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3360                "0123456789abcdef0123456789abcdef",
3361            ),
3362        ] {
3363            assert_eq!(expected, case.to_string());
3364            assert_eq!(expected, str::from_utf8(&case.to_hex()).unwrap());
3365        }
3366    }
3367
3368    #[test]
3369    fn span_id_roundtrip() {
3370        let id = SpanId::new(NonZeroU64::new(u64::MAX / 2).unwrap());
3371
3372        let fmt = id.to_string();
3373
3374        let parsed: SpanId = fmt.parse().unwrap();
3375
3376        assert_eq!(id, parsed, "{}", fmt);
3377    }
3378
3379    #[test]
3380    fn trace_id_roundtrip() {
3381        let id = TraceId::new(NonZeroU128::new(u128::MAX / 2).unwrap());
3382
3383        let fmt = id.to_string();
3384
3385        let parsed: TraceId = fmt.parse().unwrap();
3386
3387        assert_eq!(id, parsed, "{}", fmt);
3388    }
3389
3390    #[test]
3391    fn span_id_random_empty() {
3392        assert!(SpanId::random(Empty).is_none());
3393    }
3394
3395    #[test]
3396    #[cfg(feature = "rand")]
3397    fn span_id_random_rand() {
3398        assert!(SpanId::random(crate::platform::DefaultRng::new()).is_some());
3399    }
3400
3401    #[test]
3402    fn trace_id_random_empty() {
3403        assert!(TraceId::random(Empty).is_none());
3404    }
3405
3406    #[test]
3407    #[cfg(feature = "rand")]
3408    fn trace_id_random_rand() {
3409        assert!(TraceId::random(crate::platform::DefaultRng::new()).is_some());
3410    }
3411
3412    #[test]
3413    fn span_id_to_from_value() {
3414        let id = SpanId::from_u64(u64::MAX / 2).unwrap();
3415
3416        assert_eq!(id, SpanId::from_value(id.to_value()).unwrap());
3417    }
3418
3419    #[test]
3420    fn span_id_from_value_string() {
3421        assert_eq!(
3422            SpanId::from_u64(0x0123456789abcdef).unwrap(),
3423            Value::from("0123456789abcdef").cast().unwrap()
3424        );
3425    }
3426
3427    #[test]
3428    fn span_id_from_value_u64() {
3429        assert_eq!(
3430            SpanId::from_u64(0x0123456789abcdef).unwrap(),
3431            Value::from(0x0123456789abcdefu64).cast().unwrap()
3432        );
3433    }
3434
3435    #[test]
3436    fn trace_id_to_from_value() {
3437        let id = TraceId::from_u128(u128::MAX / 2).unwrap();
3438
3439        assert_eq!(id, TraceId::from_value(id.to_value()).unwrap());
3440    }
3441
3442    #[test]
3443    fn trace_id_from_value_string() {
3444        assert_eq!(
3445            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3446            Value::from("0123456789abcdef0123456789abcdef")
3447                .cast()
3448                .unwrap()
3449        );
3450    }
3451
3452    #[test]
3453    fn trace_id_from_value_u128() {
3454        assert_eq!(
3455            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3456            Value::from(0x0123456789abcdef0123456789abcdefu128)
3457                .cast()
3458                .unwrap()
3459        );
3460    }
3461
3462    #[cfg(feature = "sval")]
3463    #[test]
3464    fn span_id_stream() {
3465        sval_test::assert_tokens(
3466            &SpanId::from_u64(0x0123456789abcdef).unwrap(),
3467            &[
3468                sval_test::Token::TextBegin(None),
3469                sval_test::Token::TextFragmentComputed("0123456789abcdef".to_owned()),
3470                sval_test::Token::TextEnd,
3471            ],
3472        );
3473    }
3474
3475    #[cfg(feature = "serde")]
3476    #[test]
3477    fn span_id_serialize() {
3478        serde_test::assert_ser_tokens(
3479            &SpanId::from_u64(0x0123456789abcdef).unwrap(),
3480            &[serde_test::Token::Str("0123456789abcdef")],
3481        );
3482    }
3483
3484    #[cfg(feature = "sval")]
3485    #[test]
3486    fn trace_id_stream() {
3487        sval_test::assert_tokens(
3488            &TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3489            &[
3490                sval_test::Token::TextBegin(None),
3491                sval_test::Token::TextFragmentComputed(
3492                    "0123456789abcdef0123456789abcdef".to_owned(),
3493                ),
3494                sval_test::Token::TextEnd,
3495            ],
3496        );
3497    }
3498
3499    #[cfg(feature = "serde")]
3500    #[test]
3501    fn trace_id_serialize() {
3502        serde_test::assert_ser_tokens(
3503            &TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3504            &[serde_test::Token::Str("0123456789abcdef0123456789abcdef")],
3505        );
3506    }
3507
3508    #[test]
3509    fn span_link_parse() {
3510        for (case, expected) in [
3511            (
3512                "0123456789abcdef0123456789abcdef-0123456789abcdef",
3513                Ok::<SpanLink, ParseLinkError>(SpanLink::new(
3514                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3515                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
3516                )),
3517            ),
3518            (
3519                "00000000000000000000000000000001-0000000000000001",
3520                Ok::<SpanLink, ParseLinkError>(SpanLink::new(
3521                    TraceId::from_u128(0x1).unwrap(),
3522                    SpanId::from_u64(0x1).unwrap(),
3523                )),
3524            ),
3525            (
3526                "00000000000000000000000000000000-0000000000000000",
3527                Err(ParseLinkError {}),
3528            ),
3529            (
3530                "0123456789abcdef0123456789abcde-0123456789abcdef",
3531                Err(ParseLinkError {}),
3532            ),
3533            (
3534                "0123456789abcdef0123456789abcdef-0123456789abcde",
3535                Err(ParseLinkError {}),
3536            ),
3537            (
3538                "0123456789abcdef0123456789abcdef 0123456789abcdef",
3539                Err(ParseLinkError {}),
3540            ),
3541            (
3542                "0123456789abcdef0123456789abcdef0123456789abcdef",
3543                Err(ParseLinkError {}),
3544            ),
3545        ] {
3546            match expected {
3547                Ok(expected) => assert_eq!(expected, SpanLink::try_from_str(case).unwrap()),
3548                Err(e) => assert_eq!(
3549                    e.to_string(),
3550                    SpanLink::try_from_str(case).unwrap_err().to_string()
3551                ),
3552            }
3553        }
3554    }
3555
3556    #[test]
3557    fn span_link_fmt() {
3558        let link = SpanLink::new(
3559            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3560            SpanId::from_u64(0x0123456789abcdef).unwrap(),
3561        );
3562
3563        assert_eq!(
3564            "0123456789abcdef0123456789abcdef-0123456789abcdef",
3565            link.to_string()
3566        );
3567    }
3568
3569    #[test]
3570    fn span_link_roundtrip() {
3571        let link = SpanLink::new(
3572            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3573            SpanId::from_u64(0x0123456789abcdef).unwrap(),
3574        );
3575
3576        assert_eq!(link, SpanLink::parse(link).unwrap());
3577    }
3578
3579    #[test]
3580    fn span_link_to_from_value() {
3581        let link = SpanLink::new(
3582            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3583            SpanId::from_u64(0x0123456789abcdef).unwrap(),
3584        );
3585
3586        assert_eq!(link, SpanLink::from_value(link.to_value()).unwrap());
3587    }
3588
3589    #[test]
3590    fn span_link_from_value_string() {
3591        assert_eq!(
3592            SpanLink::new(
3593                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3594                SpanId::from_u64(0x0123456789abcdef).unwrap(),
3595            ),
3596            Value::from("0123456789abcdef0123456789abcdef-0123456789abcdef")
3597                .cast()
3598                .unwrap()
3599        );
3600    }
3601
3602    #[cfg(feature = "sval")]
3603    #[test]
3604    fn span_link_stream() {
3605        sval_test::assert_tokens(
3606            &SpanLink::new(
3607                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3608                SpanId::from_u64(0x0123456789abcdef).unwrap(),
3609            ),
3610            &[
3611                sval_test::Token::TextBegin(None),
3612                sval_test::Token::TextFragmentComputed(
3613                    "0123456789abcdef0123456789abcdef-0123456789abcdef".to_owned(),
3614                ),
3615                sval_test::Token::TextEnd,
3616            ],
3617        );
3618    }
3619
3620    #[cfg(feature = "serde")]
3621    #[test]
3622    fn span_link_serialize() {
3623        serde_test::assert_ser_tokens(
3624            &SpanLink::new(
3625                TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3626                SpanId::from_u64(0x0123456789abcdef).unwrap(),
3627            ),
3628            &[serde_test::Token::Str(
3629                "0123456789abcdef0123456789abcdef-0123456789abcdef",
3630            )],
3631        );
3632    }
3633
3634    #[test]
3635    fn span_kind_parse() {
3636        for (case, expected) in [
3637            ("internal", Some(SpanKind::Internal)),
3638            (" internal ", Some(SpanKind::Internal)),
3639            ("server", Some(SpanKind::Server)),
3640            ("client", Some(SpanKind::Client)),
3641            ("producer", Some(SpanKind::Producer)),
3642            ("consumer", Some(SpanKind::Consumer)),
3643            ("", None),
3644            ("int", None),
3645            ("internalx", None),
3646        ] {
3647            assert_eq!(expected, SpanKind::try_from_str(case).ok());
3648        }
3649    }
3650
3651    #[test]
3652    fn span_kind_roundtrip() {
3653        for case in [
3654            SpanKind::Internal,
3655            SpanKind::Server,
3656            SpanKind::Client,
3657            SpanKind::Producer,
3658            SpanKind::Consumer,
3659        ] {
3660            assert_eq!(case, SpanKind::try_from_str(&case.to_string()).unwrap());
3661        }
3662    }
3663
3664    #[cfg(feature = "sval")]
3665    #[test]
3666    fn span_kind_stream() {
3667        sval_test::assert_tokens(
3668            &SpanKind::Internal,
3669            &[
3670                sval_test::Token::TextBegin(Some(8)),
3671                sval_test::Token::TextFragment("internal"),
3672                sval_test::Token::TextEnd,
3673            ],
3674        );
3675    }
3676
3677    #[cfg(feature = "serde")]
3678    #[test]
3679    fn span_kind_serialize() {
3680        serde_test::assert_ser_tokens(&SpanKind::Internal, &[serde_test::Token::Str("internal")]);
3681    }
3682
3683    #[test]
3684    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3685    fn span_ctxt_new() {
3686        let rng = crate::platform::DefaultRng::new();
3687        let ctxt = crate::platform::DefaultCtxt::new();
3688
3689        // Span context from an empty source is empty
3690        let root = SpanCtxt::current(&ctxt);
3691        assert_eq!(SpanCtxt::empty(), root);
3692
3693        // New root context has a new trace id and span id, but no parent
3694        let root = SpanCtxt::new_root(&rng);
3695
3696        assert!(root.span_id.is_some());
3697        assert!(root.trace_id.is_some());
3698        assert!(root.span_parent.is_none());
3699
3700        // Push the span context onto the source
3701        let mut frame = ctxt.open_push(root);
3702
3703        ctxt.enter(&mut frame);
3704
3705        // Span context from a non-empty source is the last pushed
3706        let current = SpanCtxt::current(&ctxt);
3707        assert_eq!(root, current);
3708        let root = current;
3709
3710        // A child span shares the same trace id, but has a new span id
3711        // The span id of the parent becomes the span parent
3712        let child = SpanCtxt::new_child(&root, &rng);
3713
3714        assert_eq!(root.trace_id, child.trace_id);
3715        assert_ne!(root.span_id, child.span_id);
3716        assert!(child.span_id.is_some());
3717        assert_eq!(root.span_id, child.span_parent);
3718
3719        ctxt.exit(&mut frame);
3720        ctxt.close(frame);
3721    }
3722
3723    #[test]
3724    fn span_new() {
3725        let span = Span::new(
3726            Path::new_raw("test"),
3727            Timestamp::from_unix(Duration::from_secs(1)),
3728            [
3729                ("span_prop", Value::from(true)),
3730                ("span_name", Value::from("my span")),
3731                ("span_kind", Value::from("internal")),
3732                ("trace_id", Value::from("00000000000000000000000000000001")),
3733                ("span_parent", Value::from("0000000000000002")),
3734                ("span_id", Value::from("0000000000000003")),
3735            ],
3736        );
3737
3738        let ctxt = SpanCtxt::new(
3739            TraceId::from_u128(1),
3740            SpanId::from_u64(2),
3741            SpanId::from_u64(3),
3742        );
3743
3744        assert_eq!("test", span.mdl());
3745        assert_eq!(
3746            Timestamp::from_unix(Duration::from_secs(1)).unwrap(),
3747            span.extent().unwrap().as_point()
3748        );
3749        assert_eq!("my span", span.name().unwrap());
3750        assert_eq!(SpanKind::Internal, span.kind().unwrap());
3751        assert_eq!(true, span.props().pull::<bool, _>("span_prop").unwrap());
3752        assert_eq!(ctxt, span.ctxt(Empty));
3753
3754        let span = span.with_name("my span 2").with_kind(SpanKind::Consumer);
3755
3756        assert_eq!("my span 2", span.name().unwrap());
3757        assert_eq!(SpanKind::Consumer, span.kind().unwrap());
3758
3759        #[cfg(feature = "alloc")]
3760        {
3761            let set = SpanLinkSet::from_iter([
3762                SpanLink::new(
3763                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3764                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
3765                ),
3766                SpanLink::new(
3767                    TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
3768                    SpanId::from_u64(0x0123456789abcdef).unwrap(),
3769                ),
3770            ]);
3771
3772            let span = span.with_links(set.clone());
3773
3774            assert_eq!(set, span.links().unwrap());
3775        }
3776    }
3777
3778    #[test]
3779    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3780    fn span_ctxt() {
3781        let rng = crate::platform::DefaultRng::new();
3782        let ctxt = crate::platform::DefaultCtxt::new();
3783
3784        let span = Span::new(
3785            Path::new_raw("test"),
3786            Timestamp::from_unix(Duration::from_secs(1)),
3787            Empty,
3788        );
3789
3790        let root = SpanCtxt::new_root(&rng);
3791
3792        let mut frame = ctxt.open_push(root);
3793
3794        ctxt.enter(&mut frame);
3795
3796        let current = SpanCtxt::current(&ctxt);
3797
3798        let span_current = span.ctxt(&ctxt);
3799
3800        assert_eq!(root, span_current);
3801        assert_eq!(current, span_current);
3802
3803        assert_eq!(SpanCtxt::empty(), span.ctxt(Empty));
3804
3805        let unrelated_ctxt = SpanCtxt::new_root(&rng);
3806        let span = Span::new(
3807            Path::new_raw("test"),
3808            Timestamp::from_unix(Duration::from_secs(1)),
3809            unrelated_ctxt,
3810        );
3811
3812        assert_eq!(unrelated_ctxt, span.ctxt(&ctxt));
3813        assert_eq!(unrelated_ctxt, span.ctxt(Empty));
3814
3815        ctxt.exit(&mut frame);
3816        ctxt.close(frame);
3817    }
3818
3819    #[test]
3820    fn span_to_event() {
3821        let span = Span::new(
3822            Path::new_raw("test"),
3823            Timestamp::from_unix(Duration::from_secs(1)),
3824            [
3825                ("span_prop", Value::from(true)),
3826                ("span_name", Value::from("my span")),
3827            ],
3828        );
3829
3830        let evt = span.to_event();
3831
3832        assert_eq!("test", evt.mdl());
3833        assert_eq!(
3834            Timestamp::from_unix(Duration::from_secs(1)).unwrap(),
3835            evt.extent().unwrap().as_point()
3836        );
3837        assert_eq!("my span completed", evt.msg().to_string());
3838        assert_eq!(
3839            "my span",
3840            evt.props().pull::<Str, _>(KEY_SPAN_NAME).unwrap()
3841        );
3842        assert_eq!(true, evt.props().pull::<bool, _>("span_prop").unwrap());
3843        assert_eq!(
3844            Kind::Span,
3845            evt.props().pull::<Kind, _>(KEY_EVT_KIND).unwrap()
3846        );
3847    }
3848
3849    #[test]
3850    fn span_to_event_uses_tpl() {
3851        assert_eq!(
3852            "test",
3853            Span::new(
3854                Path::new_raw("test"),
3855                Timestamp::from_unix(Duration::from_secs(1)),
3856                ("span_prop", true),
3857            )
3858            .with_tpl(Template::literal("test"))
3859            .to_event()
3860            .msg()
3861            .to_string(),
3862        );
3863    }
3864
3865    #[test]
3866    fn span_to_extent() {
3867        for (case, expected) in [
3868            (
3869                Some(Timestamp::from_unix(Duration::from_secs(1)).unwrap()),
3870                Some(Extent::point(
3871                    Timestamp::from_unix(Duration::from_secs(1)).unwrap(),
3872                )),
3873            ),
3874            (None, None),
3875        ] {
3876            let span = Span::new(Path::new_raw("test"), case, ("span_prop", true));
3877
3878            let extent = span.to_extent();
3879
3880            assert_eq!(
3881                expected.map(|extent| extent.as_range().cloned()),
3882                extent.map(|extent| extent.as_range().cloned())
3883            );
3884        }
3885    }
3886
3887    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3888    struct MyClock(Cell<u64>);
3889
3890    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3891    impl Clock for MyClock {
3892        fn now(&self) -> Option<crate::Timestamp> {
3893            let ts = crate::Timestamp::from_unix(Duration::from_secs(self.0.get()));
3894            self.0.set(self.0.get() + 1);
3895            ts
3896        }
3897    }
3898
3899    #[test]
3900    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3901    fn span_guard_new() {
3902        let clock = MyClock(Cell::new(0));
3903        let rng = crate::platform::DefaultRng::new();
3904        let ctxt = crate::platform::DefaultCtxt::new();
3905
3906        let complete_called = Cell::new(false);
3907
3908        let (mut guard, frame) = SpanGuard::new(
3909            filter::from_fn(|evt| {
3910                assert_eq!(2, evt.props().pull::<usize, _>("ctxt_prop").unwrap());
3911
3912                assert!(evt.props().get("trace_id").is_some());
3913                assert!(evt.props().get("span_id").is_some());
3914
3915                true
3916            }),
3917            &ctxt,
3918            &clock,
3919            &rng,
3920            completion::from_fn(|evt| {
3921                assert_eq!(
3922                    Timestamp::from_unix(Duration::from_secs(0)).unwrap(),
3923                    evt.extent().unwrap().as_range().unwrap().start
3924                );
3925                assert_eq!(
3926                    Timestamp::from_unix(Duration::from_secs(1)).unwrap(),
3927                    evt.extent().unwrap().as_range().unwrap().end
3928                );
3929
3930                assert_eq!("test", evt.mdl());
3931                assert_eq!("span", evt.name().unwrap());
3932
3933                assert_eq!(1, evt.props().pull::<usize, _>("event_prop").unwrap());
3934
3935                ctxt.with_current(|props| {
3936                    assert_eq!(2, props.pull::<usize, _>("ctxt_prop").unwrap());
3937                });
3938
3939                let current_ctxt = SpanCtxt::current(&ctxt);
3940
3941                assert_ne!(current_ctxt, SpanCtxt::empty());
3942
3943                complete_called.set(true);
3944            }),
3945            ("ctxt_prop", 2),
3946            Path::new_raw("test"),
3947            [
3948                ("event_prop", Value::from(1)),
3949                ("span_name", Value::from("span")),
3950            ],
3951        );
3952
3953        assert!(guard.is_enabled());
3954
3955        frame.call(move || {
3956            guard.start();
3957
3958            drop(guard);
3959        });
3960
3961        assert!(complete_called.get());
3962    }
3963
3964    #[test]
3965    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3966    fn span_guard_unstarted_complete() {
3967        let clock = MyClock(Cell::new(0));
3968        let rng = crate::platform::DefaultRng::new();
3969        let ctxt = crate::platform::DefaultCtxt::new();
3970
3971        let complete_called = Cell::new(false);
3972
3973        let (guard, frame) = SpanGuard::new(
3974            filter::from_fn(|_| true),
3975            &ctxt,
3976            &clock,
3977            &rng,
3978            completion::from_fn(|_| {}),
3979            Empty,
3980            Path::new_raw("test"),
3981            Empty,
3982        );
3983
3984        assert!(guard.is_enabled());
3985
3986        frame.call(move || {
3987            drop(guard);
3988        });
3989
3990        assert!(!complete_called.get());
3991    }
3992
3993    #[test]
3994    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
3995    fn span_guard_new_disabled() {
3996        let rng = crate::platform::DefaultRng::new();
3997        let clock = crate::platform::DefaultClock::new();
3998        let ctxt = crate::platform::DefaultCtxt::new();
3999
4000        let complete_called = Cell::new(false);
4001
4002        let (mut guard, frame) = SpanGuard::new(
4003            filter::from_fn(|_| false),
4004            &ctxt,
4005            &clock,
4006            &rng,
4007            completion::from_fn(|_| {
4008                complete_called.set(true);
4009            }),
4010            Empty,
4011            Path::new_raw("test"),
4012            Empty,
4013        );
4014
4015        assert!(!guard.is_enabled());
4016
4017        frame.call(move || {
4018            guard.start();
4019
4020            drop(guard);
4021        });
4022
4023        assert!(!complete_called.get());
4024    }
4025
4026    #[test]
4027    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
4028    fn span_guard_custom_complete() {
4029        let ctxt = crate::platform::DefaultCtxt::new();
4030        let clock = crate::platform::DefaultClock::new();
4031        let rng = crate::platform::DefaultRng::new();
4032
4033        let custom_complete_called = Cell::new(false);
4034        let default_complete_called = Cell::new(false);
4035
4036        let (mut guard, _) = SpanGuard::new(
4037            filter::from_fn(|_| true),
4038            &ctxt,
4039            &clock,
4040            &rng,
4041            completion::from_fn(|_| {
4042                default_complete_called.set(true);
4043            }),
4044            Empty,
4045            Path::new_raw("test"),
4046            Empty,
4047        );
4048
4049        assert!(guard.is_enabled());
4050
4051        guard.start();
4052
4053        guard.complete_with(completion::from_fn(|_| {
4054            custom_complete_called.set(true);
4055        }));
4056
4057        assert!(!default_complete_called.get());
4058        assert!(custom_complete_called.get());
4059    }
4060
4061    #[test]
4062    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
4063    fn span_guard_with_props() {
4064        let clock = MyClock(Cell::new(0));
4065        let rng = crate::platform::DefaultRng::new();
4066        let ctxt = crate::platform::DefaultCtxt::new();
4067
4068        let complete_called = Cell::new(false);
4069
4070        let (mut guard, frame) = SpanGuard::new(
4071            filter::from_fn(|_| true),
4072            &ctxt,
4073            &clock,
4074            &rng,
4075            completion::from_fn(|evt| {
4076                assert_eq!(2, evt.props().pull::<usize, _>("event_prop").unwrap());
4077                assert_eq!("test 2", evt.props().pull::<&str, _>("span_name").unwrap());
4078                assert_eq!(
4079                    SpanKind::Consumer,
4080                    evt.props().pull::<SpanKind, _>("span_kind").unwrap()
4081                );
4082
4083                #[cfg(feature = "alloc")]
4084                {
4085                    let set = SpanLinkSet::from_iter([
4086                        SpanLink::new(
4087                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
4088                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
4089                        ),
4090                        SpanLink::new(
4091                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
4092                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
4093                        ),
4094                    ]);
4095
4096                    assert_eq!(
4097                        set,
4098                        evt.props().pull::<SpanLinkSet, _>("span_links").unwrap()
4099                    );
4100                }
4101
4102                complete_called.set(true);
4103            }),
4104            Empty,
4105            Path::new_raw("test"),
4106            ("event_prop", 1),
4107        );
4108
4109        frame.call(move || {
4110            guard.start();
4111
4112            let guard = guard
4113                .with_props(("event_prop", 2))
4114                .with_name("test 2")
4115                .with_kind(SpanKind::Consumer);
4116
4117            let guard = {
4118                #[cfg(feature = "alloc")]
4119                {
4120                    let set = SpanLinkSet::from_iter([
4121                        SpanLink::new(
4122                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
4123                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
4124                        ),
4125                        SpanLink::new(
4126                            TraceId::from_u128(0x0123456789abcdef0123456789abcdef).unwrap(),
4127                            SpanId::from_u64(0x0123456789abcdef).unwrap(),
4128                        ),
4129                    ]);
4130
4131                    guard.with_links(set)
4132                }
4133                #[cfg(not(feature = "alloc"))]
4134                {
4135                    guard
4136                }
4137            };
4138
4139            drop(guard);
4140        });
4141
4142        assert!(complete_called.get());
4143    }
4144
4145    #[test]
4146    #[cfg(all(feature = "std", feature = "rand", not(miri)))]
4147    fn span_guard_from_runtime() {
4148        use emit_core::emitter;
4149
4150        let complete_called = Cell::new(false);
4151
4152        let rt = Runtime::default()
4153            .with_emitter(emitter::from_fn(|_| {
4154                complete_called.set(true);
4155            }))
4156            .with_ctxt(crate::platform::DefaultCtxt::new())
4157            .with_clock(MyClock(Cell::new(0)))
4158            .with_rng(crate::platform::DefaultRng::new());
4159
4160        let (mut guard, frame) =
4161            SpanGuard::from_runtime(&rt, Empty, Path::new_raw("test"), ("event_prop", 1));
4162
4163        assert!(guard.is_enabled());
4164
4165        frame.call(move || {
4166            guard.start();
4167
4168            drop(guard);
4169        });
4170
4171        assert!(complete_called.get());
4172    }
4173}