🛈 Note: This is pre-release documentation for the upcoming tracing 0.2.0 ecosystem.

For the release documentation, please see docs.rs, instead.

tracing_core/
field.rs

1//! Span and `Event` key-value data.
2//!
3//! Spans and events may be annotated with key-value data, known as _fields_.
4//! These fields consist of a mapping from a key (corresponding to a `&str` but
5//! represented internally as an array index) to a [`Value`].
6//!
7//! # `Value`s and `Collect`s
8//!
9//! Collectors consume `Value`s as fields attached to [span]s or [`Event`]s.
10//! The set of field keys on a given span or event is defined on its [`Metadata`].
11//! When a span is created, it provides [`Attributes`] to the collector's
12//! [`new_span`] method, containing any fields whose values were provided when
13//! the span was created; and may call the collector's [`record`] method
14//! with additional [`Record`]s if values are added for more of its fields.
15//! Similarly, the [`Event`] type passed to the collector's [`event`] method
16//! will contain any fields attached to each event.
17//!
18//! `tracing` represents values as either one of a set of Rust primitives
19//! (`i64`, `u64`, `f64`, `i128`, `u128`, `bool`, and `&str`) or using a
20//! `fmt::Display` or `fmt::Debug` implementation. Collectors are provided
21//! these primitive value types as `dyn Value` trait objects.
22//!
23//! These trait objects can be formatted using `fmt::Debug`, but may also be
24//! recorded as typed data by calling the [`Value::record`] method on these
25//! trait objects with a _visitor_ implementing the [`Visit`] trait. This trait
26//! represents the behavior used to record values of various types. For example,
27//! we might record integers by incrementing counters for their field names,
28//! rather than printing them.
29//!
30//! [span]: super::span
31//! [`Event`]: super::event::Event
32//! [`Metadata`]: super::metadata::Metadata
33//! [`Attributes`]:  super::span::Attributes
34//! [`Record`]: super::span::Record
35//! [`new_span`]: super::collect::Collect::new_span
36//! [`record`]: super::collect::Collect::record
37//! [`event`]:  super::collect::Collect::event
38use crate::callsite;
39use core::{
40    borrow::Borrow,
41    fmt::{self, Write},
42    hash::{Hash, Hasher},
43    num,
44    ops::Range,
45};
46
47use self::private::ValidLen;
48
49/// An opaque key allowing _O_(1) access to a field in a `Span`'s key-value
50/// data.
51///
52/// As keys are defined by the _metadata_ of a span, rather than by an
53/// individual instance of a span, a key may be used to access the same field
54/// across all instances of a given span with the same metadata. Thus, when a
55/// collector observes a new span, it need only access a field by name _once_,
56/// and use the key for that name for all other accesses.
57#[derive(Debug)]
58pub struct Field {
59    i: usize,
60    fields: FieldSet,
61}
62
63/// An empty field.
64///
65/// This can be used to indicate that the value of a field is not currently
66/// present but will be recorded later.
67///
68/// When a field's value is `Empty`. it will not be recorded.
69#[derive(Debug, Eq, PartialEq)]
70pub struct Empty;
71
72/// Describes the fields present on a span.
73///
74/// ## Equality
75///
76/// In well-behaved applications, two `FieldSet`s [initialized] with equal
77/// [callsite identifiers] will have identical fields. Consequently, in release
78/// builds, [`FieldSet::eq`] *only* checks that its arguments have equal
79/// callsites. However, the equality of field names is checked in debug builds.
80///
81/// [initialized]: Self::new
82/// [callsite identifiers]: callsite::Identifier
83pub struct FieldSet {
84    /// The names of each field on the described span.
85    names: &'static [&'static str],
86    /// The callsite where the described span originates.
87    callsite: callsite::Identifier,
88}
89
90/// A set of fields and values for a span.
91pub struct ValueSet<'a> {
92    values: &'a [(&'a Field, Option<&'a (dyn Value + 'a)>)],
93    fields: &'a FieldSet,
94}
95
96/// An iterator over a set of fields.
97#[derive(Debug)]
98pub struct Iter {
99    idxs: Range<usize>,
100    fields: FieldSet,
101}
102
103/// Visits typed values.
104///
105/// An instance of `Visit` ("a visitor") represents the logic necessary to
106/// record field values of various types. When an implementor of [`Value`] is
107/// [recorded], it calls the appropriate method on the provided visitor to
108/// indicate the type that value should be recorded as.
109///
110/// When a [`Collect`] implementation [records an `Event`] or a
111/// [set of `Value`s added to a `Span`], it can pass an `&mut Visit` to the
112/// `record` method on the provided [`ValueSet`] or [`Event`]. This visitor
113/// will then be used to record all the field-value pairs present on that
114/// `Event` or `ValueSet`.
115///
116/// # Examples
117///
118/// A simple visitor that writes to a string might be implemented like so:
119/// ```
120/// # extern crate tracing_core as tracing;
121/// use std::fmt::{self, Write};
122/// use tracing::field::{Value, Visit, Field};
123/// pub struct StringVisitor<'a> {
124///     string: &'a mut String,
125/// }
126///
127/// impl<'a> Visit for StringVisitor<'a> {
128///     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
129///         write!(self.string, "{} = {:?}; ", field.name(), value).unwrap();
130///     }
131/// }
132/// ```
133/// This visitor will format each recorded value using `fmt::Debug`, and
134/// append the field name and formatted value to the provided string,
135/// regardless of the type of the recorded value. When all the values have
136/// been recorded, the `StringVisitor` may be dropped, allowing the string
137/// to be printed or stored in some other data structure.
138///
139/// The `Visit` trait provides default implementations for `record_i64`,
140/// `record_u64`, `record_bool`, `record_str`, and `record_error`, which simply
141/// forward the recorded value to `record_debug`. Thus, `record_debug` is the
142/// only method which a `Visit` implementation *must* implement. However,
143/// visitors may override the default implementations of these functions in
144/// order to implement type-specific behavior.
145///
146/// Additionally, when a visitor receives a value of a type it does not care
147/// about, it is free to ignore those values completely. For example, a
148/// visitor which only records numeric data might look like this:
149///
150/// ```
151/// # extern crate tracing_core as tracing;
152/// # use std::fmt::{self, Write};
153/// # use tracing::field::{Value, Visit, Field};
154/// pub struct SumVisitor {
155///     sum: i64,
156/// }
157///
158/// impl Visit for SumVisitor {
159///     fn record_i64(&mut self, _field: &Field, value: i64) {
160///        self.sum += value;
161///     }
162///
163///     fn record_u64(&mut self, _field: &Field, value: u64) {
164///         self.sum += value as i64;
165///     }
166///
167///     fn record_debug(&mut self, _field: &Field, _value: &dyn fmt::Debug) {
168///         // Do nothing
169///     }
170/// }
171/// ```
172///
173/// This visitor (which is probably not particularly useful) keeps a running
174/// sum of all the numeric values it records, and ignores all other values. A
175/// more practical example of recording typed values is presented in
176/// `examples/counters.rs`, which demonstrates a very simple metrics system
177/// implemented using `tracing`.
178///
179/// <div class="example-wrap" style="display:inline-block">
180/// <pre class="ignore" style="white-space:normal;font:inherit;">
181/// <strong>Note</strong>: The <code>record_error</code> trait method is only
182/// available when the Rust standard library is present, as it requires the
183/// <code>std::error::Error</code> trait.
184/// </pre></div>
185///
186/// [recorded]: Value::record
187/// [`Collect`]: super::collect::Collect
188/// [records an `Event`]: super::collect::Collect::event
189/// [set of `Value`s added to a `Span`]: super::collect::Collect::record
190/// [`Event`]: super::event::Event
191pub trait Visit {
192    /// Visit a double-precision floating point value.
193    fn record_f64(&mut self, field: &Field, value: f64) {
194        self.record_debug(field, &value)
195    }
196
197    /// Visit a signed 64-bit integer value.
198    fn record_i64(&mut self, field: &Field, value: i64) {
199        self.record_debug(field, &value)
200    }
201
202    /// Visit an unsigned 64-bit integer value.
203    fn record_u64(&mut self, field: &Field, value: u64) {
204        self.record_debug(field, &value)
205    }
206
207    /// Visit a signed 128-bit integer value.
208    fn record_i128(&mut self, field: &Field, value: i128) {
209        self.record_debug(field, &value)
210    }
211
212    /// Visit an unsigned 128-bit integer value.
213    fn record_u128(&mut self, field: &Field, value: u128) {
214        self.record_debug(field, &value)
215    }
216
217    /// Visit a boolean value.
218    fn record_bool(&mut self, field: &Field, value: bool) {
219        self.record_debug(field, &value)
220    }
221
222    /// Visit a string value.
223    fn record_str(&mut self, field: &Field, value: &str) {
224        self.record_debug(field, &value)
225    }
226
227    /// Visit a byte slice.
228    fn record_bytes(&mut self, field: &Field, value: &[u8]) {
229        self.record_debug(field, &HexBytes(value))
230    }
231
232    /// Records a type implementing `Error`.
233    ///
234    /// <div class="example-wrap" style="display:inline-block">
235    /// <pre class="ignore" style="white-space:normal;font:inherit;">
236    /// <strong>Note</strong>: This is only enabled when the Rust standard library is
237    /// present.
238    /// </pre>
239    /// </div>
240    #[cfg(feature = "std")]
241    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
242    fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
243        self.record_debug(field, &DisplayValue(value))
244    }
245
246    /// Visit a value implementing `fmt::Debug`.
247    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug);
248}
249
250/// A field value of an erased type.
251///
252/// Implementors of `Value` may call the appropriate typed recording methods on
253/// the [visitor] passed to their `record` method in order to indicate how
254/// their data should be recorded.
255///
256/// [visitor]: Visit
257pub trait Value: crate::sealed::Sealed {
258    /// Visits this value with the given `Visitor`.
259    fn record(&self, key: &Field, visitor: &mut dyn Visit);
260}
261
262/// A `Value` which serializes using `fmt::Display`.
263///
264/// Uses `record_debug` in the `Value` implementation to
265/// avoid an unnecessary evaluation.
266#[derive(Clone)]
267pub struct DisplayValue<T: fmt::Display>(T);
268
269/// A `Value` which serializes as a string using `fmt::Debug`.
270#[derive(Clone)]
271pub struct DebugValue<T: fmt::Debug>(T);
272
273/// Wraps a type implementing `fmt::Display` as a `Value` that can be
274/// recorded using its `Display` implementation.
275pub fn display<T>(t: T) -> DisplayValue<T>
276where
277    T: fmt::Display,
278{
279    DisplayValue(t)
280}
281
282/// Wraps a type implementing `fmt::Debug` as a `Value` that can be
283/// recorded using its `Debug` implementation.
284pub fn debug<T>(t: T) -> DebugValue<T>
285where
286    T: fmt::Debug,
287{
288    DebugValue(t)
289}
290
291struct HexBytes<'a>(&'a [u8]);
292
293impl fmt::Debug for HexBytes<'_> {
294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295        f.write_char('[')?;
296
297        let mut bytes = self.0.iter();
298
299        if let Some(byte) = bytes.next() {
300            f.write_fmt(format_args!("{byte:02x}"))?;
301        }
302
303        for byte in bytes {
304            f.write_fmt(format_args!(" {byte:02x}"))?;
305        }
306
307        f.write_char(']')
308    }
309}
310
311// ===== impl Visit =====
312
313impl Visit for fmt::DebugStruct<'_, '_> {
314    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
315        self.field(field.name(), value);
316    }
317}
318
319impl Visit for fmt::DebugMap<'_, '_> {
320    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
321        self.entry(&format_args!("{}", field), value);
322    }
323}
324
325impl<F> Visit for F
326where
327    F: FnMut(&Field, &dyn fmt::Debug),
328{
329    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
330        (self)(field, value)
331    }
332}
333
334// ===== impl Value =====
335
336macro_rules! impl_values {
337    ( $( $record:ident( $( $whatever:tt)+ ) ),+ ) => {
338        $(
339            impl_value!{ $record( $( $whatever )+ ) }
340        )+
341    }
342}
343
344macro_rules! ty_to_nonzero {
345    (u8) => {
346        NonZeroU8
347    };
348    (u16) => {
349        NonZeroU16
350    };
351    (u32) => {
352        NonZeroU32
353    };
354    (u64) => {
355        NonZeroU64
356    };
357    (u128) => {
358        NonZeroU128
359    };
360    (usize) => {
361        NonZeroUsize
362    };
363    (i8) => {
364        NonZeroI8
365    };
366    (i16) => {
367        NonZeroI16
368    };
369    (i32) => {
370        NonZeroI32
371    };
372    (i64) => {
373        NonZeroI64
374    };
375    (i128) => {
376        NonZeroI128
377    };
378    (isize) => {
379        NonZeroIsize
380    };
381}
382
383macro_rules! impl_one_value {
384    (f32, $op:expr, $record:ident) => {
385        impl_one_value!(normal, f32, $op, $record);
386    };
387    (f64, $op:expr, $record:ident) => {
388        impl_one_value!(normal, f64, $op, $record);
389    };
390    (bool, $op:expr, $record:ident) => {
391        impl_one_value!(normal, bool, $op, $record);
392    };
393    ($value_ty:tt, $op:expr, $record:ident) => {
394        impl_one_value!(normal, $value_ty, $op, $record);
395        impl_one_value!(nonzero, $value_ty, $op, $record);
396    };
397    (normal, $value_ty:tt, $op:expr, $record:ident) => {
398        impl $crate::sealed::Sealed for $value_ty {}
399        impl $crate::field::Value for $value_ty {
400            fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
401                // `op` is always a function; the closure is used because
402                // sometimes there isn't a real function corresponding to that
403                // operation. the clippy warning is not that useful here.
404                #[allow(clippy::redundant_closure_call)]
405                visitor.$record(key, $op(*self))
406            }
407        }
408    };
409    (nonzero, $value_ty:tt, $op:expr, $record:ident) => {
410        // This `use num::*;` is reported as unused because it gets emitted
411        // for every single invocation of this macro, so there are multiple `use`s.
412        // All but the first are useless indeed.
413        // We need this import because we can't write a path where one part is
414        // the `ty_to_nonzero!($value_ty)` invocation.
415        #[allow(clippy::useless_attribute, unused)]
416        use num::*;
417        impl $crate::sealed::Sealed for ty_to_nonzero!($value_ty) {}
418        impl $crate::field::Value for ty_to_nonzero!($value_ty) {
419            fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
420                // `op` is always a function; the closure is used because
421                // sometimes there isn't a real function corresponding to that
422                // operation. the clippy warning is not that useful here.
423                #[allow(clippy::redundant_closure_call)]
424                visitor.$record(key, $op(self.get()))
425            }
426        }
427    };
428}
429
430macro_rules! impl_value {
431    ( $record:ident( $( $value_ty:tt ),+ ) ) => {
432        $(
433            impl_one_value!($value_ty, |this: $value_ty| this, $record);
434        )+
435    };
436    ( $record:ident( $( $value_ty:tt ),+ as $as_ty:ty) ) => {
437        $(
438            impl_one_value!($value_ty, |this: $value_ty| this as $as_ty, $record);
439        )+
440    };
441}
442
443// ===== impl Value =====
444
445impl_values! {
446    record_u64(u64),
447    record_u64(usize, u32, u16, u8 as u64),
448    record_i64(i64),
449    record_i64(isize, i32, i16, i8 as i64),
450    record_u128(u128),
451    record_i128(i128),
452    record_bool(bool),
453    record_f64(f64, f32 as f64)
454}
455
456impl<T: crate::sealed::Sealed> crate::sealed::Sealed for Wrapping<T> {}
457impl<T: crate::field::Value> crate::field::Value for Wrapping<T> {
458    fn record(&self, key: &crate::field::Field, visitor: &mut dyn crate::field::Visit) {
459        self.0.record(key, visitor)
460    }
461}
462
463impl crate::sealed::Sealed for str {}
464
465impl Value for str {
466    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
467        visitor.record_str(key, self)
468    }
469}
470
471impl crate::sealed::Sealed for [u8] {}
472
473impl Value for [u8] {
474    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
475        visitor.record_bytes(key, self)
476    }
477}
478
479#[cfg(feature = "std")]
480impl crate::sealed::Sealed for dyn std::error::Error + 'static {}
481
482#[cfg(feature = "std")]
483#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
484impl Value for dyn std::error::Error + 'static {
485    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
486        visitor.record_error(key, self)
487    }
488}
489
490#[cfg(feature = "std")]
491impl crate::sealed::Sealed for dyn std::error::Error + Send + 'static {}
492
493#[cfg(feature = "std")]
494#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
495impl Value for dyn std::error::Error + Send + 'static {
496    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
497        (self as &dyn std::error::Error).record(key, visitor)
498    }
499}
500
501#[cfg(feature = "std")]
502impl crate::sealed::Sealed for dyn std::error::Error + Sync + 'static {}
503
504#[cfg(feature = "std")]
505#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
506impl Value for dyn std::error::Error + Sync + 'static {
507    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
508        (self as &dyn std::error::Error).record(key, visitor)
509    }
510}
511
512#[cfg(feature = "std")]
513impl crate::sealed::Sealed for dyn std::error::Error + Send + Sync + 'static {}
514
515#[cfg(feature = "std")]
516#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
517impl Value for dyn std::error::Error + Send + Sync + 'static {
518    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
519        (self as &dyn std::error::Error).record(key, visitor)
520    }
521}
522
523impl<'a, T: ?Sized> crate::sealed::Sealed for &'a T where T: Value + crate::sealed::Sealed + 'a {}
524
525impl<'a, T: ?Sized> Value for &'a T
526where
527    T: Value + 'a,
528{
529    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
530        (*self).record(key, visitor)
531    }
532}
533
534impl<'a, T: ?Sized> crate::sealed::Sealed for &'a mut T where T: Value + crate::sealed::Sealed + 'a {}
535
536impl<'a, T: ?Sized> Value for &'a mut T
537where
538    T: Value + 'a,
539{
540    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
541        // Don't use `(*self).record(key, visitor)`, otherwise would
542        // cause stack overflow due to `unconditional_recursion`.
543        T::record(self, key, visitor)
544    }
545}
546
547impl crate::sealed::Sealed for fmt::Arguments<'_> {}
548
549impl Value for fmt::Arguments<'_> {
550    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
551        visitor.record_debug(key, self)
552    }
553}
554
555#[cfg(feature = "alloc")]
556impl<T: ?Sized> crate::sealed::Sealed for alloc::boxed::Box<T> where T: Value {}
557
558#[cfg(feature = "alloc")]
559#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
560impl<T: ?Sized> Value for alloc::boxed::Box<T>
561where
562    T: Value,
563{
564    #[inline]
565    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
566        self.as_ref().record(key, visitor)
567    }
568}
569
570#[cfg(feature = "alloc")]
571#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
572impl crate::sealed::Sealed for alloc::string::String {}
573
574#[cfg(feature = "alloc")]
575#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
576impl Value for alloc::string::String {
577    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
578        visitor.record_str(key, self.as_str())
579    }
580}
581
582impl fmt::Debug for dyn Value {
583    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584        // We are only going to be recording the field value, so we don't
585        // actually care about the field name here.
586        struct NullCallsite;
587        static NULL_CALLSITE: NullCallsite = NullCallsite;
588        impl crate::callsite::Callsite for NullCallsite {
589            fn set_interest(&self, _: crate::collect::Interest) {
590                unreachable!("you somehow managed to register the null callsite?")
591            }
592
593            fn metadata(&self) -> &crate::Metadata<'_> {
594                unreachable!("you somehow managed to access the null callsite?")
595            }
596        }
597
598        static FIELD: Field = Field {
599            i: 0,
600            fields: FieldSet::new(&[], crate::identify_callsite!(&NULL_CALLSITE)),
601        };
602
603        let mut res = Ok(());
604        self.record(&FIELD, &mut |_: &Field, val: &dyn fmt::Debug| {
605            res = write!(f, "{:?}", val);
606        });
607        res
608    }
609}
610
611impl fmt::Display for dyn Value {
612    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613        fmt::Debug::fmt(self, f)
614    }
615}
616
617// ===== impl DisplayValue =====
618
619impl<T: fmt::Display> crate::sealed::Sealed for DisplayValue<T> {}
620
621impl<T> Value for DisplayValue<T>
622where
623    T: fmt::Display,
624{
625    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
626        visitor.record_debug(key, self)
627    }
628}
629
630impl<T: fmt::Display> fmt::Debug for DisplayValue<T> {
631    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632        fmt::Display::fmt(self, f)
633    }
634}
635
636impl<T: fmt::Display> fmt::Display for DisplayValue<T> {
637    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
638        self.0.fmt(f)
639    }
640}
641
642// ===== impl DebugValue =====
643
644impl<T: fmt::Debug> crate::sealed::Sealed for DebugValue<T> {}
645
646impl<T: fmt::Debug> Value for DebugValue<T>
647where
648    T: fmt::Debug,
649{
650    fn record(&self, key: &Field, visitor: &mut dyn Visit) {
651        visitor.record_debug(key, &self.0)
652    }
653}
654
655impl<T: fmt::Debug> fmt::Debug for DebugValue<T> {
656    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657        self.0.fmt(f)
658    }
659}
660
661impl crate::sealed::Sealed for Empty {}
662impl Value for Empty {
663    #[inline]
664    fn record(&self, _: &Field, _: &mut dyn Visit) {}
665}
666
667// ===== impl Field =====
668
669impl Field {
670    /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`]
671    /// which defines this field.
672    ///
673    /// [`Identifier`]: super::callsite::Identifier
674    /// [`Callsite`]: super::callsite::Callsite
675    #[inline]
676    pub fn callsite(&self) -> callsite::Identifier {
677        self.fields.callsite()
678    }
679
680    /// Returns a string representing the name of the field.
681    pub fn name(&self) -> &'static str {
682        self.fields.names[self.i]
683    }
684
685    /// Returns the index of this field in its [`FieldSet`].
686    pub fn index(&self) -> usize {
687        self.i
688    }
689}
690
691impl fmt::Display for Field {
692    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
693        f.pad(self.name())
694    }
695}
696
697impl AsRef<str> for Field {
698    fn as_ref(&self) -> &str {
699        self.name()
700    }
701}
702
703impl PartialEq for Field {
704    fn eq(&self, other: &Self) -> bool {
705        self.callsite() == other.callsite() && self.i == other.i
706    }
707}
708
709impl Eq for Field {}
710
711impl Hash for Field {
712    fn hash<H>(&self, state: &mut H)
713    where
714        H: Hasher,
715    {
716        self.callsite().hash(state);
717        self.i.hash(state);
718    }
719}
720
721impl Clone for Field {
722    fn clone(&self) -> Self {
723        Field {
724            i: self.i,
725            fields: FieldSet {
726                names: self.fields.names,
727                callsite: self.fields.callsite(),
728            },
729        }
730    }
731}
732
733// ===== impl FieldSet =====
734
735impl FieldSet {
736    /// Constructs a new `FieldSet` with the given array of field names and callsite.
737    pub const fn new(names: &'static [&'static str], callsite: callsite::Identifier) -> Self {
738        Self { names, callsite }
739    }
740
741    /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`]
742    /// which defines this set of fields..
743    ///
744    /// [`Identifier`]: super::callsite::Identifier
745    /// [`Callsite`]: super::callsite::Callsite
746    #[inline]
747    pub(crate) fn callsite(&self) -> callsite::Identifier {
748        callsite::Identifier(self.callsite.0)
749    }
750
751    /// Returns the [`Field`] named `name`, or `None` if no such field exists.
752    ///
753    /// [`Field`]: super::Field
754    pub fn field<Q>(&self, name: &Q) -> Option<Field>
755    where
756        Q: Borrow<str> + ?Sized,
757    {
758        let name = &name.borrow();
759        self.names.iter().position(|f| f == name).map(|i| Field {
760            i,
761            fields: FieldSet {
762                names: self.names,
763                callsite: self.callsite(),
764            },
765        })
766    }
767
768    /// Returns `true` if `self` contains the given `field`.
769    ///
770    /// <div class="example-wrap" style="display:inline-block">
771    /// <pre class="ignore" style="white-space:normal;font:inherit;">
772    /// <strong>Note</strong>: If <code>field</code> shares a name with a field
773    /// in this <code>FieldSet</code>, but was created by a <code>FieldSet</code>
774    /// with a different callsite, this <code>FieldSet</code> does <em>not</em>
775    /// contain it. This is so that if two separate span callsites define a field
776    /// named "foo", the <code>Field</code> corresponding to "foo" for each
777    /// of those callsites are not equivalent.
778    /// </pre></div>
779    pub fn contains(&self, field: &Field) -> bool {
780        field.callsite() == self.callsite() && field.i <= self.len()
781    }
782
783    /// Returns an iterator over the `Field`s in this `FieldSet`.
784    #[inline]
785    pub fn iter(&self) -> Iter {
786        let idxs = 0..self.len();
787        Iter {
788            idxs,
789            fields: FieldSet {
790                names: self.names,
791                callsite: self.callsite(),
792            },
793        }
794    }
795
796    /// Returns a new `ValueSet` with entries for this `FieldSet`'s values.
797    #[doc(hidden)]
798    pub fn value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v>
799    where
800        V: ValidLen<'v>,
801    {
802        ValueSet {
803            fields: self,
804            values: values.borrow(),
805        }
806    }
807
808    /// Returns the number of fields in this `FieldSet`.
809    #[inline]
810    pub fn len(&self) -> usize {
811        self.names.len()
812    }
813
814    /// Returns whether or not this `FieldSet` has fields.
815    #[inline]
816    pub fn is_empty(&self) -> bool {
817        self.names.is_empty()
818    }
819}
820
821impl IntoIterator for &FieldSet {
822    type IntoIter = Iter;
823    type Item = Field;
824    #[inline]
825    fn into_iter(self) -> Self::IntoIter {
826        self.iter()
827    }
828}
829
830impl fmt::Debug for FieldSet {
831    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832        f.debug_struct("FieldSet")
833            .field("names", &self.names)
834            .field("callsite", &self.callsite)
835            .finish()
836    }
837}
838
839impl fmt::Display for FieldSet {
840    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
841        f.debug_set()
842            .entries(self.names.iter().map(display))
843            .finish()
844    }
845}
846
847impl Eq for FieldSet {}
848
849impl PartialEq for FieldSet {
850    fn eq(&self, other: &Self) -> bool {
851        if core::ptr::eq(&self, &other) {
852            true
853        } else if cfg!(not(debug_assertions)) {
854            // In a well-behaving application, two `FieldSet`s can be assumed to
855            // be totally equal so long as they share the same callsite.
856            self.callsite == other.callsite
857        } else {
858            // However, when debug-assertions are enabled, do NOT assume that
859            // the application is well-behaving; check every the field names of
860            // each `FieldSet` for equality.
861
862            // `FieldSet` is destructured here to ensure a compile-error if the
863            // fields of `FieldSet` change.
864            let Self {
865                names: lhs_names,
866                callsite: lhs_callsite,
867            } = self;
868
869            let Self {
870                names: rhs_names,
871                callsite: rhs_callsite,
872            } = &other;
873
874            // Check callsite equality first, as it is probably cheaper to do
875            // than str equality.
876            lhs_callsite == rhs_callsite && lhs_names == rhs_names
877        }
878    }
879}
880
881// ===== impl Iter =====
882
883impl Iterator for Iter {
884    type Item = Field;
885    #[inline]
886    fn next(&mut self) -> Option<Field> {
887        let i = self.idxs.next()?;
888        Some(Field {
889            i,
890            fields: FieldSet {
891                names: self.fields.names,
892                callsite: self.fields.callsite(),
893            },
894        })
895    }
896}
897
898// ===== impl ValueSet =====
899
900impl ValueSet<'_> {
901    /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`]
902    /// defining the fields this `ValueSet` refers to.
903    ///
904    /// [`Identifier`]: super::callsite::Identifier
905    /// [`Callsite`]: super::callsite::Callsite
906    #[inline]
907    pub fn callsite(&self) -> callsite::Identifier {
908        self.fields.callsite()
909    }
910
911    /// Visits all the fields in this `ValueSet` with the provided [visitor].
912    ///
913    /// [visitor]: Visit
914    pub fn record(&self, visitor: &mut dyn Visit) {
915        let my_callsite = self.callsite();
916        for (field, value) in self.values {
917            if field.callsite() != my_callsite {
918                continue;
919            }
920            if let Some(value) = value {
921                value.record(field, visitor);
922            }
923        }
924    }
925
926    /// Returns the number of fields in this `ValueSet` that would be visited
927    /// by a given [visitor] to the [`ValueSet::record()`] method.
928    ///
929    /// [visitor]: Visit
930    /// [`ValueSet::record()`]: ValueSet::record()
931    pub fn len(&self) -> usize {
932        let my_callsite = self.callsite();
933        self.values
934            .iter()
935            .filter(|(field, _)| field.callsite() == my_callsite)
936            .count()
937    }
938
939    /// Returns `true` if this `ValueSet` contains a value for the given `Field`.
940    pub(crate) fn contains(&self, field: &Field) -> bool {
941        field.callsite() == self.callsite()
942            && self
943                .values
944                .iter()
945                .any(|(key, val)| *key == field && val.is_some())
946    }
947
948    /// Returns true if this `ValueSet` contains _no_ values.
949    pub fn is_empty(&self) -> bool {
950        let my_callsite = self.callsite();
951        self.values
952            .iter()
953            .all(|(key, val)| val.is_none() || key.callsite() != my_callsite)
954    }
955
956    pub(crate) fn field_set(&self) -> &FieldSet {
957        self.fields
958    }
959}
960
961impl fmt::Debug for ValueSet<'_> {
962    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
963        self.values
964            .iter()
965            .fold(&mut f.debug_struct("ValueSet"), |dbg, (key, v)| {
966                if let Some(val) = v {
967                    val.record(key, dbg);
968                }
969                dbg
970            })
971            .field("callsite", &self.callsite())
972            .finish()
973    }
974}
975
976impl fmt::Display for ValueSet<'_> {
977    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978        self.values
979            .iter()
980            .fold(&mut f.debug_map(), |dbg, (key, v)| {
981                if let Some(val) = v {
982                    val.record(key, dbg);
983                }
984                dbg
985            })
986            .finish()
987    }
988}
989
990// ===== impl ValidLen =====
991
992mod private {
993    use super::*;
994
995    /// Restrictions on `ValueSet` lengths were removed in #2508 but this type remains for backwards compatibility.
996    pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (dyn Value + 'a)>)]> {}
997
998    impl<'a, const N: usize> ValidLen<'a> for [(&'a Field, Option<&'a (dyn Value + 'a)>); N] {}
999}
1000
1001#[cfg(test)]
1002mod test {
1003    use super::*;
1004    use crate::metadata::{Kind, Level, Metadata};
1005
1006    // Make sure TEST_CALLSITE_* have non-zero size, so they can't be located at the same address.
1007    struct TestCallsite1();
1008    static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1();
1009    static TEST_META_1: Metadata<'static> = metadata! {
1010        name: "field_test1",
1011        target: module_path!(),
1012        level: Level::INFO,
1013        fields: &["foo", "bar", "baz"],
1014        callsite: &TEST_CALLSITE_1,
1015        kind: Kind::SPAN,
1016    };
1017
1018    impl crate::callsite::Callsite for TestCallsite1 {
1019        fn set_interest(&self, _: crate::collect::Interest) {
1020            unimplemented!()
1021        }
1022
1023        fn metadata(&self) -> &Metadata<'_> {
1024            &TEST_META_1
1025        }
1026    }
1027
1028    struct TestCallsite2();
1029    static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2();
1030    static TEST_META_2: Metadata<'static> = metadata! {
1031        name: "field_test2",
1032        target: module_path!(),
1033        level: Level::INFO,
1034        fields: &["foo", "bar", "baz"],
1035        callsite: &TEST_CALLSITE_2,
1036        kind: Kind::SPAN,
1037    };
1038
1039    impl crate::callsite::Callsite for TestCallsite2 {
1040        fn set_interest(&self, _: crate::collect::Interest) {
1041            unimplemented!()
1042        }
1043
1044        fn metadata(&self) -> &Metadata<'_> {
1045            &TEST_META_2
1046        }
1047    }
1048
1049    #[test]
1050    fn value_set_with_no_values_is_empty() {
1051        let fields = TEST_META_1.fields();
1052        let values = &[
1053            (&fields.field("foo").unwrap(), None),
1054            (&fields.field("bar").unwrap(), None),
1055            (&fields.field("baz").unwrap(), None),
1056        ];
1057        let valueset = fields.value_set(values);
1058        assert!(valueset.is_empty());
1059    }
1060
1061    #[test]
1062    fn index_of_field_in_fieldset_is_correct() {
1063        let fields = TEST_META_1.fields();
1064        let foo = fields.field("foo").unwrap();
1065        assert_eq!(foo.index(), 0);
1066        let bar = fields.field("bar").unwrap();
1067        assert_eq!(bar.index(), 1);
1068        let baz = fields.field("baz").unwrap();
1069        assert_eq!(baz.index(), 2);
1070    }
1071
1072    #[test]
1073    fn empty_value_set_is_empty() {
1074        let fields = TEST_META_1.fields();
1075        let valueset = fields.value_set(&[]);
1076        assert!(valueset.is_empty());
1077    }
1078
1079    #[test]
1080    fn value_sets_with_fields_from_other_callsites_are_empty() {
1081        let fields = TEST_META_1.fields();
1082        let values = &[
1083            (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1084            (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1085            (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1086        ];
1087        let valueset = TEST_META_2.fields().value_set(values);
1088        assert!(valueset.is_empty())
1089    }
1090
1091    #[test]
1092    fn sparse_value_sets_are_not_empty() {
1093        let fields = TEST_META_1.fields();
1094        let values = &[
1095            (&fields.field("foo").unwrap(), None),
1096            (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1097            (&fields.field("baz").unwrap(), None),
1098        ];
1099        let valueset = fields.value_set(values);
1100        assert!(!valueset.is_empty());
1101    }
1102
1103    #[test]
1104    fn fields_from_other_callsets_are_skipped() {
1105        let fields = TEST_META_1.fields();
1106        let values = &[
1107            (&fields.field("foo").unwrap(), None),
1108            (
1109                &TEST_META_2.fields().field("bar").unwrap(),
1110                Some(&57 as &dyn Value),
1111            ),
1112            (&fields.field("baz").unwrap(), None),
1113        ];
1114
1115        struct MyVisitor;
1116        impl Visit for MyVisitor {
1117            fn record_debug(&mut self, field: &Field, _: &dyn (core::fmt::Debug)) {
1118                assert_eq!(field.callsite(), TEST_META_1.callsite())
1119            }
1120        }
1121        let valueset = fields.value_set(values);
1122        valueset.record(&mut MyVisitor);
1123    }
1124
1125    #[test]
1126    fn empty_fields_are_skipped() {
1127        let fields = TEST_META_1.fields();
1128        let values = &[
1129            (&fields.field("foo").unwrap(), Some(&Empty as &dyn Value)),
1130            (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1131            (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1132        ];
1133
1134        struct MyVisitor;
1135        impl Visit for MyVisitor {
1136            fn record_debug(&mut self, field: &Field, _: &dyn (core::fmt::Debug)) {
1137                assert_eq!(field.name(), "bar")
1138            }
1139        }
1140        let valueset = fields.value_set(values);
1141        valueset.record(&mut MyVisitor);
1142    }
1143
1144    #[test]
1145    #[cfg(feature = "std")]
1146    fn record_debug_fn() {
1147        let fields = TEST_META_1.fields();
1148        let values = &[
1149            (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1150            (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1151            (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1152        ];
1153        let valueset = fields.value_set(values);
1154        let mut result = String::new();
1155        valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1156            use core::fmt::Write;
1157            write!(&mut result, "{:?}", value).unwrap();
1158        });
1159        assert_eq!(result, String::from("123"));
1160    }
1161
1162    #[test]
1163    #[cfg(feature = "std")]
1164    fn record_error() {
1165        let fields = TEST_META_1.fields();
1166        let err: Box<dyn std::error::Error + Send + Sync + 'static> =
1167            std::io::Error::new(std::io::ErrorKind::Other, "lol").into();
1168        let values = &[
1169            (&fields.field("foo").unwrap(), Some(&err as &dyn Value)),
1170            (&fields.field("bar").unwrap(), Some(&Empty as &dyn Value)),
1171            (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1172        ];
1173        let valueset = fields.value_set(values);
1174        let mut result = String::new();
1175        valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1176            use core::fmt::Write;
1177            write!(&mut result, "{:?}", value).unwrap();
1178        });
1179        assert_eq!(result, format!("{}", err));
1180    }
1181
1182    #[test]
1183    fn record_bytes() {
1184        let fields = TEST_META_1.fields();
1185        let first = &b"abc"[..];
1186        let second: &[u8] = &[192, 255, 238];
1187        let values = &[
1188            (&fields.field("foo").unwrap(), Some(&first as &dyn Value)),
1189            (&fields.field("bar").unwrap(), Some(&" " as &dyn Value)),
1190            (&fields.field("baz").unwrap(), Some(&second as &dyn Value)),
1191        ];
1192        let valueset = fields.value_set(values);
1193        let mut result = String::new();
1194        valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1195            use core::fmt::Write;
1196            write!(&mut result, "{:?}", value).unwrap();
1197        });
1198        assert_eq!(result, format!("{}", r#"[61 62 63]" "[c0 ff ee]"#));
1199    }
1200}