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
112use crate::callsite;
113use crate::stdlib::{
114 borrow::Borrow,
115 fmt,
116 hash::{Hash, Hasher},
117 num,
118 ops::Range,
119 string::String,
120};
121
122use 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)]
133pub 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)]
145pub 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
158pub 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.
166pub 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)]
173pub 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
266pub 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"))))]
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.
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.
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.
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.
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.
297 fn record_u128(&mut self, field: &Field, value: u128) {
298 self.record_debug(field, &value)
299 }
300
301 /// Visit a boolean value.
302 fn record_bool(&mut self, field: &Field, value: bool) {
303 self.record_debug(field, &value)
304 }
305
306 /// Visit a string value.
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")))]
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`.
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
335pub trait Value: crate::sealed::Sealed {
336 /// Visits this value with the given `Visitor`.
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)]
345pub struct DisplayValue<T: fmt::Display>(T);
346
347/// A `Value` which serializes as a string using `fmt::Debug`.
348#[derive(Clone)]
349pub 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.
353pub fn display<T>(t: T) -> DisplayValue<T>
354where
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.
362pub fn debug<T>(t: T) -> DebugValue<T>
363where
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"))))]
375pub fn valuable<T>(t: &T) -> valuable::Value<'_>
376where
377 T: valuable::Valuable,
378{
379 t.as_value()
380}
381
382// ===== impl Visit =====
383
384impl<'a, 'b> Visit for fmt::DebugStruct<'a, 'b> {
385 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
386 self.field(field.name(), value);
387 }
388}
389
390impl<'a, 'b> Visit for fmt::DebugMap<'a, 'b> {
391 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
392 self.entry(&format_args!("{}", field), value);
393 }
394}
395
396impl<F> Visit for F
397where
398 F: FnMut(&Field, &dyn fmt::Debug),
399{
400 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
401 (self)(field, value)
402 }
403}
404
405// ===== impl Value =====
406
407macro_rules! impl_values {
408 ( $( $record:ident( $( $whatever:tt)+ ) ),+ ) => {
409 $(
410 impl_value!{ $record( $( $whatever )+ ) }
411 )+
412 }
413}
414
415macro_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
454macro_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
493macro_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
508impl_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
519impl<T: crate::sealed::Sealed> crate::sealed::Sealed for Wrapping<T> {}
520impl<T: crate::field::Value> crate::field::Value for Wrapping<T> {
521 fn record(&self, key: &crate::field::Field, visitor: &mut dyn crate::field::Visit) {
522 self.0.record(key, visitor)
523 }
524}
525
526impl crate::sealed::Sealed for str {}
527
528impl Value for str {
529 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
530 visitor.record_str(field:key, self)
531 }
532}
533
534#[cfg(feature = "std")]
535impl crate::sealed::Sealed for dyn std::error::Error + 'static {}
536
537#[cfg(feature = "std")]
538#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
539impl Value for dyn std::error::Error + 'static {
540 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
541 visitor.record_error(field:key, self)
542 }
543}
544
545#[cfg(feature = "std")]
546impl crate::sealed::Sealed for dyn std::error::Error + Send + 'static {}
547
548#[cfg(feature = "std")]
549#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
550impl Value for dyn std::error::Error + Send + 'static {
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")]
557impl crate::sealed::Sealed for dyn std::error::Error + Sync + 'static {}
558
559#[cfg(feature = "std")]
560#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
561impl Value for dyn std::error::Error + Sync + 'static {
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")]
568impl crate::sealed::Sealed for dyn std::error::Error + Send + Sync + 'static {}
569
570#[cfg(feature = "std")]
571#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
572impl Value for dyn std::error::Error + Send + Sync + 'static {
573 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
574 (self as &dyn std::error::Error).record(key, visitor)
575 }
576}
577
578impl<'a, T: ?Sized> crate::sealed::Sealed for &'a T where T: Value + crate::sealed::Sealed + 'a {}
579
580impl<'a, T: ?Sized> Value for &'a T
581where
582 T: Value + 'a,
583{
584 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
585 (*self).record(key, visitor)
586 }
587}
588
589impl<'a, T: ?Sized> crate::sealed::Sealed for &'a mut T where T: Value + crate::sealed::Sealed + 'a {}
590
591impl<'a, T: ?Sized> Value for &'a mut T
592where
593 T: Value + 'a,
594{
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
602impl<'a> crate::sealed::Sealed for fmt::Arguments<'a> {}
603
604impl<'a> Value for fmt::Arguments<'a> {
605 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
606 visitor.record_debug(field:key, self)
607 }
608}
609
610impl<T: ?Sized> crate::sealed::Sealed for crate::stdlib::boxed::Box<T> where T: Value {}
611
612impl<T: ?Sized> Value for crate::stdlib::boxed::Box<T>
613where
614 T: Value,
615{
616 #[inline]
617 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
618 self.as_ref().record(key, visitor)
619 }
620}
621
622impl crate::sealed::Sealed for String {}
623impl Value for String {
624 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
625 visitor.record_str(field:key, self.as_str())
626 }
627}
628
629impl fmt::Debug for dyn Value {
630 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
658impl fmt::Display for dyn Value {
659 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
660 fmt::Debug::fmt(self, f)
661 }
662}
663
664// ===== impl DisplayValue =====
665
666impl<T: fmt::Display> crate::sealed::Sealed for DisplayValue<T> {}
667
668impl<T> Value for DisplayValue<T>
669where
670 T: fmt::Display,
671{
672 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
673 visitor.record_debug(field:key, self)
674 }
675}
676
677impl<T: fmt::Display> fmt::Debug for DisplayValue<T> {
678 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
679 fmt::Display::fmt(self, f)
680 }
681}
682
683impl<T: fmt::Display> fmt::Display for DisplayValue<T> {
684 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685 self.0.fmt(f)
686 }
687}
688
689// ===== impl DebugValue =====
690
691impl<T: fmt::Debug> crate::sealed::Sealed for DebugValue<T> {}
692
693impl<T> Value for DebugValue<T>
694where
695 T: fmt::Debug,
696{
697 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
698 visitor.record_debug(field:key, &self.0)
699 }
700}
701
702impl<T: fmt::Debug> fmt::Debug for DebugValue<T> {
703 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"))]
711impl 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"))))]
715impl Value for valuable::Value<'_> {
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"))]
722impl 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"))))]
726impl Value for &'_ dyn valuable::Valuable {
727 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
728 visitor.record_value(key, self.as_value())
729 }
730}
731
732impl crate::sealed::Sealed for Empty {}
733impl Value for Empty {
734 #[inline]
735 fn record(&self, _: &Field, _: &mut dyn Visit) {}
736}
737
738impl<T: Value> crate::sealed::Sealed for Option<T> {}
739
740impl<T: Value> Value for Option<T> {
741 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
742 if let Some(v: &T) = &self {
743 v.record(key, visitor)
744 }
745 }
746}
747
748// ===== impl Field =====
749
750impl 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]
757 pub fn callsite(&self) -> callsite::Identifier {
758 self.fields.callsite()
759 }
760
761 /// Returns a string representing the name of the field.
762 pub fn name(&self) -> &'static str {
763 self.fields.names[self.i]
764 }
765}
766
767impl fmt::Display for Field {
768 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
769 f.pad(self.name())
770 }
771}
772
773impl AsRef<str> for Field {
774 fn as_ref(&self) -> &str {
775 self.name()
776 }
777}
778
779impl PartialEq for Field {
780 fn eq(&self, other: &Self) -> bool {
781 self.callsite() == other.callsite() && self.i == other.i
782 }
783}
784
785impl Eq for Field {}
786
787impl Hash for Field {
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
797impl Clone for Field {
798 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
811impl FieldSet {
812 /// Constructs a new `FieldSet` with the given array of field names and callsite.
813 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
822 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
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>
854 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`.
859 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)]
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]
887 pub fn len(&self) -> usize {
888 self.names.len()
889 }
890
891 /// Returns whether or not this `FieldSet` has fields.
892 #[inline]
893 pub fn is_empty(&self) -> bool {
894 self.names.is_empty()
895 }
896}
897
898impl<'a> IntoIterator for &'a FieldSet {
899 type IntoIter = Iter;
900 type Item = Field;
901 #[inline]
902 fn into_iter(self) -> Self::IntoIter {
903 self.iter()
904 }
905}
906
907impl fmt::Debug for FieldSet {
908 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
909 f&mut DebugStruct<'_, '_>.debug_struct("FieldSet")
910 .field("names", &self.names)
911 .field(name:"callsite", &self.callsite)
912 .finish()
913 }
914}
915
916impl fmt::Display for FieldSet {
917 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
918 f&mut DebugSet<'_, '_>.debug_set()
919 .entries(self.names.iter().map(display))
920 .finish()
921 }
922}
923
924impl Eq for FieldSet {}
925
926impl PartialEq for FieldSet {
927 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
960impl Iterator for Iter {
961 type Item = Field;
962 fn next(&mut self) -> Option<Field> {
963 let i: usize = 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
976impl<'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]
983 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
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()
1007 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`.
1016 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.
1025 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
1032 pub(crate) fn field_set(&self) -> &FieldSet {
1033 self.fields
1034 }
1035}
1036
1037impl<'a> fmt::Debug for ValueSet<'a> {
1038 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(name:"callsite", &self.callsite())
1048 .finish()
1049 }
1050}
1051
1052impl<'a> fmt::Display for ValueSet<'a> {
1053 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1054 self.values
1055 .iter()
1056 .fold(&mut f.debug_map(), |dbg: &mut DebugMap<'_, '_>, (key: &&Field, v: &Option<&dyn Value>)| {
1057 if let Some(val: &&dyn Value) = v {
1058 val.record(key, visitor:dbg);
1059 }
1060 dbg
1061 })
1062 .finish()
1063 }
1064}
1065
1066// ===== impl ValidLen =====
1067
1068mod 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
1081macro_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
1090impl_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)]
1096mod 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 {
1113 fn set_interest(&self, _: crate::subscriber::Interest) {
1114 unimplemented!()
1115 }
1116
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 {
1134 fn set_interest(&self, _: crate::subscriber::Interest) {
1135 unimplemented!()
1136 }
1137
1138 fn metadata(&self) -> &Metadata<'_> {
1139 &TEST_META_2
1140 }
1141 }
1142
1143 #[test]
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]
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]
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]
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]
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]
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]
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")]
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