1 //! `Span` and `Event` key-value data.
2 //!
3 //! Spans and events may be annotated with key-value data, referred to as _fields_.
4 //! 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 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`, `bool`, and `&str`) or using a `fmt::Display` or
20 //! `fmt::Debug` implementation. `Subscriber`s are provided these primitive
21 //! 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 //! [`fmt::Debug`]: std::fmt::Debug
98 //! [`fmt::Display`]: std::fmt::Debug
99 //! [`valuable`]: https://crates.io/crates/valuable
100 //! [`valuable::Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html
101 //! [`as_value`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html#tymethod.as_value
102 //! [`valuable::Value`]: https://docs.rs/valuable/latest/valuable/enum.Value.html
103 //! [`Subscriber`]: crate::Subscriber
104 //! [`record_value`]: Visit::record_value
105 //! [`record_debug`]: Visit::record_debug
106 //! [span]: mod@crate::span
107 //! [`Event`]: crate::event::Event
108 //! [`Metadata`]: crate::Metadata
109 //! [`Attributes`]: crate::span::Attributes
110 //! [`Record`]: crate::span::Record
111 //! [`new_span`]: crate::Subscriber::new_span
112 //! [`record`]: crate::Subscriber::record
113 //! [`event`]: crate::Subscriber::event
114 pub use tracing_core::field::*;
115 
116 use crate::Metadata;
117 
118 /// Trait implemented to allow a type to be used as a field key.
119 ///
120 /// <pre class="ignore" style="white-space:normal;font:inherit;">
121 /// <strong>Note</strong>: Although this is implemented for both the
122 /// <a href="./struct.Field.html"><code>Field</code></a> type <em>and</em> any
123 /// type that can be borrowed as an <code>&str</code>, only <code>Field</code>
124 /// allows <em>O</em>(1) access.
125 /// Indexing a field with a string results in an iterative search that performs
126 /// string comparisons. Thus, if possible, once the key for a field is known, it
127 /// should be used whenever possible.
128 /// </pre>
129 pub trait AsField: crate::sealed::Sealed {
130     /// Attempts to convert `&self` into a `Field` with the specified `metadata`.
131     ///
132     /// If `metadata` defines this field, then the field is returned. Otherwise,
133     /// this returns `None`.
as_field(&self, metadata: &Metadata<'_>) -> Option<Field>134     fn as_field(&self, metadata: &Metadata<'_>) -> Option<Field>;
135 }
136 
137 // ===== impl AsField =====
138 
139 impl AsField for Field {
140     #[inline]
as_field(&self, metadata: &Metadata<'_>) -> Option<Field>141     fn as_field(&self, metadata: &Metadata<'_>) -> Option<Field> {
142         if self.callsite() == metadata.callsite() {
143             Some(self.clone())
144         } else {
145             None
146         }
147     }
148 }
149 
150 impl<'a> AsField for &'a Field {
151     #[inline]
as_field(&self, metadata: &Metadata<'_>) -> Option<Field>152     fn as_field(&self, metadata: &Metadata<'_>) -> Option<Field> {
153         if self.callsite() == metadata.callsite() {
154             Some((*self).clone())
155         } else {
156             None
157         }
158     }
159 }
160 
161 impl AsField for str {
162     #[inline]
as_field(&self, metadata: &Metadata<'_>) -> Option<Field>163     fn as_field(&self, metadata: &Metadata<'_>) -> Option<Field> {
164         metadata.fields().field(&self)
165     }
166 }
167 
168 impl crate::sealed::Sealed for Field {}
169 impl<'a> crate::sealed::Sealed for &'a Field {}
170 impl crate::sealed::Sealed for str {}
171