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