tokio_trace_core/
metadata.rs

1//! Metadata describing trace data.
2use super::{
3    callsite::{self, Callsite},
4    field,
5};
6use std::fmt;
7
8/// Metadata describing a [span] or [event].
9///
10/// This includes the source code location where the span occurred, the names of
11/// its fields, et cetera.
12///
13/// Metadata is used by [`Subscriber`]s when filtering spans and events, and it
14/// may also be used as part of their data payload.
15///
16/// When created by the `event!` or `span!` macro, the metadata describing a
17/// particular event or span is constructed statically and exists as a single
18/// static instance. Thus, the overhead of creating the metadata is
19/// _significantly_ lower than that of creating the actual span. Therefore,
20/// filtering is based on metadata, rather than  on the constructed span.
21///
22/// **Note**: Although instances of `Metadata` cannot be compared directly, they
23/// provide a method [`Metadata::id()`] which returns an an opaque [callsite
24/// identifier] which uniquely identifies the callsite where the metadata
25/// originated. This can be used for determining if two Metadata correspond to
26/// the same callsite.
27///
28/// [span]: ../span
29/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
30/// [`Metadata::id()`]: struct.Metadata.html#method.id
31/// [callsite identifier]: ../callsite/struct.Identifier.html
32// TODO: When `const fn` is stable, make this type's fields private.
33pub struct Metadata<'a> {
34    /// The name of the span described by this metadata.
35    ///
36    /// **Warning**: The fields on this type are currently `pub` because it must
37    /// be able to be constructed statically by macros. However, when `const
38    /// fn`s are available on stable Rust, this will no longer be necessary.
39    /// Thus, these fields are *not* considered stable public API, and they may
40    /// change warning. Do not rely on any fields on `Metadata`. When
41    /// constructing new `Metadata`, use the `metadata!` macro or the
42    /// `Metadata::new` constructor instead!
43    #[doc(hidden)]
44    pub name: &'static str,
45
46    /// The part of the system that the span that this metadata describes
47    /// occurred in.
48    ///
49    /// Typically, this is the module path, but alternate targets may be set
50    /// when spans or events are constructed.
51    ///
52    /// **Warning**: The fields on this type are currently `pub` because it must
53    /// be able to be constructed statically by macros. However, when `const
54    /// fn`s are available on stable Rust, this will no longer be necessary.
55    /// Thus, these fields are *not* considered stable public API, and they may
56    /// change warning. Do not rely on any fields on `Metadata`. When
57    /// constructing new `Metadata`, use the `metadata!` macro or the
58    /// `Metadata::new` constructor instead!
59    #[doc(hidden)]
60    pub target: &'a str,
61
62    /// The level of verbosity of the described span.
63    ///
64    /// **Warning**: The fields on this type are currently `pub` because it must
65    /// be able to be constructed statically by macros. However, when `const
66    /// fn`s are available on stable Rust, this will no longer be necessary.
67    /// Thus, these fields are *not* considered stable public API, and they may
68    /// change warning. Do not rely on any fields on `Metadata`. When
69    /// constructing new `Metadata`, use the `metadata!` macro or the
70    /// `Metadata::new` constructor instead!
71    #[doc(hidden)]
72    pub level: Level,
73
74    /// The name of the Rust module where the span occurred, or `None` if this
75    /// could not be determined.
76    ///
77    /// **Warning**: The fields on this type are currently `pub` because it must
78    /// be able to be constructed statically by macros. However, when `const
79    /// fn`s are available on stable Rust, this will no longer be necessary.
80    /// Thus, these fields are *not* considered stable public API, and they may
81    /// change warning. Do not rely on any fields on `Metadata`. When
82    /// constructing new `Metadata`, use the `metadata!` macro or the
83    /// `Metadata::new` constructor instead!
84    #[doc(hidden)]
85    pub module_path: Option<&'a str>,
86
87    /// The name of the source code file where the span occurred, or `None` if
88    /// this could not be determined.
89    ///
90    /// **Warning**: The fields on this type are currently `pub` because it must
91    /// be able to be constructed statically by macros. However, when `const
92    /// fn`s are available on stable Rust, this will no longer be necessary.
93    /// Thus, these fields are *not* considered stable public API, and they may
94    /// change warning. Do not rely on any fields on `Metadata`. When
95    /// constructing new `Metadata`, use the `metadata!` macro or the
96    /// `Metadata::new` constructor instead!
97    #[doc(hidden)]
98    pub file: Option<&'a str>,
99
100    /// The line number in the source code file where the span occurred, or
101    /// `None` if this could not be determined.
102    ///
103    /// **Warning**: The fields on this type are currently `pub` because it must
104    /// be able to be constructed statically by macros. However, when `const
105    /// fn`s are available on stable Rust, this will no longer be necessary.
106    /// Thus, these fields are *not* considered stable public API, and they may
107    /// change warning. Do not rely on any fields on `Metadata`. When
108    /// constructing new `Metadata`, use the `metadata!` macro or the
109    /// `Metadata::new` constructor instead!
110    #[doc(hidden)]
111    pub line: Option<u32>,
112
113    /// The names of the key-value fields attached to the described span or
114    /// event.
115    ///
116    /// **Warning**: The fields on this type are currently `pub` because it must
117    /// be able to be constructed statically by macros. However, when `const
118    /// fn`s are available on stable Rust, this will no longer be necessary.
119    /// Thus, these fields are *not* considered stable public API, and they may
120    /// change warning. Do not rely on any fields on `Metadata`. When
121    /// constructing new `Metadata`, use the `metadata!` macro or the
122    /// `Metadata::new` constructor instead!
123    #[doc(hidden)]
124    pub fields: field::FieldSet,
125
126    /// The kind of the callsite.
127    ///
128    /// **Warning**: The fields on this type are currently `pub` because it must
129    /// be able to be constructed statically by macros. However, when `const
130    /// fn`s are available on stable Rust, this will no longer be necessary.
131    /// Thus, these fields are *not* considered stable public API, and they may
132    /// change warning. Do not rely on any fields on `Metadata`. When
133    /// constructing new `Metadata`, use the `metadata!` macro or the
134    /// `Metadata::new` constructor instead!
135    #[doc(hidden)]
136    pub kind: Kind,
137}
138
139/// Indicate whether the callsite is a span or event.
140#[derive(Clone, Debug, Eq, PartialEq)]
141pub struct Kind(KindInner);
142
143/// Describes the level of verbosity of a span or event.
144#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
145pub struct Level(LevelInner);
146
147// ===== impl Metadata =====
148
149impl<'a> Metadata<'a> {
150    /// Construct new metadata for a span, with a name, target, level, field
151    /// names, and optional source code location.
152    pub fn new(
153        name: &'static str,
154        target: &'a str,
155        level: Level,
156        module_path: Option<&'a str>,
157        file: Option<&'a str>,
158        line: Option<u32>,
159        field_names: &'static [&'static str],
160        callsite: &'static Callsite,
161        kind: Kind,
162    ) -> Self {
163        Metadata {
164            name,
165            target,
166            level,
167            module_path,
168            file,
169            line,
170            fields: field::FieldSet {
171                names: field_names,
172                callsite: callsite::Identifier(callsite),
173            },
174            kind,
175        }
176    }
177
178    /// Returns the set of fields on the described span.
179    pub fn fields(&self) -> &field::FieldSet {
180        &self.fields
181    }
182
183    /// Returns the level of verbosity of the described span.
184    pub fn level(&self) -> &Level {
185        &self.level
186    }
187
188    /// Returns the name of the span.
189    pub fn name(&self) -> &'static str {
190        self.name
191    }
192
193    /// Returns a string describing the part of the system where the span or
194    /// event that this metadata describes occurred.
195    ///
196    /// Typically, this is the module path, but alternate targets may be set
197    /// when spans or events are constructed.
198    pub fn target(&self) -> &'a str {
199        self.target
200    }
201
202    /// Returns the path to the Rust module where the span occurred, or
203    /// `None` if the module path is unknown.
204    pub fn module_path(&self) -> Option<&'a str> {
205        self.module_path
206    }
207
208    /// Returns the name of the source code file where the span
209    /// occurred, or `None` if the file is unknown
210    pub fn file(&self) -> Option<&'a str> {
211        self.file
212    }
213
214    /// Returns the line number in the source code file where the span
215    /// occurred, or `None` if the line number is unknown.
216    pub fn line(&self) -> Option<u32> {
217        self.line
218    }
219
220    /// Returns an opaque `Identifier` that uniquely identifies the callsite
221    /// this `Metadata` originated from.
222    #[inline]
223    pub fn callsite(&self) -> callsite::Identifier {
224        self.fields.callsite()
225    }
226
227    /// Returns true if the callsite kind is `Event`.
228    pub fn is_event(&self) -> bool {
229        self.kind.is_event()
230    }
231
232    /// Return true if the callsite kind is `Span`.
233    pub fn is_span(&self) -> bool {
234        self.kind.is_span()
235    }
236}
237
238impl<'a> fmt::Debug for Metadata<'a> {
239    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240        let mut meta = f.debug_struct("Metadata");
241        meta.field("name", &self.name)
242            .field("target", &self.target)
243            .field("level", &self.level);
244
245        if let Some(path) = self.module_path() {
246            meta.field("module_path", &path);
247        }
248
249        match (self.file(), self.line()) {
250            (Some(file), Some(line)) => {
251                meta.field("location", &format_args!("{}:{}", file, line));
252            }
253            (Some(file), None) => {
254                meta.field("file", &format_args!("{}", file));
255            }
256
257            // Note: a line num with no file is a kind of weird case that _probably_ never occurs...
258            (None, Some(line)) => {
259                meta.field("line", &line);
260            }
261            (None, None) => {}
262        };
263
264        meta.field("fields", &format_args!("{}", self.fields))
265            .field("callsite", &self.callsite())
266            .field("kind", &self.kind)
267            .finish()
268    }
269}
270
271#[derive(Clone, Debug, Eq, PartialEq)]
272enum KindInner {
273    Event,
274    Span,
275}
276
277impl Kind {
278    /// `Event` callsite
279    pub const EVENT: Kind = Kind(KindInner::Event);
280
281    /// `Span` callsite
282    pub const SPAN: Kind = Kind(KindInner::Span);
283
284    /// Return true if the callsite kind is `Span`
285    pub fn is_span(&self) -> bool {
286        match self {
287            Kind(KindInner::Span) => true,
288            _ => false,
289        }
290    }
291
292    /// Return true if the callsite kind is `Event`
293    pub fn is_event(&self) -> bool {
294        match self {
295            Kind(KindInner::Event) => true,
296            _ => false,
297        }
298    }
299}
300
301// ===== impl Level =====
302
303impl Level {
304    /// The "error" level.
305    ///
306    /// Designates very serious errors.
307    pub const ERROR: Level = Level(LevelInner::Error);
308    /// The "warn" level.
309    ///
310    /// Designates hazardous situations.
311    pub const WARN: Level = Level(LevelInner::Warn);
312    /// The "info" level.
313    ///
314    /// Designates useful information.
315    pub const INFO: Level = Level(LevelInner::Info);
316    /// The "debug" level.
317    ///
318    /// Designates lower priority information.
319    pub const DEBUG: Level = Level(LevelInner::Debug);
320    /// The "trace" level.
321    ///
322    /// Designates very low priority, often extremely verbose, information.
323    pub const TRACE: Level = Level(LevelInner::Trace);
324}
325
326#[repr(usize)]
327#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
328enum LevelInner {
329    /// The "error" level.
330    ///
331    /// Designates very serious errors.
332    Error = 1,
333    /// The "warn" level.
334    ///
335    /// Designates hazardous situations.
336    Warn,
337    /// The "info" level.
338    ///
339    /// Designates useful information.
340    Info,
341    /// The "debug" level.
342    ///
343    /// Designates lower priority information.
344    Debug,
345    /// The "trace" level.
346    ///
347    /// Designates very low priority, often extremely verbose, information.
348    Trace,
349}