1use 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#[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 pub fn random<R: Rng>(rng: R) -> Option<Self> {
113 Some(TraceId::new(NonZeroU128::new(rng.gen_u128()?)?))
114 }
115
116 pub const fn new(v: NonZeroU128) -> Self {
120 TraceId(v)
121 }
122
123 pub fn from_u128(v: u128) -> Option<Self> {
129 Some(TraceId(NonZeroU128::new(v)?))
130 }
131
132 pub const fn to_u128(&self) -> u128 {
136 self.0.get()
137 }
138
139 pub fn from_bytes(v: [u8; 16]) -> Option<Self> {
143 Self::from_u128(u128::from_be_bytes(v))
144 }
145
146 pub fn to_bytes(&self) -> [u8; 16] {
150 self.0.get().to_be_bytes()
151 }
152
153 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 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 let h1 = HEX_DECODE_TABLE[hex[i * 2] as usize];
185 let h2 = HEX_DECODE_TABLE[hex[i * 2 + 1] as usize];
186
187 if h1 | h2 == 0xff {
190 return Err(ParseIdError {});
191 }
192
193 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 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#[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 pub fn random<R: Rng>(rng: R) -> Option<Self> {
279 Some(SpanId::new(NonZeroU64::new(rng.gen_u64()?)?))
280 }
281
282 pub const fn new(v: NonZeroU64) -> Self {
286 SpanId(v)
287 }
288
289 pub fn from_u64(v: u64) -> Option<Self> {
295 Some(SpanId(NonZeroU64::new(v)?))
296 }
297
298 pub const fn to_u64(&self) -> u64 {
302 self.0.get()
303 }
304
305 pub fn from_bytes(v: [u8; 8]) -> Option<Self> {
309 Self::from_u64(u64::from_be_bytes(v))
310 }
311
312 pub fn to_bytes(&self) -> [u8; 8] {
316 self.0.get().to_be_bytes()
317 }
318
319 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 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 let h1 = HEX_DECODE_TABLE[hex[i * 2] as usize];
351 let h2 = HEX_DECODE_TABLE[hex[i * 2 + 1] as usize];
352
353 if h1 | h2 == 0xff {
356 return Err(ParseIdError {});
357 }
358
359 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 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
382const 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#[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
442pub 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 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 pub fn mdl(&self) -> &Path<'a> {
479 &self.mdl
480 }
481
482 pub fn with_mdl(mut self, mdl: impl Into<Path<'a>>) -> Self {
486 self.mdl = mdl.into();
487 self
488 }
489
490 pub fn name(&self) -> Option<Str<'_>> {
494 self.props.pull(KEY_SPAN_NAME)
495 }
496
497 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 pub fn kind(&self) -> Option<SpanKind> {
508 self.props.pull(KEY_SPAN_KIND)
509 }
510
511 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 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 #[cfg(feature = "alloc")]
542 pub fn links(&self) -> Option<SpanLinkSet> {
543 self.props.pull(KEY_SPAN_LINKS)
544 }
545
546 #[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 pub fn extent(&self) -> Option<&Extent> {
561 self.extent.as_ref()
562 }
563
564 pub fn with_extent(mut self, extent: impl ToExtent) -> Self {
568 self.extent = extent.to_extent();
569 self
570 }
571
572 pub fn ts(&self) -> Option<&Timestamp> {
578 self.extent.as_ref().map(|extent| extent.as_point())
579 }
580
581 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 pub fn props(&self) -> &P {
597 &self.props
598 }
599
600 pub fn props_mut(&mut self) -> &mut P {
604 &mut self.props
605 }
606
607 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 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 pub fn tpl(&self) -> &Template<'a> {
635 self.tpl.as_ref().unwrap_or(&END_TEMPLATE)
636 }
637
638 pub fn with_tpl(mut self, tpl: impl Into<Template<'a>>) -> Self {
642 self.tpl = Some(tpl.into());
643 self
644 }
645
646 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
665const 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
673const 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#[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 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 pub const fn empty() -> Self {
754 Self {
755 trace_id: None,
756 span_parent: None,
757 span_id: None,
758 }
759 }
760
761 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 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 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 pub fn trace_id(&self) -> Option<&TraceId> {
806 self.trace_id.as_ref()
807 }
808
809 pub fn span_parent(&self) -> Option<&SpanId> {
813 self.span_parent.as_ref()
814 }
815
816 pub fn span_id(&self) -> Option<&SpanId> {
820 self.span_id.as_ref()
821 }
822
823 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#[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#[non_exhaustive]
873#[derive(Clone, Copy, PartialEq, Eq)]
874pub enum SpanKind {
875 Internal,
879 Server,
885 Client,
891 Producer,
897 Consumer,
903}
904
905impl SpanKind {
906 pub fn try_from_str(s: &str) -> Result<Self, ParseKindError> {
910 s.parse()
911 }
912
913 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#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
1009pub struct SpanLink {
1010 trace_id: TraceId,
1011 span_id: SpanId,
1012}
1013
1014impl SpanLink {
1015 pub const fn new(trace_id: TraceId, span_id: SpanId) -> Self {
1019 SpanLink { trace_id, span_id }
1020 }
1021
1022 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 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 pub fn trace_id(&self) -> &TraceId {
1057 &self.trace_id
1058 }
1059
1060 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#[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 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 #[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 #[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 pub fn new() -> Self {
1210 SpanLinkSet { links: Set::new() }
1211 }
1212
1213 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 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 if !first {
1244 if s.first() != Some(&b',') {
1245 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 if s.get(50) != Some(&b'"') {
1257 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 return Err(ParseSpanLinkSetError {});
1270 }
1271
1272 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 return Err(ParseSpanLinkSetError {});
1284 }
1285
1286 s = trim_start(s);
1287 }
1288
1289 if s.len() != 1 {
1290 return Err(ParseSpanLinkSetError {});
1292 }
1293
1294 Ok(set)
1295 }
1296
1297 pub fn insert(&mut self, link: SpanLink) -> bool {
1303 self.links.insert(link)
1304 }
1305
1306 pub fn len(&self) -> usize {
1310 self.links.len()
1311 }
1312
1313 pub fn is_empty(&self) -> bool {
1317 self.links.is_empty()
1318 }
1319
1320 pub fn clear(&mut self) {
1324 self.links.clear();
1325 }
1326
1327 pub fn contains(&self, link: SpanLink) -> bool {
1331 self.links.contains(&link)
1332 }
1333
1334 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 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
2375pub struct SpanGuard<'a, T: Clock, P: Props, F: Completion> {
2393 state: SpanGuardState<T>,
2394 data: Option<SpanGuardData<'a, P>>,
2396 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 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 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 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 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 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 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 pub fn is_enabled(&self) -> bool {
2555 self.completion.is_some()
2556 }
2557
2558 #[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 self.completion.take();
2569
2570 SpanGuard {
2571 state: self.state.take(),
2572 data: self.data.take(),
2573 completion: Some(completion),
2574 }
2575 }
2576
2577 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 pub fn props_mut(&mut self) -> Option<&mut P> {
2678 self.data.as_mut().map(|data| &mut data.props)
2679 }
2680
2681 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 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 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 pub trait Completion {
2747 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 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 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 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 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 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 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 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 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 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 pub const fn new(emitter: E) -> Self {
2997 FromEmitter(emitter)
2998 }
2999 }
3000
3001 pub const fn from_emitter<E: Emitter>(emitter: E) -> FromEmitter<E> {
3007 FromEmitter(emitter)
3008 }
3009
3010 pub struct FromFn<F = fn(Span<&dyn ErasedProps>)>(F);
3016
3017 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 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 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 let root = SpanCtxt::current(&ctxt);
3691 assert_eq!(SpanCtxt::empty(), root);
3692
3693 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 let mut frame = ctxt.open_push(root);
3702
3703 ctxt.enter(&mut frame);
3704
3705 let current = SpanCtxt::current(&ctxt);
3707 assert_eq!(root, current);
3708 let root = current;
3709
3710 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}