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