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