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