]> git.proxmox.com Git - rustc.git/blame - vendor/tracing/src/lib.rs
New upstream version 1.62.1+dfsg1
[rustc.git] / vendor / tracing / src / lib.rs
CommitLineData
f035d41b
XL
1//! A scoped, structured logging and diagnostics system.
2//!
3//! # Overview
4//!
5//! `tracing` is a framework for instrumenting Rust programs to collect
6//! structured, event-based diagnostic information.
7//!
8//! In asynchronous systems like Tokio, interpreting traditional log messages can
9//! often be quite challenging. Since individual tasks are multiplexed on the same
10//! thread, associated events and log lines are intermixed making it difficult to
11//! trace the logic flow. `tracing` expands upon logging-style diagnostics by
12//! allowing libraries and applications to record structured events with additional
13//! information about *temporality* and *causality* — unlike a log message, a span
14//! in `tracing` has a beginning and end time, may be entered and exited by the
15//! flow of execution, and may exist within a nested tree of similar spans. In
16//! addition, `tracing` spans are *structured*, with the ability to record typed
17//! data as well as textual messages.
18//!
19//! The `tracing` crate provides the APIs necessary for instrumenting libraries
20//! and applications to emit trace data.
21//!
5e7ed085 22//! *Compiler support: [requires `rustc` 1.49+][msrv]*
5869c6ff
XL
23//!
24//! [msrv]: #supported-rust-versions
f035d41b
XL
25//! # Core Concepts
26//!
27//! The core of `tracing`'s API is composed of _spans_, _events_ and
28//! _subscribers_. We'll cover these in turn.
29//!
30//! ## Spans
31//!
32//! To record the flow of execution through a program, `tracing` introduces the
5869c6ff 33//! concept of [spans]. Unlike a log line that represents a _moment in
f035d41b
XL
34//! time_, a span represents a _period of time_ with a beginning and an end. When a
35//! program begins executing in a context or performing a unit of work, it
36//! _enters_ that context's span, and when it stops executing in that context,
37//! it _exits_ the span. The span in which a thread is currently executing is
38//! referred to as that thread's _current_ span.
39//!
40//! For example:
41//! ```
42//! use tracing::{span, Level};
43//! # fn main() {
44//! let span = span!(Level::TRACE, "my_span");
45//! // `enter` returns a RAII guard which, when dropped, exits the span. this
46//! // indicates that we are in the span for the current lexical scope.
47//! let _enter = span.enter();
48//! // perform some work in the context of `my_span`...
49//! # }
50//!```
51//!
52//! The [`span` module][span]'s documentation provides further details on how to
53//! use spans.
54//!
5099ac24
FG
55//! <div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
56//!
57//! **Warning**: In asynchronous code that uses async/await syntax,
58//! `Span::enter` may produce incorrect traces if the returned drop
59//! guard is held across an await point. See
60//! [the method documentation][Span#in-asynchronous-code] for details.
61//!
62//! </pre></div>
3dfed10e 63//!
f035d41b
XL
64//! ## Events
65//!
66//! An [`Event`] represents a _moment_ in time. It signifies something that
67//! happened while a trace was being recorded. `Event`s are comparable to the log
5869c6ff 68//! records emitted by unstructured logging code, but unlike a typical log line,
f035d41b
XL
69//! an `Event` may occur within the context of a span.
70//!
71//! For example:
72//! ```
73//! use tracing::{event, span, Level};
74//!
75//! # fn main() {
76//! // records an event outside of any span context:
77//! event!(Level::INFO, "something happened");
78//!
79//! let span = span!(Level::INFO, "my_span");
80//! let _guard = span.enter();
81//!
82//! // records an event within "my_span".
83//! event!(Level::DEBUG, "something happened inside my_span");
84//! # }
85//!```
86//!
87//! In general, events should be used to represent points in time _within_ a
88//! span — a request returned with a given status code, _n_ new items were
89//! taken from a queue, and so on.
90//!
91//! The [`Event` struct][`Event`] documentation provides further details on using
92//! events.
93//!
94//! ## Subscribers
95//!
96//! As `Span`s and `Event`s occur, they are recorded or aggregated by
97//! implementations of the [`Subscriber`] trait. `Subscriber`s are notified
98//! when an `Event` takes place and when a `Span` is entered or exited. These
99//! notifications are represented by the following `Subscriber` trait methods:
100//!
101//! + [`event`][Subscriber::event], called when an `Event` takes place,
102//! + [`enter`], called when execution enters a `Span`,
103//! + [`exit`], called when execution exits a `Span`
104//!
105//! In addition, subscribers may implement the [`enabled`] function to _filter_
106//! the notifications they receive based on [metadata] describing each `Span`
107//! or `Event`. If a call to `Subscriber::enabled` returns `false` for a given
108//! set of metadata, that `Subscriber` will *not* be notified about the
109//! corresponding `Span` or `Event`. For performance reasons, if no currently
110//! active subscribers express interest in a given set of metadata by returning
111//! `true`, then the corresponding `Span` or `Event` will never be constructed.
112//!
113//! # Usage
114//!
115//! First, add this to your `Cargo.toml`:
116//!
117//! ```toml
118//! [dependencies]
119//! tracing = "0.1"
120//! ```
121//!
c295e0f8 122//! *Compiler support: [requires `rustc` 1.42+][msrv]*
f035d41b
XL
123//!
124//! ## Recording Spans and Events
125//!
126//! Spans and events are recorded using macros.
127//!
128//! ### Spans
129//!
130//! The [`span!`] macro expands to a [`Span` struct][`Span`] which is used to
131//! record a span. The [`Span::enter`] method on that struct records that the
132//! span has been entered, and returns a [RAII] guard object, which will exit
133//! the span when dropped.
134//!
135//! For example:
136//!
137//! ```rust
138//! use tracing::{span, Level};
139//! # fn main() {
140//! // Construct a new span named "my span" with trace log level.
141//! let span = span!(Level::TRACE, "my span");
142//!
143//! // Enter the span, returning a guard object.
144//! let _enter = span.enter();
145//!
146//! // Any trace events that occur before the guard is dropped will occur
147//! // within the span.
148//!
149//! // Dropping the guard will exit the span.
150//! # }
151//! ```
152//!
153//! The [`#[instrument]`][instrument] attribute provides an easy way to
154//! add `tracing` spans to functions. A function annotated with `#[instrument]`
155//! will create and enter a span with that function's name every time the
156//! function is called, with arguments to that function will be recorded as
157//! fields using `fmt::Debug`.
158//!
159//! For example:
160//! ```ignore
161//! # // this doctest is ignored because we don't have a way to say
162//! # // that it should only be run with cfg(feature = "attributes")
163//! use tracing::{Level, event, instrument};
164//!
165//! #[instrument]
166//! pub fn my_function(my_arg: usize) {
167//! // This event will be recorded inside a span named `my_function` with the
168//! // field `my_arg`.
169//! event!(Level::INFO, "inside my_function!");
170//! // ...
171//! }
172//! # fn main() {}
173//! ```
174//!
17df50a5 175//! For functions which don't have built-in tracing support and can't have
3c0e092e 176//! the `#[instrument]` attribute applied (such as from an external crate),
17df50a5
XL
177//! the [`Span` struct][`Span`] has a [`in_scope()` method][`in_scope`]
178//! which can be used to easily wrap synchonous code in a span.
179//!
180//! For example:
181//! ```rust
182//! use tracing::info_span;
183//!
184//! # fn doc() -> Result<(), ()> {
185//! # mod serde_json {
186//! # pub(crate) fn from_slice(buf: &[u8]) -> Result<(), ()> { Ok(()) }
187//! # }
188//! # let buf: [u8; 0] = [];
189//! let json = info_span!("json.parse").in_scope(|| serde_json::from_slice(&buf))?;
190//! # let _ = json; // suppress unused variable warning
191//! # Ok(())
192//! # }
193//! ```
f035d41b
XL
194//!
195//! You can find more examples showing how to use this crate [here][examples].
196//!
c295e0f8 197//! [RAII]: https://github.com/rust-unofficial/patterns/blob/master/patterns/behavioural/RAII.md
f035d41b
XL
198//! [examples]: https://github.com/tokio-rs/tracing/tree/master/examples
199//!
200//! ### Events
201//!
202//! [`Event`]s are recorded using the [`event!`] macro:
203//!
204//! ```rust
205//! # fn main() {
206//! use tracing::{event, Level};
207//! event!(Level::INFO, "something has happened!");
208//! # }
209//! ```
210//!
211//! ## Using the Macros
212//!
6a06907d
XL
213//! The [`span!`] and [`event!`] macros as well as the `#[instrument]` attribute
214//! use fairly similar syntax, with some exceptions.
f035d41b
XL
215//!
216//! ### Configuring Attributes
217//!
218//! Both macros require a [`Level`] specifying the verbosity of the span or
219//! event. Optionally, the [target] and [parent span] may be overridden. If the
220//! target and parent span are not overridden, they will default to the
221//! module path where the macro was invoked and the current span (as determined
222//! by the subscriber), respectively.
223//!
224//! For example:
225//!
226//! ```
227//! # use tracing::{span, event, Level};
228//! # fn main() {
229//! span!(target: "app_spans", Level::TRACE, "my span");
230//! event!(target: "app_events", Level::INFO, "something has happened!");
231//! # }
232//! ```
233//! ```
234//! # use tracing::{span, event, Level};
235//! # fn main() {
236//! let span = span!(Level::TRACE, "my span");
237//! event!(parent: &span, Level::INFO, "something has happened!");
238//! # }
239//! ```
240//!
241//! The span macros also take a string literal after the level, to set the name
242//! of the span.
243//!
244//! ### Recording Fields
245//!
246//! Structured fields on spans and events are specified using the syntax
247//! `field_name = field_value`. Fields are separated by commas.
248//!
249//! ```
250//! # use tracing::{event, Level};
251//! # fn main() {
252//! // records an event with two fields:
253//! // - "answer", with the value 42
254//! // - "question", with the value "life, the universe and everything"
255//! event!(Level::INFO, answer = 42, question = "life, the universe, and everything");
256//! # }
257//! ```
258//!
259//! As shorthand, local variables may be used as field values without an
260//! assignment, similar to [struct initializers]. For example:
261//!
262//! ```
263//! # use tracing::{span, Level};
264//! # fn main() {
265//! let user = "ferris";
266//!
267//! span!(Level::TRACE, "login", user);
268//! // is equivalent to:
269//! span!(Level::TRACE, "login", user = user);
270//! # }
271//!```
272//!
273//! Field names can include dots, but should not be terminated by them:
274//! ```
275//! # use tracing::{span, Level};
276//! # fn main() {
277//! let user = "ferris";
278//! let email = "ferris@rust-lang.org";
279//! span!(Level::TRACE, "login", user, user.email = email);
280//! # }
281//!```
282//!
283//! Since field names can include dots, fields on local structs can be used
284//! using the local variable shorthand:
285//! ```
286//! # use tracing::{span, Level};
287//! # fn main() {
288//! # struct User {
289//! # name: &'static str,
290//! # email: &'static str,
291//! # }
292//! let user = User {
293//! name: "ferris",
294//! email: "ferris@rust-lang.org",
295//! };
296//! // the span will have the fields `user.name = "ferris"` and
297//! // `user.email = "ferris@rust-lang.org"`.
298//! span!(Level::TRACE, "login", user.name, user.email);
299//! # }
300//!```
301//!
3dfed10e
XL
302//! Fields with names that are not Rust identifiers, or with names that are Rust reserved words,
303//! may be created using quoted string literals. However, this may not be used with the local
304//! variable shorthand.
305//! ```
306//! # use tracing::{span, Level};
307//! # fn main() {
308//! // records an event with fields whose names are not Rust identifiers
309//! // - "guid:x-request-id", containing a `:`, with the value "abcdef"
310//! // - "type", which is a reserved word, with the value "request"
311//! span!(Level::TRACE, "api", "guid:x-request-id" = "abcdef", "type" = "request");
312//! # }
313//!```
314//!
f035d41b
XL
315//! The `?` sigil is shorthand that specifies a field should be recorded using
316//! its [`fmt::Debug`] implementation:
317//! ```
318//! # use tracing::{event, Level};
319//! # fn main() {
320//! #[derive(Debug)]
321//! struct MyStruct {
322//! field: &'static str,
323//! }
324//!
325//! let my_struct = MyStruct {
326//! field: "Hello world!"
327//! };
328//!
329//! // `my_struct` will be recorded using its `fmt::Debug` implementation.
330//! event!(Level::TRACE, greeting = ?my_struct);
331//! // is equivalent to:
332//! event!(Level::TRACE, greeting = tracing::field::debug(&my_struct));
333//! # }
334//! ```
335//!
336//! The `%` sigil operates similarly, but indicates that the value should be
337//! recorded using its [`fmt::Display`] implementation:
338//! ```
339//! # use tracing::{event, Level};
340//! # fn main() {
341//! # #[derive(Debug)]
342//! # struct MyStruct {
343//! # field: &'static str,
344//! # }
345//! #
346//! # let my_struct = MyStruct {
347//! # field: "Hello world!"
348//! # };
349//! // `my_struct.field` will be recorded using its `fmt::Display` implementation.
350//! event!(Level::TRACE, greeting = %my_struct.field);
351//! // is equivalent to:
352//! event!(Level::TRACE, greeting = tracing::field::display(&my_struct.field));
353//! # }
354//! ```
355//!
356//! The `%` and `?` sigils may also be used with local variable shorthand:
357//!
358//! ```
359//! # use tracing::{event, Level};
360//! # fn main() {
361//! # #[derive(Debug)]
362//! # struct MyStruct {
363//! # field: &'static str,
364//! # }
365//! #
366//! # let my_struct = MyStruct {
367//! # field: "Hello world!"
368//! # };
369//! // `my_struct.field` will be recorded using its `fmt::Display` implementation.
370//! event!(Level::TRACE, %my_struct.field);
371//! # }
372//! ```
373//!
374//! Additionally, a span may declare fields with the special value [`Empty`],
375//! which indicates that that the value for that field does not currently exist
376//! but may be recorded later. For example:
377//!
378//! ```
379//! use tracing::{trace_span, field};
380//!
381//! // Create a span with two fields: `greeting`, with the value "hello world", and
382//! // `parting`, without a value.
383//! let span = trace_span!("my_span", greeting = "hello world", parting = field::Empty);
384//!
385//! // ...
386//!
387//! // Now, record a value for parting as well.
388//! span.record("parting", &"goodbye world!");
389//! ```
390//!
391//! Note that a span may have up to 32 fields. The following will not compile:
392//!
393//! ```rust,compile_fail
394//! # use tracing::Level;
395//! # fn main() {
396//! let bad_span = span!(
397//! Level::TRACE,
398//! "too many fields!",
399//! a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9,
400//! j = 10, k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17,
401//! r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25,
402//! z = 26, aa = 27, bb = 28, cc = 29, dd = 30, ee = 31, ff = 32, gg = 33
403//! );
404//! # }
405//! ```
406//!
407//! Finally, events may also include human-readable messages, in the form of a
408//! [format string][fmt] and (optional) arguments, **after** the event's
409//! key-value fields. If a format string and arguments are provided,
410//! they will implicitly create a new field named `message` whose value is the
411//! provided set of format arguments.
412//!
413//! For example:
414//!
415//! ```
416//! # use tracing::{event, Level};
417//! # fn main() {
5099ac24 418//! let question = "the ultimate question of life, the universe, and everything";
f035d41b
XL
419//! let answer = 42;
420//! // records an event with the following fields:
421//! // - `question.answer` with the value 42,
422//! // - `question.tricky` with the value `true`,
423//! // - "message", with the value "the answer to the ultimate question of life, the
424//! // universe, and everything is 42."
425//! event!(
426//! Level::DEBUG,
427//! question.answer = answer,
428//! question.tricky = true,
429//! "the answer to {} is {}.", question, answer
430//! );
431//! # }
432//! ```
433//!
434//! Specifying a formatted message in this manner does not allocate by default.
435//!
436//! [struct initializers]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name
04454e1e
FG
437//! [target]: Metadata::target
438//! [parent span]: span::Attributes::parent
439//! [determined contextually]: span::Attributes::is_contextual
f035d41b
XL
440//! [`fmt::Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
441//! [`fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
442//! [fmt]: https://doc.rust-lang.org/std/fmt/#usage
04454e1e 443//! [`Empty`]: field::Empty
f035d41b
XL
444//!
445//! ### Shorthand Macros
446//!
447//! `tracing` also offers a number of macros with preset verbosity levels.
448//! The [`trace!`], [`debug!`], [`info!`], [`warn!`], and [`error!`] behave
449//! similarly to the [`event!`] macro, but with the [`Level`] argument already
450//! specified, while the corresponding [`trace_span!`], [`debug_span!`],
451//! [`info_span!`], [`warn_span!`], and [`error_span!`] macros are the same,
452//! but for the [`span!`] macro.
453//!
454//! These are intended both as a shorthand, and for compatibility with the [`log`]
455//! crate (see the next section).
456//!
04454e1e
FG
457//! [`span!`]: span!
458//! [`event!`]: event!
459//! [`trace!`]: trace!
460//! [`debug!`]: debug!
461//! [`info!`]: info!
462//! [`warn!`]: warn!
463//! [`error!`]: error!
464//! [`trace_span!`]: trace_span!
465//! [`debug_span!`]: debug_span!
466//! [`info_span!`]: info_span!
467//! [`warn_span!`]: warn_span!
468//! [`error_span!`]: error_span!
469//! [`Level`]: Level
f035d41b
XL
470//!
471//! ### For `log` Users
472//!
473//! Users of the [`log`] crate should note that `tracing` exposes a set of
474//! macros for creating `Event`s (`trace!`, `debug!`, `info!`, `warn!`, and
475//! `error!`) which may be invoked with the same syntax as the similarly-named
476//! macros from the `log` crate. Often, the process of converting a project to
477//! use `tracing` can begin with a simple drop-in replacement.
478//!
479//! Let's consider the `log` crate's yak-shaving example:
480//!
481//! ```rust,ignore
482//! use std::{error::Error, io};
483//! use tracing::{debug, error, info, span, warn, Level};
484//!
485//! // the `#[tracing::instrument]` attribute creates and enters a span
486//! // every time the instrumented function is called. The span is named after the
487//! // the function or method. Parameters passed to the function are recorded as fields.
488//! #[tracing::instrument]
489//! pub fn shave(yak: usize) -> Result<(), Box<dyn Error + 'static>> {
490//! // this creates an event at the DEBUG level with two fields:
491//! // - `excitement`, with the key "excitement" and the value "yay!"
492//! // - `message`, with the key "message" and the value "hello! I'm gonna shave a yak."
493//! //
494//! // unlike other fields, `message`'s shorthand initialization is just the string itself.
495//! debug!(excitement = "yay!", "hello! I'm gonna shave a yak.");
496//! if yak == 3 {
497//! warn!("could not locate yak!");
498//! // note that this is intended to demonstrate `tracing`'s features, not idiomatic
499//! // error handling! in a library or application, you should consider returning
500//! // a dedicated `YakError`. libraries like snafu or thiserror make this easy.
501//! return Err(io::Error::new(io::ErrorKind::Other, "shaving yak failed!").into());
502//! } else {
503//! debug!("yak shaved successfully");
504//! }
505//! Ok(())
506//! }
507//!
508//! pub fn shave_all(yaks: usize) -> usize {
509//! // Constructs a new span named "shaving_yaks" at the TRACE level,
510//! // and a field whose key is "yaks". This is equivalent to writing:
511//! //
512//! // let span = span!(Level::TRACE, "shaving_yaks", yaks = yaks);
513//! //
514//! // local variables (`yaks`) can be used as field values
515//! // without an assignment, similar to struct initializers.
6a06907d 516//! let _span = span!(Level::TRACE, "shaving_yaks", yaks).entered();
f035d41b
XL
517//!
518//! info!("shaving yaks");
519//!
520//! let mut yaks_shaved = 0;
521//! for yak in 1..=yaks {
522//! let res = shave(yak);
523//! debug!(yak, shaved = res.is_ok());
524//!
525//! if let Err(ref error) = res {
526//! // Like spans, events can also use the field initialization shorthand.
527//! // In this instance, `yak` is the field being initalized.
528//! error!(yak, error = error.as_ref(), "failed to shave yak!");
529//! } else {
530//! yaks_shaved += 1;
531//! }
532//! debug!(yaks_shaved);
533//! }
534//!
535//! yaks_shaved
536//! }
537//! ```
538//!
539//! ## In libraries
540//!
541//! Libraries should link only to the `tracing` crate, and use the provided
542//! macros to record whatever information will be useful to downstream
543//! consumers.
544//!
545//! ## In executables
546//!
547//! In order to record trace events, executables have to use a `Subscriber`
548//! implementation compatible with `tracing`. A `Subscriber` implements a
549//! way of collecting trace data, such as by logging it to standard output.
550//!
551//! This library does not contain any `Subscriber` implementations; these are
552//! provided by [other crates](#related-crates).
553//!
554//! The simplest way to use a subscriber is to call the [`set_global_default`]
555//! function:
556//!
557//! ```
558//! extern crate tracing;
559//! # pub struct FooSubscriber;
560//! # use tracing::{span::{Id, Attributes, Record}, Metadata};
561//! # impl tracing::Subscriber for FooSubscriber {
562//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
563//! # fn record(&self, _: &Id, _: &Record) {}
564//! # fn event(&self, _: &tracing::Event) {}
565//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
566//! # fn enabled(&self, _: &Metadata) -> bool { false }
567//! # fn enter(&self, _: &Id) {}
568//! # fn exit(&self, _: &Id) {}
569//! # }
570//! # impl FooSubscriber {
571//! # fn new() -> Self { FooSubscriber }
572//! # }
573//! # fn main() {
574//!
575//! let my_subscriber = FooSubscriber::new();
576//! tracing::subscriber::set_global_default(my_subscriber)
577//! .expect("setting tracing default failed");
578//! # }
579//! ```
580//!
c295e0f8
XL
581//! <pre class="compile_fail" style="white-space:normal;font:inherit;">
582//! <strong>Warning</strong>: In general, libraries should <em>not</em> call
583//! <code>set_global_default()</code>! Doing so will cause conflicts when
584//! executables that depend on the library try to set the default later.
585//! </pre>
f035d41b
XL
586//!
587//! This subscriber will be used as the default in all threads for the
588//! remainder of the duration of the program, similar to setting the logger
589//! in the `log` crate.
590//!
591//! In addition, the default subscriber can be set through using the
592//! [`with_default`] function. This follows the `tokio` pattern of using
593//! closures to represent executing code in a context that is exited at the end
594//! of the closure. For example:
595//!
596//! ```rust
597//! # pub struct FooSubscriber;
598//! # use tracing::{span::{Id, Attributes, Record}, Metadata};
599//! # impl tracing::Subscriber for FooSubscriber {
600//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
601//! # fn record(&self, _: &Id, _: &Record) {}
602//! # fn event(&self, _: &tracing::Event) {}
603//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
604//! # fn enabled(&self, _: &Metadata) -> bool { false }
605//! # fn enter(&self, _: &Id) {}
606//! # fn exit(&self, _: &Id) {}
607//! # }
608//! # impl FooSubscriber {
609//! # fn new() -> Self { FooSubscriber }
610//! # }
611//! # fn main() {
612//!
613//! let my_subscriber = FooSubscriber::new();
614//! # #[cfg(feature = "std")]
615//! tracing::subscriber::with_default(my_subscriber, || {
616//! // Any trace events generated in this closure or by functions it calls
617//! // will be collected by `my_subscriber`.
618//! })
619//! # }
620//! ```
621//!
622//! This approach allows trace data to be collected by multiple subscribers
623//! within different contexts in the program. Note that the override only applies to the
624//! currently executing thread; other threads will not see the change from with_default.
625//!
626//! Any trace events generated outside the context of a subscriber will not be collected.
627//!
628//! Once a subscriber has been set, instrumentation points may be added to the
629//! executable using the `tracing` crate's macros.
630//!
631//! ## `log` Compatibility
632//!
633//! The [`log`] crate provides a simple, lightweight logging facade for Rust.
634//! While `tracing` builds upon `log`'s foundation with richer structured
635//! diagnostic data, `log`'s simplicity and ubiquity make it the "lowest common
636//! denominator" for text-based logging in Rust — a vast majority of Rust
637//! libraries and applications either emit or consume `log` records. Therefore,
638//! `tracing` provides multiple forms of interoperability with `log`: `tracing`
639//! instrumentation can emit `log` records, and a compatibility layer enables
640//! `tracing` [`Subscriber`]s to consume `log` records as `tracing` [`Event`]s.
641//!
642//! ### Emitting `log` Records
643//!
644//! This crate provides two feature flags, "log" and "log-always", which will
645//! cause [spans] and [events] to emit `log` records. When the "log" feature is
646//! enabled, if no `tracing` `Subscriber` is active, invoking an event macro or
647//! creating a span with fields will emit a `log` record. This is intended
648//! primarily for use in libraries which wish to emit diagnostics that can be
649//! consumed by applications using `tracing` *or* `log`, without paying the
650//! additional overhead of emitting both forms of diagnostics when `tracing` is
651//! in use.
652//!
653//! Enabling the "log-always" feature will cause `log` records to be emitted
654//! even if a `tracing` `Subscriber` _is_ set. This is intended to be used in
655//! applications where a `log` `Logger` is being used to record a textual log,
656//! and `tracing` is used only to record other forms of diagnostics (such as
657//! metrics, profiling, or distributed tracing data). Unlike the "log" feature,
658//! libraries generally should **not** enable the "log-always" feature, as doing
659//! so will prevent applications from being able to opt out of the `log` records.
660//!
661//! See [here][flags] for more details on this crate's feature flags.
662//!
663//! The generated `log` records' messages will be a string representation of the
664//! span or event's fields, and all additional information recorded by `log`
665//! (target, verbosity level, module path, file, and line number) will also be
666//! populated. Additionally, `log` records are also generated when spans are
667//! entered, exited, and closed. Since these additional span lifecycle logs have
668//! the potential to be very verbose, and don't include additional fields, they
3dfed10e
XL
669//! will always be emitted at the `Trace` level, rather than inheriting the
670//! level of the span that generated them. Furthermore, they are are categorized
671//! under a separate `log` target, "tracing::span" (and its sub-target,
672//! "tracing::span::active", for the logs on entering and exiting a span), which
673//! may be enabled or disabled separately from other `log` records emitted by
674//! `tracing`.
f035d41b
XL
675//!
676//! ### Consuming `log` Records
677//!
678//! The [`tracing-log`] crate provides a compatibility layer which
679//! allows a `tracing` [`Subscriber`] to consume `log` records as though they
680//! were `tracing` [events]. This allows applications using `tracing` to record
681//! the logs emitted by dependencies using `log` as events within the context of
682//! the application's trace tree. See [that crate's documentation][log-tracer]
683//! for details.
684//!
685//! [log-tracer]: https://docs.rs/tracing-log/latest/tracing_log/#convert-log-records-to-tracing-events
686//!
687//! ## Related Crates
688//!
689//! In addition to `tracing` and `tracing-core`, the [`tokio-rs/tracing`] repository
690//! contains several additional crates designed to be used with the `tracing` ecosystem.
691//! This includes a collection of `Subscriber` implementations, as well as utility
692//! and adapter crates to assist in writing `Subscriber`s and instrumenting
693//! applications.
694//!
695//! In particular, the following crates are likely to be of interest:
696//!
697//! - [`tracing-futures`] provides a compatibility layer with the `futures`
698//! crate, allowing spans to be attached to `Future`s, `Stream`s, and `Executor`s.
699//! - [`tracing-subscriber`] provides `Subscriber` implementations and
700//! utilities for working with `Subscriber`s. This includes a [`FmtSubscriber`]
701//! `FmtSubscriber` for logging formatted trace data to stdout, with similar
702//! filtering and formatting to the [`env_logger`] crate.
703//! - [`tracing-log`] provides a compatibility layer with the [`log`] crate,
704//! allowing log messages to be recorded as `tracing` `Event`s within the
705//! trace tree. This is useful when a project using `tracing` have
706//! dependencies which use `log`. Note that if you're using
707//! `tracing-subscriber`'s `FmtSubscriber`, you don't need to depend on
708//! `tracing-log` directly.
709//! - [`tracing-appender`] provides utilities for outputting tracing data,
710//! including a file appender and non blocking writer.
711//!
712//! Additionally, there are also several third-party crates which are not
713//! maintained by the `tokio` project. These include:
714//!
715//! - [`tracing-timing`] implements inter-event timing metrics on top of `tracing`.
716//! It provides a subscriber that records the time elapsed between pairs of
717//! `tracing` events and generates histograms.
718//! - [`tracing-opentelemetry`] provides a subscriber for emitting traces to
719//! [OpenTelemetry]-compatible distributed tracing systems.
720//! - [`tracing-honeycomb`] Provides a layer that reports traces spanning multiple machines to [honeycomb.io]. Backed by [`tracing-distributed`].
721//! - [`tracing-distributed`] Provides a generic implementation of a layer that reports traces spanning multiple machines to some backend.
c295e0f8 722//! - [`tracing-actix-web`] provides `tracing` integration for the `actix-web` web framework.
f035d41b
XL
723//! - [`tracing-actix`] provides `tracing` integration for the `actix` actor
724//! framework.
725//! - [`tracing-gelf`] implements a subscriber for exporting traces in Greylog
726//! GELF format.
727//! - [`tracing-coz`] provides integration with the [coz] causal profiler
728//! (Linux-only).
729//! - [`tracing-bunyan-formatter`] provides a layer implementation that reports events and spans
730//! in [bunyan] format, enriched with timing information.
3dfed10e
XL
731//! - [`tracing-wasm`] provides a `Subscriber`/`Layer` implementation that reports
732//! events and spans via browser `console.log` and [User Timing API (`window.performance`)].
733//! - [`tide-tracing`] provides a [tide] middleware to trace all incoming requests and responses.
5099ac24 734//! - [`test-log`] takes care of initializing `tracing` for tests, based on
5869c6ff
XL
735//! environment variables with an `env_logger` compatible syntax.
736//! - [`tracing-unwrap`] provides convenience methods to report failed unwraps
737//! on `Result` or `Option` types to a `Subscriber`.
738//! - [`diesel-tracing`] provides integration with [`diesel`] database connections.
739//! - [`tracing-tracy`] provides a way to collect [Tracy] profiles in instrumented
740//! applications.
6a06907d 741//! - [`tracing-elastic-apm`] provides a layer for reporting traces to [Elastic APM].
5099ac24
FG
742//! - [`tracing-etw`] provides a layer for emitting Windows [ETW] events.
743//! - [`tracing-fluent-assertions`] provides a fluent assertions-style testing
744//! framework for validating the behavior of `tracing` spans.
745//! - [`sentry-tracing`] provides a layer for reporting events and traces to [Sentry].
5e7ed085
FG
746//! - [`tracing-forest`] provides a subscriber that preserves contextual coherence by
747//! grouping together logs from the same spans during writing.
04454e1e 748//! - [`tracing-loki`] provides a layer for shipping logs to [Grafana Loki].
f035d41b
XL
749//!
750//! If you're the maintainer of a `tracing` ecosystem crate not listed above,
751//! please let us know! We'd love to add your project to the list!
752//!
753//! [`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry
754//! [OpenTelemetry]: https://opentelemetry.io/
755//! [`tracing-honeycomb`]: https://crates.io/crates/tracing-honeycomb
756//! [`tracing-distributed`]: https://crates.io/crates/tracing-distributed
757//! [honeycomb.io]: https://www.honeycomb.io/
c295e0f8 758//! [`tracing-actix-web`]: https://crates.io/crates/tracing-actix-web
f035d41b
XL
759//! [`tracing-actix`]: https://crates.io/crates/tracing-actix
760//! [`tracing-gelf`]: https://crates.io/crates/tracing-gelf
761//! [`tracing-coz`]: https://crates.io/crates/tracing-coz
762//! [coz]: https://github.com/plasma-umass/coz
763//! [`tracing-bunyan-formatter`]: https://crates.io/crates/tracing-bunyan-formatter
764//! [bunyan]: https://github.com/trentm/node-bunyan
3dfed10e
XL
765//! [`tracing-wasm`]: https://docs.rs/tracing-wasm
766//! [User Timing API (`window.performance`)]: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API
767//! [`tide-tracing`]: https://crates.io/crates/tide-tracing
768//! [tide]: https://crates.io/crates/tide
5099ac24 769//! [`test-log`]: https://crates.io/crates/test-log
5869c6ff
XL
770//! [`tracing-unwrap`]: https://docs.rs/tracing-unwrap
771//! [`diesel`]: https://crates.io/crates/diesel
772//! [`diesel-tracing`]: https://crates.io/crates/diesel-tracing
773//! [`tracing-tracy`]: https://crates.io/crates/tracing-tracy
774//! [Tracy]: https://github.com/wolfpld/tracy
6a06907d
XL
775//! [`tracing-elastic-apm`]: https://crates.io/crates/tracing-elastic-apm
776//! [Elastic APM]: https://www.elastic.co/apm
5099ac24
FG
777//! [`tracing-etw`]: https://github.com/microsoft/tracing-etw
778//! [ETW]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing
779//! [`tracing-fluent-assertions`]: https://crates.io/crates/tracing-fluent-assertions
780//! [`sentry-tracing`]: https://crates.io/crates/sentry-tracing
781//! [Sentry]: https://sentry.io/welcome/
5e7ed085 782//! [`tracing-forest`]: https://crates.io/crates/tracing-forest
04454e1e
FG
783//! [`tracing-loki`]: https://crates.io/crates/tracing-loki
784//! [Grafana Loki]: https://grafana.com/oss/loki/
3dfed10e 785//!
3dfed10e 786//! <pre class="ignore" style="white-space:normal;font:inherit;">
c295e0f8
XL
787//! <strong>Note</strong>: Some of these ecosystem crates are currently
788//! unreleased and/or in earlier stages of development. They may be less stable
789//! than <code>tracing</code> and <code>tracing-core</code>.
790//! </pre>
f035d41b
XL
791//!
792//! ## Crate Feature Flags
793//!
5099ac24 794//! The following crate [feature flags] are available:
f035d41b
XL
795//!
796//! * A set of features controlling the [static verbosity level].
797//! * `log`: causes trace instrumentation points to emit [`log`] records as well
798//! as trace events, if a default `tracing` subscriber has not been set. This
799//! is intended for use in libraries whose users may be using either `tracing`
800//! or `log`.
f035d41b 801//! * `log-always`: Emit `log` records from all `tracing` spans and events, even
3dfed10e 802//! if a `tracing` subscriber has been set. This should be set only by
f035d41b
XL
803//! applications which intend to collect traces and logs separately; if an
804//! adapter is used to convert `log` records into `tracing` events, this will
805//! cause duplicate events to occur.
806//! * `attributes`: Includes support for the `#[instrument]` attribute.
807//! This is on by default, but does bring in the `syn` crate as a dependency,
808//! which may add to the compile time of crates that do not already use it.
809//! * `std`: Depend on the Rust standard library (enabled by default).
810//!
811//! `no_std` users may disable this feature with `default-features = false`:
812//!
813//! ```toml
814//! [dependencies]
04454e1e 815//! tracing = { version = "0.1.34", default-features = false }
f035d41b
XL
816//! ```
817//!
3dfed10e 818//! <pre class="ignore" style="white-space:normal;font:inherit;">
c295e0f8
XL
819//! <strong>Note</strong>: <code>tracing</code>'s <code>no_std</code> support
820//! requires <code>liballoc</code>.
821//! </pre>
f035d41b 822//!
5099ac24
FG
823//! ### Unstable Features
824//!
825//! These feature flags enable **unstable** features. The public API may break in 0.1.x
826//! releases. To enable these features, the `--cfg tracing_unstable` must be passed to
827//! `rustc` when compiling.
828//!
829//! The following unstable feature flags are currently available:
830//!
831//! * `valuable`: Enables support for recording [field values] using the
832//! [`valuable`] crate.
833//!
834//! #### Enabling Unstable Features
835//!
836//! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS`
837//! env variable when running `cargo` commands:
838//!
839//! ```shell
840//! RUSTFLAGS="--cfg tracing_unstable" cargo build
841//! ```
842//! Alternatively, the following can be added to the `.cargo/config` file in a
843//! project to automatically enable the cfg flag for that project:
844//!
845//! ```toml
846//! [build]
847//! rustflags = ["--cfg", "tracing_unstable"]
848//! ```
849//!
850//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
851//! [field values]: crate::field
852//! [`valuable`]: https://crates.io/crates/valuable
853//!
5869c6ff
XL
854//! ## Supported Rust Versions
855//!
856//! Tracing is built against the latest stable release. The minimum supported
5e7ed085 857//! version is 1.49. The current Tracing version is not guaranteed to build on
5869c6ff
XL
858//! Rust versions earlier than the minimum supported version.
859//!
860//! Tracing follows the same compiler support policies as the rest of the Tokio
861//! project. The current stable Rust compiler and the three most recent minor
862//! versions before it will always be supported. For example, if the current
863//! stable compiler version is 1.45, the minimum supported version will not be
864//! increased past 1.42, three minor versions prior. Increasing the minimum
865//! supported compiler version is not considered a semver breaking change as
866//! long as doing so complies with this policy.
867//!
f035d41b 868//! [`log`]: https://docs.rs/log/0.4.6/log/
5869c6ff
XL
869//! [span]: mod@span
870//! [spans]: mod@span
871//! [`Span`]: span::Span
872//! [`in_scope`]: span::Span::in_scope
873//! [event]: Event
874//! [events]: Event
875//! [`Subscriber`]: subscriber::Subscriber
876//! [Subscriber::event]: subscriber::Subscriber::event
877//! [`enter`]: subscriber::Subscriber::enter
878//! [`exit`]: subscriber::Subscriber::exit
879//! [`enabled`]: subscriber::Subscriber::enabled
880//! [metadata]: Metadata
881//! [`field::display`]: field::display
882//! [`field::debug`]: field::debug
883//! [`set_global_default`]: subscriber::set_global_default
884//! [`with_default`]: subscriber::with_default
f035d41b
XL
885//! [`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing
886//! [`tracing-futures`]: https://crates.io/crates/tracing-futures
887//! [`tracing-subscriber`]: https://crates.io/crates/tracing-subscriber
888//! [`tracing-log`]: https://crates.io/crates/tracing-log
889//! [`tracing-timing`]: https://crates.io/crates/tracing-timing
890//! [`tracing-appender`]: https://crates.io/crates/tracing-appender
891//! [`env_logger`]: https://crates.io/crates/env_logger
892//! [`FmtSubscriber`]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/struct.Subscriber.html
04454e1e 893//! [static verbosity level]: level_filters#compile-time-filters
f035d41b
XL
894//! [instrument]: https://docs.rs/tracing-attributes/latest/tracing_attributes/attr.instrument.html
895//! [flags]: #crate-feature-flags
896#![cfg_attr(not(feature = "std"), no_std)]
c295e0f8 897#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))]
04454e1e 898#![doc(html_root_url = "https://docs.rs/tracing/0.1.34")]
3dfed10e 899#![doc(
5869c6ff 900 html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
3dfed10e
XL
901 issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
902)]
f035d41b
XL
903#![warn(
904 missing_debug_implementations,
905 missing_docs,
906 rust_2018_idioms,
907 unreachable_pub,
908 bad_style,
909 const_err,
910 dead_code,
911 improper_ctypes,
912 non_shorthand_field_patterns,
913 no_mangle_generic_items,
914 overflowing_literals,
915 path_statements,
916 patterns_in_fns_without_body,
917 private_in_public,
918 unconditional_recursion,
919 unused,
920 unused_allocation,
921 unused_comparisons,
922 unused_parens,
923 while_true
924)]
925
926#[cfg(not(feature = "std"))]
927extern crate alloc;
928
f035d41b
XL
929// Somehow this `use` statement is necessary for us to re-export the `core`
930// macros on Rust 1.26.0. I'm not sure how this makes it work, but it does.
931#[allow(unused_imports)]
932#[doc(hidden)]
933use tracing_core::*;
934
5869c6ff
XL
935#[doc(inline)]
936pub use self::instrument::Instrument;
f035d41b
XL
937pub use self::{dispatcher::Dispatch, event::Event, field::Value, subscriber::Subscriber};
938
939#[doc(hidden)]
940pub use self::span::Id;
941
942#[doc(hidden)]
943pub use tracing_core::{
944 callsite::{self, Callsite},
945 metadata,
946};
947pub use tracing_core::{event, Level, Metadata};
948
949#[doc(inline)]
950pub use self::span::Span;
951#[cfg(feature = "attributes")]
952#[cfg_attr(docsrs, doc(cfg(feature = "attributes")))]
953#[doc(inline)]
954pub use tracing_attributes::instrument;
955
956#[macro_use]
957mod macros;
958
959pub mod dispatcher;
960pub mod field;
5869c6ff
XL
961/// Attach a span to a `std::future::Future`.
962pub mod instrument;
f035d41b
XL
963pub mod level_filters;
964pub mod span;
965pub(crate) mod stdlib;
966pub mod subscriber;
967
968#[doc(hidden)]
969pub mod __macro_support {
5869c6ff 970 pub use crate::callsite::Callsite;
c295e0f8
XL
971 use crate::stdlib::{
972 fmt,
973 sync::atomic::{AtomicUsize, Ordering},
974 };
5869c6ff 975 use crate::{subscriber::Interest, Metadata};
5099ac24 976 pub use core::concat;
3dfed10e
XL
977 use tracing_core::Once;
978
979 /// Callsite implementation used by macro-generated code.
980 ///
981 /// /!\ WARNING: This is *not* a stable API! /!\
982 /// This type, and all code contained in the `__macro_support` module, is
983 /// a *private* API of `tracing`. It is exposed publicly because it is used
984 /// by the `tracing` macros, but it is not part of the stable versioned API.
985 /// Breaking changes to this module may occur in small-numbered versions
986 /// without warning.
3dfed10e
XL
987 pub struct MacroCallsite {
988 interest: AtomicUsize,
989 meta: &'static Metadata<'static>,
990 registration: Once,
991 }
992
993 impl MacroCallsite {
994 /// Returns a new `MacroCallsite` with the specified `Metadata`.
995 ///
996 /// /!\ WARNING: This is *not* a stable API! /!\
997 /// This method, and all code contained in the `__macro_support` module, is
998 /// a *private* API of `tracing`. It is exposed publicly because it is used
999 /// by the `tracing` macros, but it is not part of the stable versioned API.
1000 /// Breaking changes to this module may occur in small-numbered versions
1001 /// without warning.
1002 pub const fn new(meta: &'static Metadata<'static>) -> Self {
1003 Self {
04454e1e 1004 interest: AtomicUsize::new(0xDEAD),
3dfed10e
XL
1005 meta,
1006 registration: Once::new(),
1007 }
1008 }
1009
5869c6ff
XL
1010 /// Registers this callsite with the global callsite registry.
1011 ///
1012 /// If the callsite is already registered, this does nothing.
3dfed10e
XL
1013 ///
1014 /// /!\ WARNING: This is *not* a stable API! /!\
1015 /// This method, and all code contained in the `__macro_support` module, is
1016 /// a *private* API of `tracing`. It is exposed publicly because it is used
1017 /// by the `tracing` macros, but it is not part of the stable versioned API.
1018 /// Breaking changes to this module may occur in small-numbered versions
1019 /// without warning.
5869c6ff
XL
1020 #[inline(never)]
1021 // This only happens once (or if the cached interest value was corrupted).
1022 #[cold]
1023 pub fn register(&'static self) -> Interest {
1024 self.registration
1025 .call_once(|| crate::callsite::register(self));
1026 match self.interest.load(Ordering::Relaxed) {
1027 0 => Interest::never(),
1028 2 => Interest::always(),
1029 _ => Interest::sometimes(),
3dfed10e 1030 }
3dfed10e
XL
1031 }
1032
5869c6ff
XL
1033 /// Returns the callsite's cached Interest, or registers it for the
1034 /// first time if it has not yet been registered.
3dfed10e
XL
1035 ///
1036 /// /!\ WARNING: This is *not* a stable API! /!\
1037 /// This method, and all code contained in the `__macro_support` module, is
1038 /// a *private* API of `tracing`. It is exposed publicly because it is used
1039 /// by the `tracing` macros, but it is not part of the stable versioned API.
1040 /// Breaking changes to this module may occur in small-numbered versions
1041 /// without warning.
5869c6ff
XL
1042 #[inline]
1043 pub fn interest(&'static self) -> Interest {
3dfed10e
XL
1044 match self.interest.load(Ordering::Relaxed) {
1045 0 => Interest::never(),
5869c6ff 1046 1 => Interest::sometimes(),
3dfed10e 1047 2 => Interest::always(),
5869c6ff 1048 _ => self.register(),
3dfed10e
XL
1049 }
1050 }
5869c6ff
XL
1051
1052 pub fn is_enabled(&self, interest: Interest) -> bool {
1053 interest.is_always()
1054 || crate::dispatcher::get_default(|default| default.enabled(self.meta))
1055 }
1056
1057 #[inline]
1058 #[cfg(feature = "log")]
1059 pub fn disabled_span(&self) -> crate::Span {
1060 crate::Span::new_disabled(self.meta)
1061 }
1062
1063 #[inline]
1064 #[cfg(not(feature = "log"))]
1065 pub fn disabled_span(&self) -> crate::Span {
1066 crate::Span::none()
1067 }
04454e1e
FG
1068
1069 #[cfg(feature = "log")]
1070 pub fn log(
1071 &self,
1072 logger: &'static dyn log::Log,
1073 log_meta: log::Metadata<'_>,
1074 values: &tracing_core::field::ValueSet<'_>,
1075 ) {
1076 let meta = self.metadata();
1077 logger.log(
1078 &crate::log::Record::builder()
1079 .file(meta.file())
1080 .module_path(meta.module_path())
1081 .line(meta.line())
1082 .metadata(log_meta)
1083 .args(format_args!(
1084 "{}",
1085 crate::log::LogValueSet {
1086 values,
1087 is_first: true
1088 }
1089 ))
1090 .build(),
1091 );
1092 }
3dfed10e 1093 }
f035d41b 1094
3dfed10e
XL
1095 impl Callsite for MacroCallsite {
1096 fn set_interest(&self, interest: Interest) {
1097 let interest = match () {
1098 _ if interest.is_never() => 0,
1099 _ if interest.is_always() => 2,
1100 _ => 1,
1101 };
1102 self.interest.store(interest, Ordering::SeqCst);
1103 }
f035d41b 1104
3dfed10e
XL
1105 #[inline(always)]
1106 fn metadata(&self) -> &Metadata<'static> {
c295e0f8
XL
1107 self.meta
1108 }
1109 }
1110
1111 impl fmt::Debug for MacroCallsite {
1112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1113 f.debug_struct("MacroCallsite")
1114 .field("interest", &self.interest)
1115 .field("meta", &self.meta)
1116 .field("registration", &self.registration)
1117 .finish()
3dfed10e
XL
1118 }
1119 }
04454e1e 1120}
5099ac24 1121
04454e1e
FG
1122#[cfg(feature = "log")]
1123#[doc(hidden)]
1124pub mod log {
1125 use core::fmt;
1126 pub use log::*;
5099ac24
FG
1127 use tracing_core::field::{Field, ValueSet, Visit};
1128
04454e1e
FG
1129 /// Utility to format [`ValueSet`]s for logging.
1130 pub(crate) struct LogValueSet<'a> {
1131 pub(crate) values: &'a ValueSet<'a>,
1132 pub(crate) is_first: bool,
1133 }
5099ac24 1134
5099ac24 1135 impl<'a> fmt::Display for LogValueSet<'a> {
04454e1e 1136 #[inline]
5099ac24 1137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
04454e1e
FG
1138 struct LogVisitor<'a, 'b> {
1139 f: &'a mut fmt::Formatter<'b>,
1140 is_first: bool,
1141 result: fmt::Result,
1142 }
5099ac24 1143
04454e1e
FG
1144 impl Visit for LogVisitor<'_, '_> {
1145 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
1146 let res = if self.is_first {
1147 self.is_first = false;
1148 if field.name() == "message" {
1149 write!(self.f, "{:?}", value)
1150 } else {
1151 write!(self.f, "{}={:?}", field.name(), value)
1152 }
1153 } else {
1154 write!(self.f, " {}={:?}", field.name(), value)
1155 };
1156 if let Err(err) = res {
1157 self.result = self.result.and(Err(err));
1158 }
1159 }
5099ac24 1160
04454e1e
FG
1161 fn record_str(&mut self, field: &Field, value: &str) {
1162 if field.name() == "message" {
1163 self.record_debug(field, &format_args!("{}", value))
1164 } else {
1165 self.record_debug(field, &value)
1166 }
5099ac24 1167 }
5099ac24 1168 }
5099ac24 1169
04454e1e
FG
1170 let mut visit = LogVisitor {
1171 f,
1172 is_first: self.is_first,
1173 result: Ok(()),
1174 };
1175 self.values.record(&mut visit);
1176 visit.result
5099ac24
FG
1177 }
1178 }
f035d41b
XL
1179}
1180
1181mod sealed {
1182 pub trait Sealed {}
1183}