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`, `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 //! we might record integers by incrementing counters for their field names,
28 //! rather than printing them.
29 //!
30 //! [`Value`]: trait.Value.html
31 //! [span]: ../span/
32 //! [`Event`]: ../event/struct.Event.html
33 //! [`Metadata`]: ../metadata/struct.Metadata.html
34 //! [`Attributes`]:  ../span/struct.Attributes.html
35 //! [`Record`]: ../span/struct.Record.html
36 //! [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
37 //! [`record`]: ../subscriber/trait.Subscriber.html#method.record
38 //! [`event`]:  ../subscriber/trait.Subscriber.html#method.event
39 //! [`Value::record`]: trait.Value.html#method.record
40 //! [`Visit`]: trait.Visit.html
41 use crate::callsite;
42 use crate::stdlib::{
43     borrow::Borrow,
44     fmt,
45     hash::{Hash, Hasher},
46     num,
47     ops::Range,
48 };
49 
50 use self::private::ValidLen;
51 
52 /// An opaque key allowing _O_(1) access to a field in a `Span`'s key-value
53 /// data.
54 ///
55 /// As keys are defined by the _metadata_ of a span, rather than by an
56 /// individual instance of a span, a key may be used to access the same field
57 /// across all instances of a given span with the same metadata. Thus, when a
58 /// subscriber observes a new span, it need only access a field by name _once_,
59 /// and use the key for that name for all other accesses.
60 #[derive(Debug)]
61 pub struct Field {
62     i: usize,
63     fields: FieldSet,
64 }
65 
66 /// An empty field.
67 ///
68 /// This can be used to indicate that the value of a field is not currently
69 /// present but will be recorded later.
70 ///
71 /// When a field's value is `Empty`. it will not be recorded.
72 #[derive(Debug, Eq, PartialEq)]
73 pub struct Empty;
74 
75 /// Describes the fields present on a span.
76 pub struct FieldSet {
77     /// The names of each field on the described span.
78     names: &'static [&'static str],
79     /// The callsite where the described span originates.
80     callsite: callsite::Identifier,
81 }
82 
83 /// A set of fields and values for a span.
84 pub struct ValueSet<'a> {
85     values: &'a [(&'a Field, Option<&'a (dyn Value + 'a)>)],
86     fields: &'a FieldSet,
87 }
88 
89 /// An iterator over a set of fields.
90 #[derive(Debug)]
91 pub struct Iter {
92     idxs: Range<usize>,
93     fields: FieldSet,
94 }
95 
96 /// Visits typed values.
97 ///
98 /// An instance of `Visit` ("a visitor") represents the logic necessary to
99 /// record field values of various types. When an implementor of [`Value`] is
100 /// [recorded], it calls the appropriate method on the provided visitor to
101 /// indicate the type that value should be recorded as.
102 ///
103 /// When a [`Subscriber`] implementation [records an `Event`] or a
104 /// [set of `Value`s added to a `Span`], it can pass an `&mut Visit` to the
105 /// `record` method on the provided [`ValueSet`] or [`Event`]. This visitor
106 /// will then be used to record all the field-value pairs present on that
107 /// `Event` or `ValueSet`.
108 ///
109 /// # Examples
110 ///
111 /// A simple visitor that writes to a string might be implemented like so:
112 /// ```
113 /// # extern crate tracing_core as tracing;
114 /// use std::fmt::{self, Write};
115 /// use tracing::field::{Value, Visit, Field};
116 /// pub struct StringVisitor<'a> {
117 ///     string: &'a mut String,
118 /// }
119 ///
120 /// impl<'a> Visit for StringVisitor<'a> {
121 ///     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
122 ///         write!(self.string, "{} = {:?}; ", field.name(), value).unwrap();
123 ///     }
124 /// }
125 /// ```
126 /// This visitor will format each recorded value using `fmt::Debug`, and
127 /// append the field name and formatted value to the provided string,
128 /// regardless of the type of the recorded value. When all the values have
129 /// been recorded, the `StringVisitor` may be dropped, allowing the string
130 /// to be printed or stored in some other data structure.
131 ///
132 /// The `Visit` trait provides default implementations for `record_i64`,
133 /// `record_u64`, `record_bool`, `record_str`, and `record_error`, which simply
134 /// forward the recorded value to `record_debug`. Thus, `record_debug` is the
135 /// only method which a `Visit` implementation *must* implement. However,
136 /// visitors may override the default implementations of these functions in
137 /// order to implement type-specific behavior.
138 ///
139 /// Additionally, when a visitor receives a value of a type it does not care
140 /// about, it is free to ignore those values completely. For example, a
141 /// visitor which only records numeric data might look like this:
142 ///
143 /// ```
144 /// # extern crate tracing_core as tracing;
145 /// # use std::fmt::{self, Write};
146 /// # use tracing::field::{Value, Visit, Field};
147 /// pub struct SumVisitor {
148 ///     sum: i64,
149 /// }
150 ///
151 /// impl Visit for SumVisitor {
152 ///     fn record_i64(&mut self, _field: &Field, value: i64) {
153 ///        self.sum += value;
154 ///     }
155 ///
156 ///     fn record_u64(&mut self, _field: &Field, value: u64) {
157 ///         self.sum += value as i64;
158 ///     }
159 ///
160 ///     fn record_debug(&mut self, _field: &Field, _value: &fmt::Debug) {
161 ///         // Do nothing
162 ///     }
163 /// }
164 /// ```
165 ///
166 /// This visitor (which is probably not particularly useful) keeps a running
167 /// sum of all the numeric values it records, and ignores all other values. A
168 /// more practical example of recording typed values is presented in
169 /// `examples/counters.rs`, which demonstrates a very simple metrics system
170 /// implemented using `tracing`.
171 ///
172 /// <div class="example-wrap" style="display:inline-block">
173 /// <pre class="ignore" style="white-space:normal;font:inherit;">
174 /// <strong>Note</strong>: The <code>record_error</code> trait method is only
175 /// available when the Rust standard library is present, as it requires the
176 /// <code>std::error::Error</code> trait.
177 /// </pre></div>
178 ///
179 /// [`Value`]: trait.Value.html
180 /// [recorded]: trait.Value.html#method.record
181 /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
182 /// [records an `Event`]: ../subscriber/trait.Subscriber.html#method.event
183 /// [set of `Value`s added to a `Span`]: ../subscriber/trait.Subscriber.html#method.record
184 /// [`Event`]: ../event/struct.Event.html
185 /// [`ValueSet`]: struct.ValueSet.html
186 pub trait Visit {
187     /// Visit a double-precision floating point value.
record_f64(&mut self, field: &Field, value: f64)188     fn record_f64(&mut self, field: &Field, value: f64) {
189         self.record_debug(field, &value)
190     }
191 
192     /// Visit a signed 64-bit integer value.
record_i64(&mut self, field: &Field, value: i64)193     fn record_i64(&mut self, field: &Field, value: i64) {
194         self.record_debug(field, &value)
195     }
196 
197     /// Visit an unsigned 64-bit integer value.
record_u64(&mut self, field: &Field, value: u64)198     fn record_u64(&mut self, field: &Field, value: u64) {
199         self.record_debug(field, &value)
200     }
201 
202     /// Visit a boolean value.
record_bool(&mut self, field: &Field, value: bool)203     fn record_bool(&mut self, field: &Field, value: bool) {
204         self.record_debug(field, &value)
205     }
206 
207     /// Visit a string value.
record_str(&mut self, field: &Field, value: &str)208     fn record_str(&mut self, field: &Field, value: &str) {
209         self.record_debug(field, &value)
210     }
211 
212     /// Records a type implementing `Error`.
213     ///
214     /// <div class="example-wrap" style="display:inline-block">
215     /// <pre class="ignore" style="white-space:normal;font:inherit;">
216     /// <strong>Note</strong>: This is only enabled when the Rust standard library is
217     /// present.
218     /// </pre>
219     #[cfg(feature = "std")]
220     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static))221     fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
222         self.record_debug(field, &format_args!("{}", value))
223     }
224 
225     /// Visit a value implementing `fmt::Debug`.
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)226     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug);
227 }
228 
229 /// A field value of an erased type.
230 ///
231 /// Implementors of `Value` may call the appropriate typed recording methods on
232 /// the [visitor] passed to their `record` method in order to indicate how
233 /// their data should be recorded.
234 ///
235 /// [visitor]: trait.Visit.html
236 pub trait Value: crate::sealed::Sealed {
237     /// Visits this value with the given `Visitor`.
record(&self, key: &Field, visitor: &mut dyn Visit)238     fn record(&self, key: &Field, visitor: &mut dyn Visit);
239 }
240 
241 /// A `Value` which serializes using `fmt::Display`.
242 ///
243 /// Uses `record_debug` in the `Value` implementation to
244 /// avoid an unnecessary evaluation.
245 #[derive(Clone)]
246 pub struct DisplayValue<T: fmt::Display>(T);
247 
248 /// A `Value` which serializes as a string using `fmt::Debug`.
249 #[derive(Clone)]
250 pub struct DebugValue<T: fmt::Debug>(T);
251 
252 /// Wraps a type implementing `fmt::Display` as a `Value` that can be
253 /// recorded using its `Display` implementation.
display<T>(t: T) -> DisplayValue<T> where T: fmt::Display,254 pub fn display<T>(t: T) -> DisplayValue<T>
255 where
256     T: fmt::Display,
257 {
258     DisplayValue(t)
259 }
260 
261 /// Wraps a type implementing `fmt::Debug` as a `Value` that can be
262 /// recorded using its `Debug` implementation.
debug<T>(t: T) -> DebugValue<T> where T: fmt::Debug,263 pub fn debug<T>(t: T) -> DebugValue<T>
264 where
265     T: fmt::Debug,
266 {
267     DebugValue(t)
268 }
269 
270 // ===== impl Visit =====
271 
272 impl<'a, 'b> Visit for fmt::DebugStruct<'a, 'b> {
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)273     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
274         self.field(field.name(), value);
275     }
276 }
277 
278 impl<'a, 'b> Visit for fmt::DebugMap<'a, 'b> {
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)279     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
280         self.entry(&format_args!("{}", field), value);
281     }
282 }
283 
284 impl<F> Visit for F
285 where
286     F: FnMut(&Field, &dyn fmt::Debug),
287 {
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)288     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
289         (self)(field, value)
290     }
291 }
292 
293 // ===== impl Value =====
294 
295 macro_rules! impl_values {
296     ( $( $record:ident( $( $whatever:tt)+ ) ),+ ) => {
297         $(
298             impl_value!{ $record( $( $whatever )+ ) }
299         )+
300     }
301 }
302 
303 macro_rules! ty_to_nonzero {
304     (u8) => {
305         NonZeroU8
306     };
307     (u16) => {
308         NonZeroU16
309     };
310     (u32) => {
311         NonZeroU32
312     };
313     (u64) => {
314         NonZeroU64
315     };
316     (u128) => {
317         NonZeroU128
318     };
319     (usize) => {
320         NonZeroUsize
321     };
322     (i8) => {
323         NonZeroI8
324     };
325     (i16) => {
326         NonZeroI16
327     };
328     (i32) => {
329         NonZeroI32
330     };
331     (i64) => {
332         NonZeroI64
333     };
334     (i128) => {
335         NonZeroI128
336     };
337     (isize) => {
338         NonZeroIsize
339     };
340 }
341 
342 macro_rules! impl_one_value {
343     (f32, $op:expr, $record:ident) => {
344         impl_one_value!(normal, f32, $op, $record);
345     };
346     (f64, $op:expr, $record:ident) => {
347         impl_one_value!(normal, f64, $op, $record);
348     };
349     (bool, $op:expr, $record:ident) => {
350         impl_one_value!(normal, bool, $op, $record);
351     };
352     ($value_ty:tt, $op:expr, $record:ident) => {
353         impl_one_value!(normal, $value_ty, $op, $record);
354         impl_one_value!(nonzero, $value_ty, $op, $record);
355     };
356     (normal, $value_ty:tt, $op:expr, $record:ident) => {
357         impl $crate::sealed::Sealed for $value_ty {}
358         impl $crate::field::Value for $value_ty {
359             fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
360                 visitor.$record(key, $op(*self))
361             }
362         }
363     };
364     (nonzero, $value_ty:tt, $op:expr, $record:ident) => {
365         // This `use num::*;` is reported as unused because it gets emitted
366         // for every single invocation of this macro, so there are multiple `use`s.
367         // All but the first are useless indeed.
368         // We need this import because we can't write a path where one part is
369         // the `ty_to_nonzero!($value_ty)` invocation.
370         #[allow(clippy::useless_attribute, unused)]
371         use num::*;
372         impl $crate::sealed::Sealed for ty_to_nonzero!($value_ty) {}
373         impl $crate::field::Value for ty_to_nonzero!($value_ty) {
374             fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
375                 visitor.$record(key, $op(self.get()))
376             }
377         }
378     };
379 }
380 
381 macro_rules! impl_value {
382     ( $record:ident( $( $value_ty:tt ),+ ) ) => {
383         $(
384             impl_one_value!($value_ty, |this: $value_ty| this, $record);
385         )+
386     };
387     ( $record:ident( $( $value_ty:tt ),+ as $as_ty:ty) ) => {
388         $(
389             impl_one_value!($value_ty, |this: $value_ty| this as $as_ty, $record);
390         )+
391     };
392 }
393 
394 // ===== impl Value =====
395 
396 impl_values! {
397     record_u64(u64),
398     record_u64(usize, u32, u16, u8 as u64),
399     record_i64(i64),
400     record_i64(isize, i32, i16, i8 as i64),
401     record_bool(bool),
402     record_f64(f64, f32 as f64)
403 }
404 
405 impl<T: crate::sealed::Sealed> crate::sealed::Sealed for Wrapping<T> {}
406 impl<T: crate::field::Value> crate::field::Value for Wrapping<T> {
record(&self, key: &crate::field::Field, visitor: &mut dyn crate::field::Visit)407     fn record(&self, key: &crate::field::Field, visitor: &mut dyn crate::field::Visit) {
408         self.0.record(key, visitor)
409     }
410 }
411 
412 impl crate::sealed::Sealed for str {}
413 
414 impl Value for str {
record(&self, key: &Field, visitor: &mut dyn Visit)415     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
416         visitor.record_str(key, self)
417     }
418 }
419 
420 #[cfg(feature = "std")]
421 impl crate::sealed::Sealed for dyn std::error::Error + 'static {}
422 
423 #[cfg(feature = "std")]
424 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
425 impl Value for dyn std::error::Error + 'static {
record(&self, key: &Field, visitor: &mut dyn Visit)426     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
427         visitor.record_error(key, self)
428     }
429 }
430 
431 impl<'a, T: ?Sized> crate::sealed::Sealed for &'a T where T: Value + crate::sealed::Sealed + 'a {}
432 
433 impl<'a, T: ?Sized> Value for &'a T
434 where
435     T: Value + 'a,
436 {
record(&self, key: &Field, visitor: &mut dyn Visit)437     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
438         (*self).record(key, visitor)
439     }
440 }
441 
442 impl<'a, T: ?Sized> crate::sealed::Sealed for &'a mut T where T: Value + crate::sealed::Sealed + 'a {}
443 
444 impl<'a, T: ?Sized> Value for &'a mut T
445 where
446     T: Value + 'a,
447 {
record(&self, key: &Field, visitor: &mut dyn Visit)448     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
449         // Don't use `(*self).record(key, visitor)`, otherwise would
450         // cause stack overflow due to `unconditional_recursion`.
451         T::record(self, key, visitor)
452     }
453 }
454 
455 impl<'a> crate::sealed::Sealed for fmt::Arguments<'a> {}
456 
457 impl<'a> Value for fmt::Arguments<'a> {
record(&self, key: &Field, visitor: &mut dyn Visit)458     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
459         visitor.record_debug(key, self)
460     }
461 }
462 
463 impl fmt::Debug for dyn Value {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result464     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465         // We are only going to be recording the field value, so we don't
466         // actually care about the field name here.
467         struct NullCallsite;
468         static NULL_CALLSITE: NullCallsite = NullCallsite;
469         impl crate::callsite::Callsite for NullCallsite {
470             fn set_interest(&self, _: crate::subscriber::Interest) {
471                 unreachable!("you somehow managed to register the null callsite?")
472             }
473 
474             fn metadata(&self) -> &crate::Metadata<'_> {
475                 unreachable!("you somehow managed to access the null callsite?")
476             }
477         }
478 
479         static FIELD: Field = Field {
480             i: 0,
481             fields: FieldSet::new(&[], crate::identify_callsite!(&NULL_CALLSITE)),
482         };
483 
484         let mut res = Ok(());
485         self.record(&FIELD, &mut |_: &Field, val: &dyn fmt::Debug| {
486             res = write!(f, "{:?}", val);
487         });
488         res
489     }
490 }
491 
492 impl fmt::Display for dyn Value {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result493     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494         fmt::Debug::fmt(self, f)
495     }
496 }
497 
498 // ===== impl DisplayValue =====
499 
500 impl<T: fmt::Display> crate::sealed::Sealed for DisplayValue<T> {}
501 
502 impl<T> Value for DisplayValue<T>
503 where
504     T: fmt::Display,
505 {
record(&self, key: &Field, visitor: &mut dyn Visit)506     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
507         visitor.record_debug(key, &format_args!("{}", self.0))
508     }
509 }
510 
511 impl<T: fmt::Display> fmt::Debug for DisplayValue<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result512     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513         write!(f, "{}", self.0)
514     }
515 }
516 
517 impl<T: fmt::Display> fmt::Display for DisplayValue<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result518     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519         fmt::Display::fmt(&self.0, f)
520     }
521 }
522 
523 // ===== impl DebugValue =====
524 
525 impl<T: fmt::Debug> crate::sealed::Sealed for DebugValue<T> {}
526 
527 impl<T> Value for DebugValue<T>
528 where
529     T: fmt::Debug,
530 {
record(&self, key: &Field, visitor: &mut dyn Visit)531     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
532         visitor.record_debug(key, &self.0)
533     }
534 }
535 
536 impl<T: fmt::Debug> fmt::Debug for DebugValue<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result537     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
538         write!(f, "{:?}", self.0)
539     }
540 }
541 
542 impl crate::sealed::Sealed for Empty {}
543 impl Value for Empty {
544     #[inline]
record(&self, _: &Field, _: &mut dyn Visit)545     fn record(&self, _: &Field, _: &mut dyn Visit) {}
546 }
547 
548 impl<T: Value> crate::sealed::Sealed for Option<T> {}
549 
550 impl<T: Value> Value for Option<T> {
record(&self, key: &Field, visitor: &mut dyn Visit)551     fn record(&self, key: &Field, visitor: &mut dyn Visit) {
552         if let Some(v) = &self {
553             v.record(key, visitor)
554         }
555     }
556 }
557 
558 // ===== impl Field =====
559 
560 impl Field {
561     /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`]
562     /// which defines this field.
563     ///
564     /// [`Identifier`]: ../callsite/struct.Identifier.html
565     /// [`Callsite`]: ../callsite/trait.Callsite.html
566     #[inline]
callsite(&self) -> callsite::Identifier567     pub fn callsite(&self) -> callsite::Identifier {
568         self.fields.callsite()
569     }
570 
571     /// Returns a string representing the name of the field.
name(&self) -> &'static str572     pub fn name(&self) -> &'static str {
573         self.fields.names[self.i]
574     }
575 }
576 
577 impl fmt::Display for Field {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result578     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579         f.pad(self.name())
580     }
581 }
582 
583 impl AsRef<str> for Field {
as_ref(&self) -> &str584     fn as_ref(&self) -> &str {
585         self.name()
586     }
587 }
588 
589 impl PartialEq for Field {
eq(&self, other: &Self) -> bool590     fn eq(&self, other: &Self) -> bool {
591         self.callsite() == other.callsite() && self.i == other.i
592     }
593 }
594 
595 impl Eq for Field {}
596 
597 impl Hash for Field {
hash<H>(&self, state: &mut H) where H: Hasher,598     fn hash<H>(&self, state: &mut H)
599     where
600         H: Hasher,
601     {
602         self.callsite().hash(state);
603         self.i.hash(state);
604     }
605 }
606 
607 impl Clone for Field {
clone(&self) -> Self608     fn clone(&self) -> Self {
609         Field {
610             i: self.i,
611             fields: FieldSet {
612                 names: self.fields.names,
613                 callsite: self.fields.callsite(),
614             },
615         }
616     }
617 }
618 
619 // ===== impl FieldSet =====
620 
621 impl FieldSet {
622     /// Constructs a new `FieldSet` with the given array of field names and callsite.
new(names: &'static [&'static str], callsite: callsite::Identifier) -> Self623     pub const fn new(names: &'static [&'static str], callsite: callsite::Identifier) -> Self {
624         Self { names, callsite }
625     }
626 
627     /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`]
628     /// which defines this set of fields..
629     ///
630     /// [`Identifier`]: ../callsite/struct.Identifier.html
631     /// [`Callsite`]: ../callsite/trait.Callsite.html
callsite(&self) -> callsite::Identifier632     pub(crate) fn callsite(&self) -> callsite::Identifier {
633         callsite::Identifier(self.callsite.0)
634     }
635 
636     /// Returns the [`Field`] named `name`, or `None` if no such field exists.
637     ///
638     /// [`Field`]: ../struct.Field.html
field<Q: ?Sized>(&self, name: &Q) -> Option<Field> where Q: Borrow<str>,639     pub fn field<Q: ?Sized>(&self, name: &Q) -> Option<Field>
640     where
641         Q: Borrow<str>,
642     {
643         let name = &name.borrow();
644         self.names.iter().position(|f| f == name).map(|i| Field {
645             i,
646             fields: FieldSet {
647                 names: self.names,
648                 callsite: self.callsite(),
649             },
650         })
651     }
652 
653     /// Returns `true` if `self` contains the given `field`.
654     ///
655     /// <div class="example-wrap" style="display:inline-block">
656     /// <pre class="ignore" style="white-space:normal;font:inherit;">
657     /// <strong>Note</strong>: If <code>field</code> shares a name with a field
658     /// in this <code>FieldSet</code>, but was created by a <code>FieldSet</code>
659     /// with a different callsite, this <code>FieldSet</code> does <em>not</em>
660     /// contain it. This is so that if two separate span callsites define a field
661     /// named "foo", the <code>Field</code> corresponding to "foo" for each
662     /// of those callsites are not equivalent.
663     /// </pre></div>
contains(&self, field: &Field) -> bool664     pub fn contains(&self, field: &Field) -> bool {
665         field.callsite() == self.callsite() && field.i <= self.len()
666     }
667 
668     /// Returns an iterator over the `Field`s in this `FieldSet`.
iter(&self) -> Iter669     pub fn iter(&self) -> Iter {
670         let idxs = 0..self.len();
671         Iter {
672             idxs,
673             fields: FieldSet {
674                 names: self.names,
675                 callsite: self.callsite(),
676             },
677         }
678     }
679 
680     /// Returns a new `ValueSet` with entries for this `FieldSet`'s values.
681     ///
682     /// Note that a `ValueSet` may not be constructed with arrays of over 32
683     /// elements.
684     #[doc(hidden)]
value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v> where V: ValidLen<'v>,685     pub fn value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v>
686     where
687         V: ValidLen<'v>,
688     {
689         ValueSet {
690             fields: self,
691             values: values.borrow(),
692         }
693     }
694 
695     /// Returns the number of fields in this `FieldSet`.
696     #[inline]
len(&self) -> usize697     pub fn len(&self) -> usize {
698         self.names.len()
699     }
700 
701     /// Returns whether or not this `FieldSet` has fields.
702     #[inline]
is_empty(&self) -> bool703     pub fn is_empty(&self) -> bool {
704         self.names.is_empty()
705     }
706 }
707 
708 impl<'a> IntoIterator for &'a FieldSet {
709     type IntoIter = Iter;
710     type Item = Field;
711     #[inline]
into_iter(self) -> Self::IntoIter712     fn into_iter(self) -> Self::IntoIter {
713         self.iter()
714     }
715 }
716 
717 impl fmt::Debug for FieldSet {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result718     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
719         f.debug_struct("FieldSet")
720             .field("names", &self.names)
721             .field("callsite", &self.callsite)
722             .finish()
723     }
724 }
725 
726 impl fmt::Display for FieldSet {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result727     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
728         f.debug_set()
729             .entries(self.names.iter().map(display))
730             .finish()
731     }
732 }
733 
734 // ===== impl Iter =====
735 
736 impl Iterator for Iter {
737     type Item = Field;
next(&mut self) -> Option<Field>738     fn next(&mut self) -> Option<Field> {
739         let i = self.idxs.next()?;
740         Some(Field {
741             i,
742             fields: FieldSet {
743                 names: self.fields.names,
744                 callsite: self.fields.callsite(),
745             },
746         })
747     }
748 }
749 
750 // ===== impl ValueSet =====
751 
752 impl<'a> ValueSet<'a> {
753     /// Returns an [`Identifier`] that uniquely identifies the [`Callsite`]
754     /// defining the fields this `ValueSet` refers to.
755     ///
756     /// [`Identifier`]: ../callsite/struct.Identifier.html
757     /// [`Callsite`]: ../callsite/trait.Callsite.html
758     #[inline]
callsite(&self) -> callsite::Identifier759     pub fn callsite(&self) -> callsite::Identifier {
760         self.fields.callsite()
761     }
762 
763     /// Visits all the fields in this `ValueSet` with the provided [visitor].
764     ///
765     /// [visitor]: ../trait.Visit.html
record(&self, visitor: &mut dyn Visit)766     pub(crate) fn record(&self, visitor: &mut dyn Visit) {
767         let my_callsite = self.callsite();
768         for (field, value) in self.values {
769             if field.callsite() != my_callsite {
770                 continue;
771             }
772             if let Some(value) = value {
773                 value.record(field, visitor);
774             }
775         }
776     }
777 
778     /// Returns `true` if this `ValueSet` contains a value for the given `Field`.
contains(&self, field: &Field) -> bool779     pub(crate) fn contains(&self, field: &Field) -> bool {
780         field.callsite() == self.callsite()
781             && self
782                 .values
783                 .iter()
784                 .any(|(key, val)| *key == field && val.is_some())
785     }
786 
787     /// Returns true if this `ValueSet` contains _no_ values.
is_empty(&self) -> bool788     pub(crate) fn is_empty(&self) -> bool {
789         let my_callsite = self.callsite();
790         self.values
791             .iter()
792             .all(|(key, val)| val.is_none() || key.callsite() != my_callsite)
793     }
794 
field_set(&self) -> &FieldSet795     pub(crate) fn field_set(&self) -> &FieldSet {
796         self.fields
797     }
798 }
799 
800 impl<'a> fmt::Debug for ValueSet<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result801     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
802         self.values
803             .iter()
804             .fold(&mut f.debug_struct("ValueSet"), |dbg, (key, v)| {
805                 if let Some(val) = v {
806                     val.record(key, dbg);
807                 }
808                 dbg
809             })
810             .field("callsite", &self.callsite())
811             .finish()
812     }
813 }
814 
815 impl<'a> fmt::Display for ValueSet<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result816     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817         self.values
818             .iter()
819             .fold(&mut f.debug_map(), |dbg, (key, v)| {
820                 if let Some(val) = v {
821                     val.record(key, dbg);
822                 }
823                 dbg
824             })
825             .finish()
826     }
827 }
828 
829 // ===== impl ValidLen =====
830 
831 mod private {
832     use super::*;
833 
834     /// Marker trait implemented by arrays which are of valid length to
835     /// construct a `ValueSet`.
836     ///
837     /// `ValueSet`s may only be constructed from arrays containing 32 or fewer
838     /// elements, to ensure the array is small enough to always be allocated on the
839     /// stack. This trait is only implemented by arrays of an appropriate length,
840     /// ensuring that the correct size arrays are used at compile-time.
841     pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (dyn Value + 'a)>)]> {}
842 }
843 
844 macro_rules! impl_valid_len {
845     ( $( $len:tt ),+ ) => {
846         $(
847             impl<'a> private::ValidLen<'a> for
848                 [(&'a Field, Option<&'a (dyn Value + 'a)>); $len] {}
849         )+
850     }
851 }
852 
853 impl_valid_len! {
854     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
855     21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
856 }
857 
858 #[cfg(test)]
859 mod test {
860     use super::*;
861     use crate::metadata::{Kind, Level, Metadata};
862     use crate::stdlib::{borrow::ToOwned, string::String};
863 
864     struct TestCallsite1;
865     static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1;
866     static TEST_META_1: Metadata<'static> = metadata! {
867         name: "field_test1",
868         target: module_path!(),
869         level: Level::INFO,
870         fields: &["foo", "bar", "baz"],
871         callsite: &TEST_CALLSITE_1,
872         kind: Kind::SPAN,
873     };
874 
875     impl crate::callsite::Callsite for TestCallsite1 {
set_interest(&self, _: crate::subscriber::Interest)876         fn set_interest(&self, _: crate::subscriber::Interest) {
877             unimplemented!()
878         }
879 
metadata(&self) -> &Metadata<'_>880         fn metadata(&self) -> &Metadata<'_> {
881             &TEST_META_1
882         }
883     }
884 
885     struct TestCallsite2;
886     static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2;
887     static TEST_META_2: Metadata<'static> = metadata! {
888         name: "field_test2",
889         target: module_path!(),
890         level: Level::INFO,
891         fields: &["foo", "bar", "baz"],
892         callsite: &TEST_CALLSITE_2,
893         kind: Kind::SPAN,
894     };
895 
896     impl crate::callsite::Callsite for TestCallsite2 {
set_interest(&self, _: crate::subscriber::Interest)897         fn set_interest(&self, _: crate::subscriber::Interest) {
898             unimplemented!()
899         }
900 
metadata(&self) -> &Metadata<'_>901         fn metadata(&self) -> &Metadata<'_> {
902             &TEST_META_2
903         }
904     }
905 
906     #[test]
value_set_with_no_values_is_empty()907     fn value_set_with_no_values_is_empty() {
908         let fields = TEST_META_1.fields();
909         let values = &[
910             (&fields.field("foo").unwrap(), None),
911             (&fields.field("bar").unwrap(), None),
912             (&fields.field("baz").unwrap(), None),
913         ];
914         let valueset = fields.value_set(values);
915         assert!(valueset.is_empty());
916     }
917 
918     #[test]
empty_value_set_is_empty()919     fn empty_value_set_is_empty() {
920         let fields = TEST_META_1.fields();
921         let valueset = fields.value_set(&[]);
922         assert!(valueset.is_empty());
923     }
924 
925     #[test]
value_sets_with_fields_from_other_callsites_are_empty()926     fn value_sets_with_fields_from_other_callsites_are_empty() {
927         let fields = TEST_META_1.fields();
928         let values = &[
929             (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
930             (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
931             (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
932         ];
933         let valueset = TEST_META_2.fields().value_set(values);
934         assert!(valueset.is_empty())
935     }
936 
937     #[test]
sparse_value_sets_are_not_empty()938     fn sparse_value_sets_are_not_empty() {
939         let fields = TEST_META_1.fields();
940         let values = &[
941             (&fields.field("foo").unwrap(), None),
942             (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
943             (&fields.field("baz").unwrap(), None),
944         ];
945         let valueset = fields.value_set(values);
946         assert!(!valueset.is_empty());
947     }
948 
949     #[test]
fields_from_other_callsets_are_skipped()950     fn fields_from_other_callsets_are_skipped() {
951         let fields = TEST_META_1.fields();
952         let values = &[
953             (&fields.field("foo").unwrap(), None),
954             (
955                 &TEST_META_2.fields().field("bar").unwrap(),
956                 Some(&57 as &dyn Value),
957             ),
958             (&fields.field("baz").unwrap(), None),
959         ];
960 
961         struct MyVisitor;
962         impl Visit for MyVisitor {
963             fn record_debug(&mut self, field: &Field, _: &dyn (crate::stdlib::fmt::Debug)) {
964                 assert_eq!(field.callsite(), TEST_META_1.callsite())
965             }
966         }
967         let valueset = fields.value_set(values);
968         valueset.record(&mut MyVisitor);
969     }
970 
971     #[test]
empty_fields_are_skipped()972     fn empty_fields_are_skipped() {
973         let fields = TEST_META_1.fields();
974         let values = &[
975             (&fields.field("foo").unwrap(), Some(&Empty as &dyn Value)),
976             (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
977             (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
978         ];
979 
980         struct MyVisitor;
981         impl Visit for MyVisitor {
982             fn record_debug(&mut self, field: &Field, _: &dyn (crate::stdlib::fmt::Debug)) {
983                 assert_eq!(field.name(), "bar")
984             }
985         }
986         let valueset = fields.value_set(values);
987         valueset.record(&mut MyVisitor);
988     }
989 
990     #[test]
record_debug_fn()991     fn record_debug_fn() {
992         let fields = TEST_META_1.fields();
993         let values = &[
994             (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
995             (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
996             (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
997         ];
998         let valueset = fields.value_set(values);
999         let mut result = String::new();
1000         valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1001             use crate::stdlib::fmt::Write;
1002             write!(&mut result, "{:?}", value).unwrap();
1003         });
1004         assert_eq!(result, "123".to_owned());
1005     }
1006 }
1007