• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Metadata describing trace data.
2 use super::{callsite, field};
3 use crate::stdlib::{
4     cmp, fmt,
5     str::FromStr,
6     sync::atomic::{AtomicUsize, Ordering},
7 };
8 
9 /// Metadata describing a [span] or [event].
10 ///
11 /// All spans and events have the following metadata:
12 /// - A [name], represented as a static string.
13 /// - A [target], a string that categorizes part of the system where the span
14 ///   or event occurred. The `tracing` macros default to using the module
15 ///   path where the span or event originated as the target, but it may be
16 ///   overridden.
17 /// - A [verbosity level]. This determines how verbose a given span or event
18 ///   is, and allows enabling or disabling more verbose diagnostics
19 ///   situationally. See the documentation for the [`Level`] type for details.
20 /// - The names of the [fields] defined by the span or event.
21 /// - Whether the metadata corresponds to a span or event.
22 ///
23 /// In addition, the following optional metadata describing the source code
24 /// location where the span or event originated _may_ be provided:
25 /// - The [file name]
26 /// - The [line number]
27 /// - The [module path]
28 ///
29 /// Metadata is used by [`Subscriber`]s when filtering spans and events, and it
30 /// may also be used as part of their data payload.
31 ///
32 /// When created by the `event!` or `span!` macro, the metadata describing a
33 /// particular event or span is constructed statically and exists as a single
34 /// static instance. Thus, the overhead of creating the metadata is
35 /// _significantly_ lower than that of creating the actual span. Therefore,
36 /// filtering is based on metadata, rather than on the constructed span.
37 ///
38 /// ## Equality
39 ///
40 /// In well-behaved applications, two `Metadata` with equal
41 /// [callsite identifiers] will be equal in all other ways (i.e., have the same
42 /// `name`, `target`, etc.). Consequently, in release builds, [`Metadata::eq`]
43 /// *only* checks that its arguments have equal callsites. However, the equality
44 /// of `Metadata`'s other fields is checked in debug builds.
45 ///
46 /// [span]: super::span
47 /// [event]: super::event
48 /// [name]: Self::name
49 /// [target]: Self::target
50 /// [fields]: Self::fields
51 /// [verbosity level]: Self::level
52 /// [file name]: Self::file
53 /// [line number]: Self::line
54 /// [module path]: Self::module_path
55 /// [`Subscriber`]: super::subscriber::Subscriber
56 /// [callsite identifiers]: Self::callsite
57 pub struct Metadata<'a> {
58     /// The name of the span described by this metadata.
59     name: &'static str,
60 
61     /// The part of the system that the span that this metadata describes
62     /// occurred in.
63     target: &'a str,
64 
65     /// The level of verbosity of the described span.
66     level: Level,
67 
68     /// The name of the Rust module where the span occurred, or `None` if this
69     /// could not be determined.
70     module_path: Option<&'a str>,
71 
72     /// The name of the source code file where the span occurred, or `None` if
73     /// this could not be determined.
74     file: Option<&'a str>,
75 
76     /// The line number in the source code file where the span occurred, or
77     /// `None` if this could not be determined.
78     line: Option<u32>,
79 
80     /// The names of the key-value fields attached to the described span or
81     /// event.
82     fields: field::FieldSet,
83 
84     /// The kind of the callsite.
85     kind: Kind,
86 }
87 
88 /// Indicates whether the callsite is a span or event.
89 #[derive(Clone, Eq, PartialEq)]
90 pub struct Kind(u8);
91 
92 /// Describes the level of verbosity of a span or event.
93 ///
94 /// # Comparing Levels
95 ///
96 /// `Level` implements the [`PartialOrd`] and [`Ord`] traits, allowing two
97 /// `Level`s to be compared to determine which is considered more or less
98 /// verbose. Levels which are more verbose are considered "greater than" levels
99 /// which are less verbose, with [`Level::ERROR`] considered the lowest, and
100 /// [`Level::TRACE`] considered the highest.
101 ///
102 /// For example:
103 /// ```
104 /// use tracing_core::Level;
105 ///
106 /// assert!(Level::TRACE > Level::DEBUG);
107 /// assert!(Level::ERROR < Level::WARN);
108 /// assert!(Level::INFO <= Level::DEBUG);
109 /// assert_eq!(Level::TRACE, Level::TRACE);
110 /// ```
111 ///
112 /// # Filtering
113 ///
114 /// `Level`s are typically used to implement filtering that determines which
115 /// spans and events are enabled. Depending on the use case, more or less
116 /// verbose diagnostics may be desired. For example, when running in
117 /// development, [`DEBUG`]-level traces may be enabled by default. When running in
118 /// production, only [`INFO`]-level and lower traces might be enabled. Libraries
119 /// may include very verbose diagnostics at the [`DEBUG`] and/or [`TRACE`] levels.
120 /// Applications using those libraries typically chose to ignore those traces. However, when
121 /// debugging an issue involving said libraries, it may be useful to temporarily
122 /// enable the more verbose traces.
123 ///
124 /// The [`LevelFilter`] type is provided to enable filtering traces by
125 /// verbosity. `Level`s can be compared against [`LevelFilter`]s, and
126 /// [`LevelFilter`] has a variant for each `Level`, which compares analogously
127 /// to that level. In addition, [`LevelFilter`] adds a [`LevelFilter::OFF`]
128 /// variant, which is considered "less verbose" than every other `Level`. This is
129 /// intended to allow filters to completely disable tracing in a particular context.
130 ///
131 /// For example:
132 /// ```
133 /// use tracing_core::{Level, LevelFilter};
134 ///
135 /// assert!(LevelFilter::OFF < Level::TRACE);
136 /// assert!(LevelFilter::TRACE > Level::DEBUG);
137 /// assert!(LevelFilter::ERROR < Level::WARN);
138 /// assert!(LevelFilter::INFO <= Level::DEBUG);
139 /// assert!(LevelFilter::INFO >= Level::INFO);
140 /// ```
141 ///
142 /// ## Examples
143 ///
144 /// Below is a simple example of how a [`Subscriber`] could implement filtering through
145 /// a [`LevelFilter`]. When a span or event is recorded, the [`Subscriber::enabled`] method
146 /// compares the span or event's `Level` against the configured [`LevelFilter`].
147 /// The optional [`Subscriber::max_level_hint`] method can also be implemented to allow spans
148 /// and events above a maximum verbosity level to be skipped more efficiently,
149 /// often improving performance in short-lived programs.
150 ///
151 /// ```
152 /// use tracing_core::{span, Event, Level, LevelFilter, Subscriber, Metadata};
153 /// # use tracing_core::span::{Id, Record, Current};
154 ///
155 /// #[derive(Debug)]
156 /// pub struct MySubscriber {
157 ///     /// The most verbose level that this subscriber will enable.
158 ///     max_level: LevelFilter,
159 ///
160 ///     // ...
161 /// }
162 ///
163 /// impl MySubscriber {
164 ///     /// Returns a new `MySubscriber` which will record spans and events up to
165 ///     /// `max_level`.
166 ///     pub fn with_max_level(max_level: LevelFilter) -> Self {
167 ///         Self {
168 ///             max_level,
169 ///             // ...
170 ///         }
171 ///     }
172 /// }
173 /// impl Subscriber for MySubscriber {
174 ///     fn enabled(&self, meta: &Metadata<'_>) -> bool {
175 ///         // A span or event is enabled if it is at or below the configured
176 ///         // maximum level.
177 ///         meta.level() <= &self.max_level
178 ///     }
179 ///
180 ///     // This optional method returns the most verbose level that this
181 ///     // subscriber will enable. Although implementing this method is not
182 ///     // *required*, it permits additional optimizations when it is provided,
183 ///     // allowing spans and events above the max level to be skipped
184 ///     // more efficiently.
185 ///     fn max_level_hint(&self) -> Option<LevelFilter> {
186 ///         Some(self.max_level)
187 ///     }
188 ///
189 ///     // Implement the rest of the subscriber...
190 ///     fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
191 ///         // ...
192 ///         # drop(span); Id::from_u64(1)
193 ///     }
194 
195 ///     fn event(&self, event: &Event<'_>) {
196 ///         // ...
197 ///         # drop(event);
198 ///     }
199 ///
200 ///     // ...
201 ///     # fn enter(&self, _: &Id) {}
202 ///     # fn exit(&self, _: &Id) {}
203 ///     # fn record(&self, _: &Id, _: &Record<'_>) {}
204 ///     # fn record_follows_from(&self, _: &Id, _: &Id) {}
205 /// }
206 /// ```
207 ///
208 /// It is worth noting that the `tracing-subscriber` crate provides [additional
209 /// APIs][envfilter] for performing more sophisticated filtering, such as
210 /// enabling different levels based on which module or crate a span or event is
211 /// recorded in.
212 ///
213 /// [`DEBUG`]: Level::DEBUG
214 /// [`INFO`]: Level::INFO
215 /// [`TRACE`]: Level::TRACE
216 /// [`Subscriber::enabled`]: crate::subscriber::Subscriber::enabled
217 /// [`Subscriber::max_level_hint`]: crate::subscriber::Subscriber::max_level_hint
218 /// [`Subscriber`]: crate::subscriber::Subscriber
219 /// [envfilter]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html
220 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
221 pub struct Level(LevelInner);
222 
223 /// A filter comparable to a verbosity [`Level`].
224 ///
225 /// If a [`Level`] is considered less than or equal to a `LevelFilter`, it
226 /// should be considered enabled; if greater than the `LevelFilter`, that level
227 /// is disabled. See [`LevelFilter::current`] for more details.
228 ///
229 /// Note that this is essentially identical to the `Level` type, but with the
230 /// addition of an [`OFF`] level that completely disables all trace
231 /// instrumentation.
232 ///
233 /// See the documentation for the [`Level`] type to see how `Level`s
234 /// and `LevelFilter`s interact.
235 ///
236 /// [`OFF`]: LevelFilter::OFF
237 #[repr(transparent)]
238 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
239 pub struct LevelFilter(Option<Level>);
240 
241 /// Indicates that a string could not be parsed to a valid level.
242 #[derive(Clone, Debug)]
243 pub struct ParseLevelFilterError(());
244 
245 static MAX_LEVEL: AtomicUsize = AtomicUsize::new(LevelFilter::OFF_USIZE);
246 
247 // ===== impl Metadata =====
248 
249 impl<'a> Metadata<'a> {
250     /// Construct new metadata for a span or event, with a name, target, level, field
251     /// names, and optional source code location.
new( name: &'static str, target: &'a str, level: Level, file: Option<&'a str>, line: Option<u32>, module_path: Option<&'a str>, fields: field::FieldSet, kind: Kind, ) -> Self252     pub const fn new(
253         name: &'static str,
254         target: &'a str,
255         level: Level,
256         file: Option<&'a str>,
257         line: Option<u32>,
258         module_path: Option<&'a str>,
259         fields: field::FieldSet,
260         kind: Kind,
261     ) -> Self {
262         Metadata {
263             name,
264             target,
265             level,
266             module_path,
267             file,
268             line,
269             fields,
270             kind,
271         }
272     }
273 
274     /// Returns the names of the fields on the described span or event.
275     #[inline]
fields(&self) -> &field::FieldSet276     pub fn fields(&self) -> &field::FieldSet {
277         &self.fields
278     }
279 
280     /// Returns the level of verbosity of the described span or event.
level(&self) -> &Level281     pub fn level(&self) -> &Level {
282         &self.level
283     }
284 
285     /// Returns the name of the span.
name(&self) -> &'static str286     pub fn name(&self) -> &'static str {
287         self.name
288     }
289 
290     /// Returns a string describing the part of the system where the span or
291     /// event that this metadata describes occurred.
292     ///
293     /// Typically, this is the module path, but alternate targets may be set
294     /// when spans or events are constructed.
target(&self) -> &'a str295     pub fn target(&self) -> &'a str {
296         self.target
297     }
298 
299     /// Returns the path to the Rust module where the span occurred, or
300     /// `None` if the module path is unknown.
module_path(&self) -> Option<&'a str>301     pub fn module_path(&self) -> Option<&'a str> {
302         self.module_path
303     }
304 
305     /// Returns the name of the source code file where the span
306     /// occurred, or `None` if the file is unknown
file(&self) -> Option<&'a str>307     pub fn file(&self) -> Option<&'a str> {
308         self.file
309     }
310 
311     /// Returns the line number in the source code file where the span
312     /// occurred, or `None` if the line number is unknown.
line(&self) -> Option<u32>313     pub fn line(&self) -> Option<u32> {
314         self.line
315     }
316 
317     /// Returns an opaque `Identifier` that uniquely identifies the callsite
318     /// this `Metadata` originated from.
319     #[inline]
callsite(&self) -> callsite::Identifier320     pub fn callsite(&self) -> callsite::Identifier {
321         self.fields.callsite()
322     }
323 
324     /// Returns true if the callsite kind is `Event`.
is_event(&self) -> bool325     pub fn is_event(&self) -> bool {
326         self.kind.is_event()
327     }
328 
329     /// Return true if the callsite kind is `Span`.
is_span(&self) -> bool330     pub fn is_span(&self) -> bool {
331         self.kind.is_span()
332     }
333 }
334 
335 impl<'a> fmt::Debug for Metadata<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result336     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337         let mut meta = f.debug_struct("Metadata");
338         meta.field("name", &self.name)
339             .field("target", &self.target)
340             .field("level", &self.level);
341 
342         if let Some(path) = self.module_path() {
343             meta.field("module_path", &path);
344         }
345 
346         match (self.file(), self.line()) {
347             (Some(file), Some(line)) => {
348                 meta.field("location", &format_args!("{}:{}", file, line));
349             }
350             (Some(file), None) => {
351                 meta.field("file", &format_args!("{}", file));
352             }
353 
354             // Note: a line num with no file is a kind of weird case that _probably_ never occurs...
355             (None, Some(line)) => {
356                 meta.field("line", &line);
357             }
358             (None, None) => {}
359         };
360 
361         meta.field("fields", &format_args!("{}", self.fields))
362             .field("callsite", &self.callsite())
363             .field("kind", &self.kind)
364             .finish()
365     }
366 }
367 
368 impl Kind {
369     const EVENT_BIT: u8 = 1 << 0;
370     const SPAN_BIT: u8 = 1 << 1;
371     const HINT_BIT: u8 = 1 << 2;
372 
373     /// `Event` callsite
374     pub const EVENT: Kind = Kind(Self::EVENT_BIT);
375 
376     /// `Span` callsite
377     pub const SPAN: Kind = Kind(Self::SPAN_BIT);
378 
379     /// `enabled!` callsite. [`Subscriber`][`crate::subscriber::Subscriber`]s can assume
380     /// this `Kind` means they will never receive a
381     /// full event with this [`Metadata`].
382     pub const HINT: Kind = Kind(Self::HINT_BIT);
383 
384     /// Return true if the callsite kind is `Span`
is_span(&self) -> bool385     pub fn is_span(&self) -> bool {
386         self.0 & Self::SPAN_BIT == Self::SPAN_BIT
387     }
388 
389     /// Return true if the callsite kind is `Event`
is_event(&self) -> bool390     pub fn is_event(&self) -> bool {
391         self.0 & Self::EVENT_BIT == Self::EVENT_BIT
392     }
393 
394     /// Return true if the callsite kind is `Hint`
is_hint(&self) -> bool395     pub fn is_hint(&self) -> bool {
396         self.0 & Self::HINT_BIT == Self::HINT_BIT
397     }
398 
399     /// Sets that this `Kind` is a [hint](Self::HINT).
400     ///
401     /// This can be called on [`SPAN`](Self::SPAN) and [`EVENT`](Self::EVENT)
402     /// kinds to construct a hint callsite that also counts as a span or event.
hint(self) -> Self403     pub const fn hint(self) -> Self {
404         Self(self.0 | Self::HINT_BIT)
405     }
406 }
407 
408 impl fmt::Debug for Kind {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result409     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410         f.write_str("Kind(")?;
411         let mut has_bits = false;
412         let mut write_bit = |name: &str| {
413             if has_bits {
414                 f.write_str(" | ")?;
415             }
416             f.write_str(name)?;
417             has_bits = true;
418             Ok(())
419         };
420 
421         if self.is_event() {
422             write_bit("EVENT")?;
423         }
424 
425         if self.is_span() {
426             write_bit("SPAN")?;
427         }
428 
429         if self.is_hint() {
430             write_bit("HINT")?;
431         }
432 
433         // if none of the expected bits were set, something is messed up, so
434         // just print the bits for debugging purposes
435         if !has_bits {
436             write!(f, "{:#b}", self.0)?;
437         }
438 
439         f.write_str(")")
440     }
441 }
442 
443 impl<'a> Eq for Metadata<'a> {}
444 
445 impl<'a> PartialEq for Metadata<'a> {
446     #[inline]
eq(&self, other: &Self) -> bool447     fn eq(&self, other: &Self) -> bool {
448         if core::ptr::eq(&self, &other) {
449             true
450         } else if cfg!(not(debug_assertions)) {
451             // In a well-behaving application, two `Metadata` can be assumed to
452             // be totally equal so long as they share the same callsite.
453             self.callsite() == other.callsite()
454         } else {
455             // However, when debug-assertions are enabled, do not assume that
456             // the application is well-behaving; check every field of `Metadata`
457             // for equality.
458 
459             // `Metadata` is destructured here to ensure a compile-error if the
460             // fields of `Metadata` change.
461             let Metadata {
462                 name: lhs_name,
463                 target: lhs_target,
464                 level: lhs_level,
465                 module_path: lhs_module_path,
466                 file: lhs_file,
467                 line: lhs_line,
468                 fields: lhs_fields,
469                 kind: lhs_kind,
470             } = self;
471 
472             let Metadata {
473                 name: rhs_name,
474                 target: rhs_target,
475                 level: rhs_level,
476                 module_path: rhs_module_path,
477                 file: rhs_file,
478                 line: rhs_line,
479                 fields: rhs_fields,
480                 kind: rhs_kind,
481             } = &other;
482 
483             // The initial comparison of callsites is purely an optimization;
484             // it can be removed without affecting the overall semantics of the
485             // expression.
486             self.callsite() == other.callsite()
487                 && lhs_name == rhs_name
488                 && lhs_target == rhs_target
489                 && lhs_level == rhs_level
490                 && lhs_module_path == rhs_module_path
491                 && lhs_file == rhs_file
492                 && lhs_line == rhs_line
493                 && lhs_fields == rhs_fields
494                 && lhs_kind == rhs_kind
495         }
496     }
497 }
498 
499 // ===== impl Level =====
500 
501 impl Level {
502     /// The "error" level.
503     ///
504     /// Designates very serious errors.
505     pub const ERROR: Level = Level(LevelInner::Error);
506     /// The "warn" level.
507     ///
508     /// Designates hazardous situations.
509     pub const WARN: Level = Level(LevelInner::Warn);
510     /// The "info" level.
511     ///
512     /// Designates useful information.
513     pub const INFO: Level = Level(LevelInner::Info);
514     /// The "debug" level.
515     ///
516     /// Designates lower priority information.
517     pub const DEBUG: Level = Level(LevelInner::Debug);
518     /// The "trace" level.
519     ///
520     /// Designates very low priority, often extremely verbose, information.
521     pub const TRACE: Level = Level(LevelInner::Trace);
522 
523     /// Returns the string representation of the `Level`.
524     ///
525     /// This returns the same string as the `fmt::Display` implementation.
as_str(&self) -> &'static str526     pub fn as_str(&self) -> &'static str {
527         match *self {
528             Level::TRACE => "TRACE",
529             Level::DEBUG => "DEBUG",
530             Level::INFO => "INFO",
531             Level::WARN => "WARN",
532             Level::ERROR => "ERROR",
533         }
534     }
535 }
536 
537 impl fmt::Display for Level {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result538     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539         match *self {
540             Level::TRACE => f.pad("TRACE"),
541             Level::DEBUG => f.pad("DEBUG"),
542             Level::INFO => f.pad("INFO"),
543             Level::WARN => f.pad("WARN"),
544             Level::ERROR => f.pad("ERROR"),
545         }
546     }
547 }
548 
549 #[cfg(feature = "std")]
550 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
551 impl crate::stdlib::error::Error for ParseLevelError {}
552 
553 impl FromStr for Level {
554     type Err = ParseLevelError;
from_str(s: &str) -> Result<Self, ParseLevelError>555     fn from_str(s: &str) -> Result<Self, ParseLevelError> {
556         s.parse::<usize>()
557             .map_err(|_| ParseLevelError { _p: () })
558             .and_then(|num| match num {
559                 1 => Ok(Level::ERROR),
560                 2 => Ok(Level::WARN),
561                 3 => Ok(Level::INFO),
562                 4 => Ok(Level::DEBUG),
563                 5 => Ok(Level::TRACE),
564                 _ => Err(ParseLevelError { _p: () }),
565             })
566             .or_else(|_| match s {
567                 s if s.eq_ignore_ascii_case("error") => Ok(Level::ERROR),
568                 s if s.eq_ignore_ascii_case("warn") => Ok(Level::WARN),
569                 s if s.eq_ignore_ascii_case("info") => Ok(Level::INFO),
570                 s if s.eq_ignore_ascii_case("debug") => Ok(Level::DEBUG),
571                 s if s.eq_ignore_ascii_case("trace") => Ok(Level::TRACE),
572                 _ => Err(ParseLevelError { _p: () }),
573             })
574     }
575 }
576 
577 #[repr(usize)]
578 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
579 enum LevelInner {
580     /// The "trace" level.
581     ///
582     /// Designates very low priority, often extremely verbose, information.
583     Trace = 0,
584     /// The "debug" level.
585     ///
586     /// Designates lower priority information.
587     Debug = 1,
588     /// The "info" level.
589     ///
590     /// Designates useful information.
591     Info = 2,
592     /// The "warn" level.
593     ///
594     /// Designates hazardous situations.
595     Warn = 3,
596     /// The "error" level.
597     ///
598     /// Designates very serious errors.
599     Error = 4,
600 }
601 
602 // === impl LevelFilter ===
603 
604 impl From<Level> for LevelFilter {
605     #[inline]
from(level: Level) -> Self606     fn from(level: Level) -> Self {
607         Self::from_level(level)
608     }
609 }
610 
611 impl From<Option<Level>> for LevelFilter {
612     #[inline]
from(level: Option<Level>) -> Self613     fn from(level: Option<Level>) -> Self {
614         Self(level)
615     }
616 }
617 
618 impl From<LevelFilter> for Option<Level> {
619     #[inline]
from(filter: LevelFilter) -> Self620     fn from(filter: LevelFilter) -> Self {
621         filter.into_level()
622     }
623 }
624 
625 impl LevelFilter {
626     /// The "off" level.
627     ///
628     /// Designates that trace instrumentation should be completely disabled.
629     pub const OFF: LevelFilter = LevelFilter(None);
630     /// The "error" level.
631     ///
632     /// Designates very serious errors.
633     pub const ERROR: LevelFilter = LevelFilter::from_level(Level::ERROR);
634     /// The "warn" level.
635     ///
636     /// Designates hazardous situations.
637     pub const WARN: LevelFilter = LevelFilter::from_level(Level::WARN);
638     /// The "info" level.
639     ///
640     /// Designates useful information.
641     pub const INFO: LevelFilter = LevelFilter::from_level(Level::INFO);
642     /// The "debug" level.
643     ///
644     /// Designates lower priority information.
645     pub const DEBUG: LevelFilter = LevelFilter::from_level(Level::DEBUG);
646     /// The "trace" level.
647     ///
648     /// Designates very low priority, often extremely verbose, information.
649     pub const TRACE: LevelFilter = LevelFilter(Some(Level::TRACE));
650 
651     /// Returns a `LevelFilter` that enables spans and events with verbosity up
652     /// to and including `level`.
from_level(level: Level) -> Self653     pub const fn from_level(level: Level) -> Self {
654         Self(Some(level))
655     }
656 
657     /// Returns the most verbose [`Level`] that this filter accepts, or `None`
658     /// if it is [`OFF`].
659     ///
660     /// [`OFF`]: LevelFilter::OFF
into_level(self) -> Option<Level>661     pub const fn into_level(self) -> Option<Level> {
662         self.0
663     }
664 
665     // These consts are necessary because `as` casts are not allowed as
666     // match patterns.
667     const ERROR_USIZE: usize = LevelInner::Error as usize;
668     const WARN_USIZE: usize = LevelInner::Warn as usize;
669     const INFO_USIZE: usize = LevelInner::Info as usize;
670     const DEBUG_USIZE: usize = LevelInner::Debug as usize;
671     const TRACE_USIZE: usize = LevelInner::Trace as usize;
672     // Using the value of the last variant + 1 ensures that we match the value
673     // for `Option::None` as selected by the niche optimization for
674     // `LevelFilter`. If this is the case, converting a `usize` value into a
675     // `LevelFilter` (in `LevelFilter::current`) will be an identity conversion,
676     // rather than generating a lookup table.
677     const OFF_USIZE: usize = LevelInner::Error as usize + 1;
678 
679     /// Returns a `LevelFilter` that matches the most verbose [`Level`] that any
680     /// currently active [`Subscriber`] will enable.
681     ///
682     /// User code should treat this as a *hint*. If a given span or event has a
683     /// level *higher* than the returned `LevelFilter`, it will not be enabled.
684     /// However, if the level is less than or equal to this value, the span or
685     /// event is *not* guaranteed to be enabled; the subscriber will still
686     /// filter each callsite individually.
687     ///
688     /// Therefore, comparing a given span or event's level to the returned
689     /// `LevelFilter` **can** be used for determining if something is
690     /// *disabled*, but **should not** be used for determining if something is
691     /// *enabled*.
692     ///
693     /// [`Level`]: super::Level
694     /// [`Subscriber`]: super::Subscriber
695     #[inline(always)]
current() -> Self696     pub fn current() -> Self {
697         match MAX_LEVEL.load(Ordering::Relaxed) {
698             Self::ERROR_USIZE => Self::ERROR,
699             Self::WARN_USIZE => Self::WARN,
700             Self::INFO_USIZE => Self::INFO,
701             Self::DEBUG_USIZE => Self::DEBUG,
702             Self::TRACE_USIZE => Self::TRACE,
703             Self::OFF_USIZE => Self::OFF,
704             #[cfg(debug_assertions)]
705             unknown => unreachable!(
706                 "/!\\ `LevelFilter` representation seems to have changed! /!\\ \n\
707                 This is a bug (and it's pretty bad). Please contact the `tracing` \
708                 maintainers. Thank you and I'm sorry.\n \
709                 The offending repr was: {:?}",
710                 unknown,
711             ),
712             #[cfg(not(debug_assertions))]
713             _ => unsafe {
714                 // Using `unreachable_unchecked` here (rather than
715                 // `unreachable!()`) is necessary to ensure that rustc generates
716                 // an identity conversion from integer -> discriminant, rather
717                 // than generating a lookup table. We want to ensure this
718                 // function is a single `mov` instruction (on x86) if at all
719                 // possible, because it is called *every* time a span/event
720                 // callsite is hit; and it is (potentially) the only code in the
721                 // hottest path for skipping a majority of callsites when level
722                 // filtering is in use.
723                 //
724                 // safety: This branch is only truly unreachable if we guarantee
725                 // that no values other than the possible enum discriminants
726                 // will *ever* be present. The `AtomicUsize` is initialized to
727                 // the `OFF` value. It is only set by the `set_max` function,
728                 // which takes a `LevelFilter` as a parameter. This restricts
729                 // the inputs to `set_max` to the set of valid discriminants.
730                 // Therefore, **as long as `MAX_VALUE` is only ever set by
731                 // `set_max`**, this is safe.
732                 crate::stdlib::hint::unreachable_unchecked()
733             },
734         }
735     }
736 
set_max(LevelFilter(level): LevelFilter)737     pub(crate) fn set_max(LevelFilter(level): LevelFilter) {
738         let val = match level {
739             Some(Level(level)) => level as usize,
740             None => Self::OFF_USIZE,
741         };
742 
743         // using an AcqRel swap ensures an ordered relationship of writes to the
744         // max level.
745         MAX_LEVEL.swap(val, Ordering::AcqRel);
746     }
747 }
748 
749 impl fmt::Display for LevelFilter {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result750     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
751         match *self {
752             LevelFilter::OFF => f.pad("off"),
753             LevelFilter::ERROR => f.pad("error"),
754             LevelFilter::WARN => f.pad("warn"),
755             LevelFilter::INFO => f.pad("info"),
756             LevelFilter::DEBUG => f.pad("debug"),
757             LevelFilter::TRACE => f.pad("trace"),
758         }
759     }
760 }
761 
762 impl fmt::Debug for LevelFilter {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result763     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764         match *self {
765             LevelFilter::OFF => f.pad("LevelFilter::OFF"),
766             LevelFilter::ERROR => f.pad("LevelFilter::ERROR"),
767             LevelFilter::WARN => f.pad("LevelFilter::WARN"),
768             LevelFilter::INFO => f.pad("LevelFilter::INFO"),
769             LevelFilter::DEBUG => f.pad("LevelFilter::DEBUG"),
770             LevelFilter::TRACE => f.pad("LevelFilter::TRACE"),
771         }
772     }
773 }
774 
775 impl FromStr for LevelFilter {
776     type Err = ParseLevelFilterError;
from_str(from: &str) -> Result<Self, Self::Err>777     fn from_str(from: &str) -> Result<Self, Self::Err> {
778         from.parse::<usize>()
779             .ok()
780             .and_then(|num| match num {
781                 0 => Some(LevelFilter::OFF),
782                 1 => Some(LevelFilter::ERROR),
783                 2 => Some(LevelFilter::WARN),
784                 3 => Some(LevelFilter::INFO),
785                 4 => Some(LevelFilter::DEBUG),
786                 5 => Some(LevelFilter::TRACE),
787                 _ => None,
788             })
789             .or_else(|| match from {
790                 "" => Some(LevelFilter::ERROR),
791                 s if s.eq_ignore_ascii_case("error") => Some(LevelFilter::ERROR),
792                 s if s.eq_ignore_ascii_case("warn") => Some(LevelFilter::WARN),
793                 s if s.eq_ignore_ascii_case("info") => Some(LevelFilter::INFO),
794                 s if s.eq_ignore_ascii_case("debug") => Some(LevelFilter::DEBUG),
795                 s if s.eq_ignore_ascii_case("trace") => Some(LevelFilter::TRACE),
796                 s if s.eq_ignore_ascii_case("off") => Some(LevelFilter::OFF),
797                 _ => None,
798             })
799             .ok_or(ParseLevelFilterError(()))
800     }
801 }
802 
803 /// Returned if parsing a `Level` fails.
804 #[derive(Debug)]
805 pub struct ParseLevelError {
806     _p: (),
807 }
808 
809 impl fmt::Display for ParseLevelError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result810     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
811         f.pad(
812             "error parsing level: expected one of \"error\", \"warn\", \
813              \"info\", \"debug\", \"trace\", or a number 1-5",
814         )
815     }
816 }
817 
818 impl fmt::Display for ParseLevelFilterError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result819     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
820         f.pad(
821             "error parsing level filter: expected one of \"off\", \"error\", \
822             \"warn\", \"info\", \"debug\", \"trace\", or a number 0-5",
823         )
824     }
825 }
826 
827 #[cfg(feature = "std")]
828 impl std::error::Error for ParseLevelFilterError {}
829 
830 // ==== Level and LevelFilter comparisons ====
831 
832 // /!\ BIG, IMPORTANT WARNING /!\
833 // Do NOT mess with these implementations! They are hand-written for a reason!
834 //
835 // Since comparing `Level`s and `LevelFilter`s happens in a *very* hot path
836 // (potentially, every time a span or event macro is hit, regardless of whether
837 // or not is enabled), we *need* to ensure that these comparisons are as fast as
838 // possible. Therefore, we have some requirements:
839 //
840 // 1. We want to do our best to ensure that rustc will generate integer-integer
841 //    comparisons wherever possible.
842 //
843 //    The derived `Ord`/`PartialOrd` impls for `LevelFilter` will not do this,
844 //    because `LevelFilter`s are represented by `Option<Level>`, rather than as
845 //    a separate `#[repr(usize)]` enum. This was (unfortunately) necessary for
846 //    backwards-compatibility reasons, as the  `tracing` crate's original
847 //    version of `LevelFilter` defined `const fn` conversions between `Level`s
848 //    and `LevelFilter`, so we're stuck with the `Option<Level>` repr.
849 //    Therefore, we need hand-written `PartialOrd` impls that cast both sides of
850 //    the comparison to `usize`s, to force the compiler to generate integer
851 //    compares.
852 //
853 // 2. The hottest `Level`/`LevelFilter` comparison, the one that happens every
854 //    time a callsite is hit, occurs *within the `tracing` crate's macros*.
855 //    This means that the comparison is happening *inside* a crate that
856 //    *depends* on `tracing-core`, not in `tracing-core` itself. The compiler
857 //    will only inline function calls across crate boundaries if the called
858 //    function is annotated with an `#[inline]` attribute, and we *definitely*
859 //    want the comparison functions to be inlined: as previously mentioned, they
860 //    should compile down to a single integer comparison on release builds, and
861 //    it seems really sad to push an entire stack frame to call a function
862 //    consisting of one `cmp` instruction!
863 //
864 //    Therefore, we need to ensure that all the comparison methods have
865 //    `#[inline]` or `#[inline(always)]` attributes. It's not sufficient to just
866 //    add the attribute to `partial_cmp` in a manual implementation of the
867 //    trait, since it's the comparison operators (`lt`, `le`, `gt`, and `ge`)
868 //    that will actually be *used*, and the default implementation of *those*
869 //    methods, which calls `partial_cmp`, does not have an inline annotation.
870 //
871 // 3. We need the comparisons to be inverted. The discriminants for the
872 //    `LevelInner` enum are assigned in "backwards" order, with `TRACE` having
873 //    the *lowest* value. However, we want `TRACE` to compare greater-than all
874 //    other levels.
875 //
876 //    Why are the numeric values inverted? In order to ensure that `LevelFilter`
877 //    (which, as previously mentioned, *has* to be internally represented by an
878 //    `Option<Level>`) compiles down to a single integer value. This is
879 //    necessary for storing the global max in an `AtomicUsize`, and for ensuring
880 //    that we use fast integer-integer comparisons, as mentioned previously. In
881 //    order to ensure this, we exploit the niche optimization. The niche
882 //    optimization for `Option<{enum with a numeric repr}>` will choose
883 //    `(HIGHEST_DISCRIMINANT_VALUE + 1)` as the representation for `None`.
884 //    Therefore, the integer representation of `LevelFilter::OFF` (which is
885 //    `None`) will be the number 5. `OFF` must compare higher than every other
886 //    level in order for it to filter as expected. Since we want to use a single
887 //    `cmp` instruction, we can't special-case the integer value of `OFF` to
888 //    compare higher, as that will generate more code. Instead, we need it to be
889 //    on one end of the enum, with `ERROR` on the opposite end, so we assign the
890 //    value 0 to `ERROR`.
891 //
892 //    This *does* mean that when parsing `LevelFilter`s or `Level`s from
893 //    `String`s, the integer values are inverted, but that doesn't happen in a
894 //    hot path.
895 //
896 //    Note that we manually invert the comparisons by swapping the left-hand and
897 //    right-hand side. Using `Ordering::reverse` generates significantly worse
898 //    code (per Matt Godbolt's Compiler Explorer).
899 //
900 // Anyway, that's a brief history of why this code is the way it is. Don't
901 // change it unless you know what you're doing.
902 
903 impl PartialEq<LevelFilter> for Level {
904     #[inline(always)]
eq(&self, other: &LevelFilter) -> bool905     fn eq(&self, other: &LevelFilter) -> bool {
906         self.0 as usize == filter_as_usize(&other.0)
907     }
908 }
909 
910 impl PartialOrd for Level {
911     #[inline(always)]
partial_cmp(&self, other: &Level) -> Option<cmp::Ordering>912     fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
913         Some(self.cmp(other))
914     }
915 
916     #[inline(always)]
lt(&self, other: &Level) -> bool917     fn lt(&self, other: &Level) -> bool {
918         (other.0 as usize) < (self.0 as usize)
919     }
920 
921     #[inline(always)]
le(&self, other: &Level) -> bool922     fn le(&self, other: &Level) -> bool {
923         (other.0 as usize) <= (self.0 as usize)
924     }
925 
926     #[inline(always)]
gt(&self, other: &Level) -> bool927     fn gt(&self, other: &Level) -> bool {
928         (other.0 as usize) > (self.0 as usize)
929     }
930 
931     #[inline(always)]
ge(&self, other: &Level) -> bool932     fn ge(&self, other: &Level) -> bool {
933         (other.0 as usize) >= (self.0 as usize)
934     }
935 }
936 
937 impl Ord for Level {
938     #[inline(always)]
cmp(&self, other: &Self) -> cmp::Ordering939     fn cmp(&self, other: &Self) -> cmp::Ordering {
940         (other.0 as usize).cmp(&(self.0 as usize))
941     }
942 }
943 
944 impl PartialOrd<LevelFilter> for Level {
945     #[inline(always)]
partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering>946     fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
947         Some(filter_as_usize(&other.0).cmp(&(self.0 as usize)))
948     }
949 
950     #[inline(always)]
lt(&self, other: &LevelFilter) -> bool951     fn lt(&self, other: &LevelFilter) -> bool {
952         filter_as_usize(&other.0) < (self.0 as usize)
953     }
954 
955     #[inline(always)]
le(&self, other: &LevelFilter) -> bool956     fn le(&self, other: &LevelFilter) -> bool {
957         filter_as_usize(&other.0) <= (self.0 as usize)
958     }
959 
960     #[inline(always)]
gt(&self, other: &LevelFilter) -> bool961     fn gt(&self, other: &LevelFilter) -> bool {
962         filter_as_usize(&other.0) > (self.0 as usize)
963     }
964 
965     #[inline(always)]
ge(&self, other: &LevelFilter) -> bool966     fn ge(&self, other: &LevelFilter) -> bool {
967         filter_as_usize(&other.0) >= (self.0 as usize)
968     }
969 }
970 
971 #[inline(always)]
filter_as_usize(x: &Option<Level>) -> usize972 fn filter_as_usize(x: &Option<Level>) -> usize {
973     match x {
974         Some(Level(f)) => *f as usize,
975         None => LevelFilter::OFF_USIZE,
976     }
977 }
978 
979 impl PartialEq<Level> for LevelFilter {
980     #[inline(always)]
eq(&self, other: &Level) -> bool981     fn eq(&self, other: &Level) -> bool {
982         filter_as_usize(&self.0) == other.0 as usize
983     }
984 }
985 
986 impl PartialOrd for LevelFilter {
987     #[inline(always)]
partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering>988     fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
989         Some(self.cmp(other))
990     }
991 
992     #[inline(always)]
lt(&self, other: &LevelFilter) -> bool993     fn lt(&self, other: &LevelFilter) -> bool {
994         filter_as_usize(&other.0) < filter_as_usize(&self.0)
995     }
996 
997     #[inline(always)]
le(&self, other: &LevelFilter) -> bool998     fn le(&self, other: &LevelFilter) -> bool {
999         filter_as_usize(&other.0) <= filter_as_usize(&self.0)
1000     }
1001 
1002     #[inline(always)]
gt(&self, other: &LevelFilter) -> bool1003     fn gt(&self, other: &LevelFilter) -> bool {
1004         filter_as_usize(&other.0) > filter_as_usize(&self.0)
1005     }
1006 
1007     #[inline(always)]
ge(&self, other: &LevelFilter) -> bool1008     fn ge(&self, other: &LevelFilter) -> bool {
1009         filter_as_usize(&other.0) >= filter_as_usize(&self.0)
1010     }
1011 }
1012 
1013 impl Ord for LevelFilter {
1014     #[inline(always)]
cmp(&self, other: &Self) -> cmp::Ordering1015     fn cmp(&self, other: &Self) -> cmp::Ordering {
1016         filter_as_usize(&other.0).cmp(&filter_as_usize(&self.0))
1017     }
1018 }
1019 
1020 impl PartialOrd<Level> for LevelFilter {
1021     #[inline(always)]
partial_cmp(&self, other: &Level) -> Option<cmp::Ordering>1022     fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
1023         Some((other.0 as usize).cmp(&filter_as_usize(&self.0)))
1024     }
1025 
1026     #[inline(always)]
lt(&self, other: &Level) -> bool1027     fn lt(&self, other: &Level) -> bool {
1028         (other.0 as usize) < filter_as_usize(&self.0)
1029     }
1030 
1031     #[inline(always)]
le(&self, other: &Level) -> bool1032     fn le(&self, other: &Level) -> bool {
1033         (other.0 as usize) <= filter_as_usize(&self.0)
1034     }
1035 
1036     #[inline(always)]
gt(&self, other: &Level) -> bool1037     fn gt(&self, other: &Level) -> bool {
1038         (other.0 as usize) > filter_as_usize(&self.0)
1039     }
1040 
1041     #[inline(always)]
ge(&self, other: &Level) -> bool1042     fn ge(&self, other: &Level) -> bool {
1043         (other.0 as usize) >= filter_as_usize(&self.0)
1044     }
1045 }
1046 
1047 #[cfg(test)]
1048 mod tests {
1049     use super::*;
1050     use crate::stdlib::mem;
1051 
1052     #[test]
level_from_str()1053     fn level_from_str() {
1054         assert_eq!("error".parse::<Level>().unwrap(), Level::ERROR);
1055         assert_eq!("4".parse::<Level>().unwrap(), Level::DEBUG);
1056         assert!("0".parse::<Level>().is_err())
1057     }
1058 
1059     #[test]
filter_level_conversion()1060     fn filter_level_conversion() {
1061         let mapping = [
1062             (LevelFilter::OFF, None),
1063             (LevelFilter::ERROR, Some(Level::ERROR)),
1064             (LevelFilter::WARN, Some(Level::WARN)),
1065             (LevelFilter::INFO, Some(Level::INFO)),
1066             (LevelFilter::DEBUG, Some(Level::DEBUG)),
1067             (LevelFilter::TRACE, Some(Level::TRACE)),
1068         ];
1069         for (filter, level) in mapping.iter() {
1070             assert_eq!(filter.into_level(), *level);
1071             match level {
1072                 Some(level) => {
1073                     let actual: LevelFilter = (*level).into();
1074                     assert_eq!(actual, *filter);
1075                 }
1076                 None => {
1077                     let actual: LevelFilter = None.into();
1078                     assert_eq!(actual, *filter);
1079                 }
1080             }
1081         }
1082     }
1083 
1084     #[test]
level_filter_is_usize_sized()1085     fn level_filter_is_usize_sized() {
1086         assert_eq!(
1087             mem::size_of::<LevelFilter>(),
1088             mem::size_of::<usize>(),
1089             "`LevelFilter` is no longer `usize`-sized! global MAX_LEVEL may now be invalid!"
1090         )
1091     }
1092 
1093     #[test]
level_filter_reprs()1094     fn level_filter_reprs() {
1095         let mapping = [
1096             (LevelFilter::OFF, LevelInner::Error as usize + 1),
1097             (LevelFilter::ERROR, LevelInner::Error as usize),
1098             (LevelFilter::WARN, LevelInner::Warn as usize),
1099             (LevelFilter::INFO, LevelInner::Info as usize),
1100             (LevelFilter::DEBUG, LevelInner::Debug as usize),
1101             (LevelFilter::TRACE, LevelInner::Trace as usize),
1102         ];
1103         for &(filter, expected) in &mapping {
1104             let repr = unsafe {
1105                 // safety: The entire purpose of this test is to assert that the
1106                 // actual repr matches what we expect it to be --- we're testing
1107                 // that *other* unsafe code is sound using the transmuted value.
1108                 // We're not going to do anything with it that might be unsound.
1109                 mem::transmute::<LevelFilter, usize>(filter)
1110             };
1111             assert_eq!(expected, repr, "repr changed for {:?}", filter)
1112         }
1113     }
1114 }
1115