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