3 fmt
::{format, FormatEvent, FormatFields, MakeWriter, TestWriter}
,
4 layer
::{self, Context}
,
5 registry
::{self, LookupSpan, SpanRef}
,
7 use format
::{FmtSpan, TimingDisplay}
;
8 use std
::{any::TypeId, cell::RefCell, fmt, io, marker::PhantomData, ops::Deref, time::Instant}
;
11 span
::{Attributes, Current, Id, Record}
,
12 Event
, Metadata
, Subscriber
,
15 /// A [`Layer`] that logs formatted representations of `tracing` events.
19 /// Constructing a layer with the default configuration:
22 /// use tracing_subscriber::{fmt, Registry};
23 /// use tracing_subscriber::prelude::*;
25 /// let subscriber = Registry::default()
26 /// .with(fmt::Layer::default());
28 /// tracing::subscriber::set_global_default(subscriber).unwrap();
31 /// Overriding the layer's behavior:
34 /// use tracing_subscriber::{fmt, Registry};
35 /// use tracing_subscriber::prelude::*;
37 /// let fmt_layer = fmt::layer()
38 /// .with_target(false) // don't include event targets when logging
39 /// .with_level(false); // don't include event levels when logging
41 /// let subscriber = Registry::default().with(fmt_layer);
42 /// # tracing::subscriber::set_global_default(subscriber).unwrap();
45 /// Setting a custom event formatter:
48 /// use tracing_subscriber::fmt::{self, format, time};
49 /// use tracing_subscriber::prelude::*;
51 /// let fmt = format().with_timer(time::Uptime::default());
52 /// let fmt_layer = fmt::layer()
53 /// .event_format(fmt)
54 /// .with_target(false);
55 /// # let subscriber = fmt_layer.with_subscriber(tracing_subscriber::registry::Registry::default());
56 /// # tracing::subscriber::set_global_default(subscriber).unwrap();
59 /// [`Layer`]: ../layer/trait.Layer.html
60 #[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
64 N
= format
::DefaultFields
,
65 E
= format
::Format
<format
::Full
>,
66 W
= fn() -> io
::Stdout
,
71 fmt_span
: format
::FmtSpanConfig
,
73 _inner
: PhantomData
<S
>,
77 /// Returns a new [`Layer`](struct.Layer.html) with the default configuration.
78 pub fn new() -> Self {
83 // This needs to be a seperate impl block because they place different bounds on the type parameters.
84 impl<S
, N
, E
, W
> Layer
<S
, N
, E
, W
>
86 S
: Subscriber
+ for<'a
> LookupSpan
<'a
>,
87 N
: for<'writer
> FormatFields
<'writer
> + '
static,
88 W
: for<'writer
> MakeWriter
<'writer
> + '
static,
90 /// Sets the [event formatter][`FormatEvent`] that the layer being built will
91 /// use to format events.
93 /// The event formatter may be any type implementing the [`FormatEvent`]
94 /// trait, which is implemented for all functions taking a [`FmtContext`], a
95 /// [`Writer`], and an [`Event`].
99 /// Setting a type implementing [`FormatEvent`] as the formatter:
101 /// use tracing_subscriber::fmt::{self, format};
103 /// let layer = fmt::layer()
104 /// .event_format(format().compact());
105 /// # // this is necessary for type inference.
106 /// # use tracing_subscriber::Layer as _;
107 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
109 /// [`FormatEvent`]: format::FormatEvent
110 /// [`Event`]: tracing::Event
111 /// [`Writer`]: format::Writer
112 pub fn event_format
<E2
>(self, e
: E2
) -> Layer
<S
, N
, E2
, W
>
114 E2
: FormatEvent
<S
, N
> + '
static,
117 fmt_fields
: self.fmt_fields
,
119 fmt_span
: self.fmt_span
,
120 make_writer
: self.make_writer
,
121 is_ansi
: self.is_ansi
,
126 /// Updates the event formatter by applying a function to the existing event formatter.
128 /// This sets the event formatter that the layer being built will use to record fields.
132 /// Updating an event formatter:
135 /// let layer = tracing_subscriber::fmt::layer()
136 /// .map_event_format(|e| e.compact());
137 /// # // this is necessary for type inference.
138 /// # use tracing_subscriber::Layer as _;
139 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
141 pub fn map_event_format
<E2
>(self, f
: impl FnOnce(E
) -> E2
) -> Layer
<S
, N
, E2
, W
>
143 E2
: FormatEvent
<S
, N
> + '
static,
146 fmt_fields
: self.fmt_fields
,
147 fmt_event
: f(self.fmt_event
),
148 fmt_span
: self.fmt_span
,
149 make_writer
: self.make_writer
,
150 is_ansi
: self.is_ansi
,
156 // This needs to be a seperate impl block because they place different bounds on the type parameters.
157 impl<S
, N
, E
, W
> Layer
<S
, N
, E
, W
> {
158 /// Sets the [`MakeWriter`] that the layer being built will use to write events.
162 /// Using `stderr` rather than `stdout`:
166 /// use tracing_subscriber::fmt;
168 /// let layer = fmt::layer()
169 /// .with_writer(io::stderr);
170 /// # // this is necessary for type inference.
171 /// # use tracing_subscriber::Layer as _;
172 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
174 pub fn with_writer
<W2
>(self, make_writer
: W2
) -> Layer
<S
, N
, E
, W2
>
176 W2
: for<'writer
> MakeWriter
<'writer
> + '
static,
179 fmt_fields
: self.fmt_fields
,
180 fmt_event
: self.fmt_event
,
181 fmt_span
: self.fmt_span
,
182 is_ansi
: self.is_ansi
,
188 /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in
191 /// See [`TestWriter`] for additional details.
195 /// Using [`TestWriter`] to let `cargo test` capture test output:
199 /// use tracing_subscriber::fmt;
201 /// let layer = fmt::layer()
202 /// .with_test_writer();
203 /// # // this is necessary for type inference.
204 /// # use tracing_subscriber::Layer as _;
205 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
208 /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
209 /// [`TestWriter`]: writer/struct.TestWriter.html
210 pub fn with_test_writer(self) -> Layer
<S
, N
, E
, TestWriter
> {
212 fmt_fields
: self.fmt_fields
,
213 fmt_event
: self.fmt_event
,
214 fmt_span
: self.fmt_span
,
215 is_ansi
: self.is_ansi
,
216 make_writer
: TestWriter
::default(),
221 /// Enable ANSI terminal colors for formatted output.
222 #[cfg(feature = "ansi")]
223 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
224 pub fn with_ansi(self, ansi
: bool
) -> Self {
231 /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`].
233 /// This sets the [`MakeWriter`] that the layer being built will use to write events.
237 /// Redirect output to stderr if level is <= WARN:
240 /// use tracing::Level;
241 /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt};
243 /// let stderr = std::io::stderr.with_max_level(Level::WARN);
244 /// let layer = fmt::layer()
245 /// .map_writer(move |w| stderr.or_else(w));
246 /// # // this is necessary for type inference.
247 /// # use tracing_subscriber::Layer as _;
248 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
250 pub fn map_writer
<W2
>(self, f
: impl FnOnce(W
) -> W2
) -> Layer
<S
, N
, E
, W2
>
252 W2
: for<'writer
> MakeWriter
<'writer
> + '
static,
255 fmt_fields
: self.fmt_fields
,
256 fmt_event
: self.fmt_event
,
257 fmt_span
: self.fmt_span
,
258 is_ansi
: self.is_ansi
,
259 make_writer
: f(self.make_writer
),
265 impl<S
, N
, L
, T
, W
> Layer
<S
, N
, format
::Format
<L
, T
>, W
>
267 N
: for<'writer
> FormatFields
<'writer
> + '
static,
269 /// Use the given [`timer`] for span and event timestamps.
271 /// See the [`time` module] for the provided timer implementations.
273 /// Note that using the `"time`"" feature flag enables the
274 /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the
275 /// [`time` crate] to provide more sophisticated timestamp formatting
278 /// [`timer`]: super::time::FormatTime
279 /// [`time` module]: mod@super::time
280 /// [`UtcTime`]: super::time::UtcTime
281 /// [`LocalTime`]: super::time::LocalTime
282 /// [`time` crate]: https://docs.rs/time/0.3
283 pub fn with_timer
<T2
>(self, timer
: T2
) -> Layer
<S
, N
, format
::Format
<L
, T2
>, W
> {
285 fmt_event
: self.fmt_event
.with_timer(timer
),
286 fmt_fields
: self.fmt_fields
,
287 fmt_span
: self.fmt_span
,
288 make_writer
: self.make_writer
,
289 is_ansi
: self.is_ansi
,
294 /// Do not emit timestamps with spans and event.
295 pub fn without_time(self) -> Layer
<S
, N
, format
::Format
<L
, ()>, W
> {
297 fmt_event
: self.fmt_event
.without_time(),
298 fmt_fields
: self.fmt_fields
,
299 fmt_span
: self.fmt_span
.without_time(),
300 make_writer
: self.make_writer
,
301 is_ansi
: self.is_ansi
,
306 /// Configures how synthesized events are emitted at points in the [span
307 /// lifecycle][lifecycle].
309 /// The following options are available:
311 /// - `FmtSpan::NONE`: No events will be synthesized when spans are
312 /// created, entered, exited, or closed. Data from spans will still be
313 /// included as the context for formatted events. This is the default.
314 /// - `FmtSpan::NEW`: An event will be synthesized when spans are created.
315 /// - `FmtSpan::ENTER`: An event will be synthesized when spans are entered.
316 /// - `FmtSpan::EXIT`: An event will be synthesized when spans are exited.
317 /// - `FmtSpan::CLOSE`: An event will be synthesized when a span closes. If
318 /// [timestamps are enabled][time] for this formatter, the generated
319 /// event will contain fields with the span's _busy time_ (the total
320 /// time for which it was entered) and _idle time_ (the total time that
321 /// the span existed but was not entered).
322 /// - `FmtSpan::ACTIVE`: Events will be synthesized when spans are entered
324 /// - `FmtSpan::FULL`: Events will be synthesized whenever a span is
325 /// created, entered, exited, or closed. If timestamps are enabled, the
326 /// close event will contain the span's busy and idle time, as
329 /// The options can be enabled in any combination. For instance, the following
330 /// will synthesize events whenever spans are created and closed:
333 /// use tracing_subscriber::fmt;
334 /// use tracing_subscriber::fmt::format::FmtSpan;
336 /// let subscriber = fmt()
337 /// .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
341 /// Note that the generated events will only be part of the log output by
342 /// this formatter; they will not be recorded by other `Subscriber`s or by
343 /// `Layer`s added to this subscriber.
345 /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
346 /// [time]: #method.without_time
347 pub fn with_span_events(self, kind
: FmtSpan
) -> Self {
349 fmt_span
: self.fmt_span
.with_kind(kind
),
354 /// Sets whether or not an event's target is displayed.
355 pub fn with_target(self, display_target
: bool
) -> Layer
<S
, N
, format
::Format
<L
, T
>, W
> {
357 fmt_event
: self.fmt_event
.with_target(display_target
),
361 /// Sets whether or not an event's [source code file path][file] is
364 /// [file]: tracing_core::Metadata::file
365 pub fn with_file(self, display_filename
: bool
) -> Layer
<S
, N
, format
::Format
<L
, T
>, W
> {
367 fmt_event
: self.fmt_event
.with_file(display_filename
),
372 /// Sets whether or not an event's [source code line number][line] is
375 /// [line]: tracing_core::Metadata::line
376 pub fn with_line_number(
378 display_line_number
: bool
,
379 ) -> Layer
<S
, N
, format
::Format
<L
, T
>, W
> {
381 fmt_event
: self.fmt_event
.with_line_number(display_line_number
),
386 /// Sets whether or not an event's level is displayed.
387 pub fn with_level(self, display_level
: bool
) -> Layer
<S
, N
, format
::Format
<L
, T
>, W
> {
389 fmt_event
: self.fmt_event
.with_level(display_level
),
394 /// Sets whether or not the [thread ID] of the current thread is displayed
395 /// when formatting events
397 /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
398 pub fn with_thread_ids(self, display_thread_ids
: bool
) -> Layer
<S
, N
, format
::Format
<L
, T
>, W
> {
400 fmt_event
: self.fmt_event
.with_thread_ids(display_thread_ids
),
405 /// Sets whether or not the [name] of the current thread is displayed
406 /// when formatting events
408 /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
409 pub fn with_thread_names(
411 display_thread_names
: bool
,
412 ) -> Layer
<S
, N
, format
::Format
<L
, T
>, W
> {
414 fmt_event
: self.fmt_event
.with_thread_names(display_thread_names
),
419 /// Sets the layer being built to use a [less verbose formatter](../fmt/format/struct.Compact.html).
420 pub fn compact(self) -> Layer
<S
, N
, format
::Format
<format
::Compact
, T
>, W
>
422 N
: for<'writer
> FormatFields
<'writer
> + '
static,
425 fmt_event
: self.fmt_event
.compact(),
426 fmt_fields
: self.fmt_fields
,
427 fmt_span
: self.fmt_span
,
428 make_writer
: self.make_writer
,
429 is_ansi
: self.is_ansi
,
434 /// Sets the layer being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty).
435 #[cfg(feature = "ansi")]
436 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
437 pub fn pretty(self) -> Layer
<S
, format
::Pretty
, format
::Format
<format
::Pretty
, T
>, W
> {
439 fmt_event
: self.fmt_event
.pretty(),
440 fmt_fields
: format
::Pretty
::default(),
441 fmt_span
: self.fmt_span
,
442 make_writer
: self.make_writer
,
443 is_ansi
: self.is_ansi
,
448 /// Sets the layer being built to use a [JSON formatter](../fmt/format/struct.Json.html).
450 /// The full format includes fields from all entered spans.
455 /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate","fields":{"message":"some message", "key": "value"}}
460 /// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root
463 /// [`Layer::flatten_event`]: #method.flatten_event
464 #[cfg(feature = "json")]
465 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
466 pub fn json(self) -> Layer
<S
, format
::JsonFields
, format
::Format
<format
::Json
, T
>, W
> {
468 fmt_event
: self.fmt_event
.json(),
469 fmt_fields
: format
::JsonFields
::new(),
470 fmt_span
: self.fmt_span
,
471 make_writer
: self.make_writer
,
472 // always disable ANSI escapes in JSON mode!
479 #[cfg(feature = "json")]
480 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
481 impl<S
, T
, W
> Layer
<S
, format
::JsonFields
, format
::Format
<format
::Json
, T
>, W
> {
482 /// Sets the JSON layer being built to flatten event metadata.
484 /// See [`format::Json`](../fmt/format/struct.Json.html)
485 pub fn flatten_event(
488 ) -> Layer
<S
, format
::JsonFields
, format
::Format
<format
::Json
, T
>, W
> {
490 fmt_event
: self.fmt_event
.flatten_event(flatten_event
),
491 fmt_fields
: format
::JsonFields
::new(),
496 /// Sets whether or not the formatter will include the current span in
497 /// formatted events.
499 /// See [`format::Json`](../fmt/format/struct.Json.html)
500 pub fn with_current_span(
502 display_current_span
: bool
,
503 ) -> Layer
<S
, format
::JsonFields
, format
::Format
<format
::Json
, T
>, W
> {
505 fmt_event
: self.fmt_event
.with_current_span(display_current_span
),
506 fmt_fields
: format
::JsonFields
::new(),
511 /// Sets whether or not the formatter will include a list (from root to leaf)
512 /// of all currently entered spans in formatted events.
514 /// See [`format::Json`](../fmt/format/struct.Json.html)
515 pub fn with_span_list(
517 display_span_list
: bool
,
518 ) -> Layer
<S
, format
::JsonFields
, format
::Format
<format
::Json
, T
>, W
> {
520 fmt_event
: self.fmt_event
.with_span_list(display_span_list
),
521 fmt_fields
: format
::JsonFields
::new(),
527 impl<S
, N
, E
, W
> Layer
<S
, N
, E
, W
> {
528 /// Sets the field formatter that the layer being built will use to record
530 pub fn fmt_fields
<N2
>(self, fmt_fields
: N2
) -> Layer
<S
, N2
, E
, W
>
532 N2
: for<'writer
> FormatFields
<'writer
> + '
static,
535 fmt_event
: self.fmt_event
,
537 fmt_span
: self.fmt_span
,
538 make_writer
: self.make_writer
,
539 is_ansi
: self.is_ansi
,
544 /// Updates the field formatter by applying a function to the existing field formatter.
546 /// This sets the field formatter that the layer being built will use to record fields.
550 /// Updating a field formatter:
553 /// use tracing_subscriber::field::MakeExt;
554 /// let layer = tracing_subscriber::fmt::layer()
555 /// .map_fmt_fields(|f| f.debug_alt());
556 /// # // this is necessary for type inference.
557 /// # use tracing_subscriber::Layer as _;
558 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
560 pub fn map_fmt_fields
<N2
>(self, f
: impl FnOnce(N
) -> N2
) -> Layer
<S
, N2
, E
, W
>
562 N2
: for<'writer
> FormatFields
<'writer
> + '
static,
565 fmt_event
: self.fmt_event
,
566 fmt_fields
: f(self.fmt_fields
),
567 fmt_span
: self.fmt_span
,
568 make_writer
: self.make_writer
,
569 is_ansi
: self.is_ansi
,
575 impl<S
> Default
for Layer
<S
> {
576 fn default() -> Self {
578 fmt_fields
: format
::DefaultFields
::default(),
579 fmt_event
: format
::Format
::default(),
580 fmt_span
: format
::FmtSpanConfig
::default(),
581 make_writer
: io
::stdout
,
582 is_ansi
: cfg
!(feature
= "ansi"),
588 impl<S
, N
, E
, W
> Layer
<S
, N
, E
, W
>
590 S
: Subscriber
+ for<'a
> LookupSpan
<'a
>,
591 N
: for<'writer
> FormatFields
<'writer
> + '
static,
592 E
: FormatEvent
<S
, N
> + '
static,
593 W
: for<'writer
> MakeWriter
<'writer
> + '
static,
596 fn make_ctx
<'a
>(&'a
self, ctx
: Context
<'a
, S
>, event
: &'a Event
<'a
>) -> FmtContext
<'a
, S
, N
> {
599 fmt_fields
: &self.fmt_fields
,
605 /// A formatted representation of a span's fields stored in its [extensions].
607 /// Because `FormattedFields` is generic over the type of the formatter that
608 /// produced it, multiple versions of a span's formatted fields can be stored in
609 /// the [`Extensions`][extensions] type-map. This means that when multiple
610 /// formatters are in use, each can store its own formatted representation
611 /// without conflicting.
613 /// [extensions]: ../registry/struct.Extensions.html
615 pub struct FormattedFields
<E
: ?Sized
> {
616 _format_fields
: PhantomData
<fn(E
)>,
618 /// The formatted fields of a span.
622 impl<E
: ?Sized
> FormattedFields
<E
> {
623 /// Returns a new `FormattedFields`.
624 pub fn new(fields
: String
) -> Self {
628 _format_fields
: PhantomData
,
632 /// Returns a new [`format::Writer`] for writing to this `FormattedFields`.
634 /// The returned [`format::Writer`] can be used with the
635 /// [`FormatFields::format_fields`] method.
636 pub fn as_writer(&mut self) -> format
::Writer
<'_
> {
637 format
::Writer
::new(&mut self.fields
).with_ansi(self.was_ansi
)
641 impl<E
: ?Sized
> fmt
::Debug
for FormattedFields
<E
> {
642 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
643 f
.debug_struct("FormattedFields")
644 .field("fields", &self.fields
)
645 .field("formatter", &format_args
!("{}", std
::any
::type_name
::<E
>()))
646 .field("was_ansi", &self.was_ansi
)
651 impl<E
: ?Sized
> fmt
::Display
for FormattedFields
<E
> {
652 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
653 fmt
::Display
::fmt(&self.fields
, f
)
657 impl<E
: ?Sized
> Deref
for FormattedFields
<E
> {
658 type Target
= String
;
659 fn deref(&self) -> &Self::Target
{
664 // === impl FmtLayer ===
666 macro_rules
! with_event_from_span
{
667 ($id
:ident
, $span
:ident
, $
($field
:literal
= $value
:expr
),*, |$event
:ident
| $code
:block
) => {
668 let meta
= $span
.metadata();
669 let cs
= meta
.callsite();
670 let fs
= field
::FieldSet
::new(&[$
($field
),*], cs
);
672 let mut iter
= fs
.iter();
674 (&iter
.next().unwrap(), Some(&$value
as &dyn field
::Value
)),
676 let vs
= fs
.value_set(&v
);
677 let $event
= Event
::new_child_of($id
, meta
, &vs
);
682 impl<S
, N
, E
, W
> layer
::Layer
<S
> for Layer
<S
, N
, E
, W
>
684 S
: Subscriber
+ for<'a
> LookupSpan
<'a
>,
685 N
: for<'writer
> FormatFields
<'writer
> + '
static,
686 E
: FormatEvent
<S
, N
> + '
static,
687 W
: for<'writer
> MakeWriter
<'writer
> + '
static,
689 fn on_new_span(&self, attrs
: &Attributes
<'_
>, id
: &Id
, ctx
: Context
<'_
, S
>) {
690 let span
= ctx
.span(id
).expect("Span not found, this is a bug");
691 let mut extensions
= span
.extensions_mut();
693 if extensions
.get_mut
::<FormattedFields
<N
>>().is_none() {
694 let mut fields
= FormattedFields
::<N
>::new(String
::new());
697 .format_fields(fields
.as_writer().with_ansi(self.is_ansi
), attrs
)
700 fields
.was_ansi
= self.is_ansi
;
701 extensions
.insert(fields
);
705 if self.fmt_span
.fmt_timing
706 && self.fmt_span
.trace_close()
707 && extensions
.get_mut
::<Timings
>().is_none()
709 extensions
.insert(Timings
::new());
712 if self.fmt_span
.trace_new() {
713 with_event_from_span
!(id
, span
, "message" = "new", |event
| {
716 self.on_event(&event
, ctx
);
721 fn on_record(&self, id
: &Id
, values
: &Record
<'_
>, ctx
: Context
<'_
, S
>) {
722 let span
= ctx
.span(id
).expect("Span not found, this is a bug");
723 let mut extensions
= span
.extensions_mut();
724 if let Some(fields
) = extensions
.get_mut
::<FormattedFields
<N
>>() {
725 let _
= self.fmt_fields
.add_fields(fields
, values
);
729 let mut fields
= FormattedFields
::<N
>::new(String
::new());
732 .format_fields(fields
.as_writer().with_ansi(self.is_ansi
), values
)
735 fields
.was_ansi
= self.is_ansi
;
736 extensions
.insert(fields
);
740 fn on_enter(&self, id
: &Id
, ctx
: Context
<'_
, S
>) {
741 if self.fmt_span
.trace_enter() || self.fmt_span
.trace_close() && self.fmt_span
.fmt_timing
{
742 let span
= ctx
.span(id
).expect("Span not found, this is a bug");
743 let mut extensions
= span
.extensions_mut();
744 if let Some(timings
) = extensions
.get_mut
::<Timings
>() {
745 let now
= Instant
::now();
746 timings
.idle
+= (now
- timings
.last
).as_nanos() as u64;
750 if self.fmt_span
.trace_enter() {
751 with_event_from_span
!(id
, span
, "message" = "enter", |event
| {
754 self.on_event(&event
, ctx
);
760 fn on_exit(&self, id
: &Id
, ctx
: Context
<'_
, S
>) {
761 if self.fmt_span
.trace_exit() || self.fmt_span
.trace_close() && self.fmt_span
.fmt_timing
{
762 let span
= ctx
.span(id
).expect("Span not found, this is a bug");
763 let mut extensions
= span
.extensions_mut();
764 if let Some(timings
) = extensions
.get_mut
::<Timings
>() {
765 let now
= Instant
::now();
766 timings
.busy
+= (now
- timings
.last
).as_nanos() as u64;
770 if self.fmt_span
.trace_exit() {
771 with_event_from_span
!(id
, span
, "message" = "exit", |event
| {
774 self.on_event(&event
, ctx
);
780 fn on_close(&self, id
: Id
, ctx
: Context
<'_
, S
>) {
781 if self.fmt_span
.trace_close() {
782 let span
= ctx
.span(&id
).expect("Span not found, this is a bug");
783 let extensions
= span
.extensions();
784 if let Some(timing
) = extensions
.get
::<Timings
>() {
790 idle
+= (Instant
::now() - last
).as_nanos() as u64;
792 let t_idle
= field
::display(TimingDisplay(idle
));
793 let t_busy
= field
::display(TimingDisplay(busy
));
795 with_event_from_span
!(
799 "time.busy" = t_busy
,
800 "time.idle" = t_idle
,
804 self.on_event(&event
, ctx
);
808 with_event_from_span
!(id
, span
, "message" = "close", |event
| {
811 self.on_event(&event
, ctx
);
817 fn on_event(&self, event
: &Event
<'_
>, ctx
: Context
<'_
, S
>) {
819 static BUF
: RefCell
<String
> = RefCell
::new(String
::new());
823 let borrow
= buf
.try_borrow_mut();
826 let mut buf
= match borrow
{
837 let ctx
= self.make_ctx(ctx
, event
);
842 format
::Writer
::new(&mut buf
).with_ansi(self.is_ansi
),
847 let mut writer
= self.make_writer
.make_writer_for(event
.metadata());
848 let _
= io
::Write
::write_all(&mut writer
, buf
.as_bytes());
855 unsafe fn downcast_raw(&self, id
: TypeId
) -> Option
<*const ()> {
856 // This `downcast_raw` impl allows downcasting a `fmt` layer to any of
857 // its components (event formatter, field formatter, and `MakeWriter`)
858 // as well as to the layer's type itself. The potential use-cases for
859 // this *may* be somewhat niche, though...
861 _
if id
== TypeId
::of
::<Self>() => Some(self as *const Self as *const ()),
862 _
if id
== TypeId
::of
::<E
>() => Some(&self.fmt_event
as *const E
as *const ()),
863 _
if id
== TypeId
::of
::<N
>() => Some(&self.fmt_fields
as *const N
as *const ()),
864 _
if id
== TypeId
::of
::<W
>() => Some(&self.make_writer
as *const W
as *const ()),
870 /// Provides the current span context to a formatter.
871 pub struct FmtContext
<'a
, S
, N
> {
872 pub(crate) ctx
: Context
<'a
, S
>,
873 pub(crate) fmt_fields
: &'a N
,
874 pub(crate) event
: &'a Event
<'a
>,
877 impl<'a
, S
, N
> fmt
::Debug
for FmtContext
<'a
, S
, N
> {
878 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
879 f
.debug_struct("FmtContext").finish()
883 impl<'cx
, 'writer
, S
, N
> FormatFields
<'writer
> for FmtContext
<'cx
, S
, N
>
885 S
: Subscriber
+ for<'lookup
> LookupSpan
<'lookup
>,
886 N
: FormatFields
<'writer
> + '
static,
888 fn format_fields
<R
: RecordFields
>(
890 writer
: format
::Writer
<'writer
>,
893 self.fmt_fields
.format_fields(writer
, fields
)
897 impl<'a
, S
, N
> FmtContext
<'a
, S
, N
>
899 S
: Subscriber
+ for<'lookup
> LookupSpan
<'lookup
>,
900 N
: for<'writer
> FormatFields
<'writer
> + '
static,
902 /// Visits every span in the current context with a closure.
904 /// The provided closure will be called first with the current span,
905 /// and then with that span's parent, and then that span's parent,
906 /// and so on until a root span is reached.
907 pub fn visit_spans
<E
, F
>(&self, mut f
: F
) -> Result
<(), E
>
909 F
: FnMut(&SpanRef
<'_
, S
>) -> Result
<(), E
>,
911 // visit all the current spans
912 if let Some(scope
) = self.event_scope() {
913 for span
in scope
.from_root() {
920 /// Returns metadata for the span with the given `id`, if it exists.
922 /// If this returns `None`, then no span exists for that ID (either it has
923 /// closed or the ID is invalid).
925 pub fn metadata(&self, id
: &Id
) -> Option
<&'
static Metadata
<'
static>>
927 S
: for<'lookup
> LookupSpan
<'lookup
>,
929 self.ctx
.metadata(id
)
932 /// Returns [stored data] for the span with the given `id`, if it exists.
934 /// If this returns `None`, then no span exists for that ID (either it has
935 /// closed or the ID is invalid).
937 /// [stored data]: ../registry/struct.SpanRef.html
939 pub fn span(&self, id
: &Id
) -> Option
<SpanRef
<'_
, S
>>
941 S
: for<'lookup
> LookupSpan
<'lookup
>,
946 /// Returns `true` if an active span exists for the given `Id`.
948 pub fn exists(&self, id
: &Id
) -> bool
950 S
: for<'lookup
> LookupSpan
<'lookup
>,
955 /// Returns [stored data] for the span that the wrapped subscriber considers
956 /// to be the current.
958 /// If this returns `None`, then we are not currently within a span.
960 /// [stored data]: ../registry/struct.SpanRef.html
962 pub fn lookup_current(&self) -> Option
<SpanRef
<'_
, S
>>
964 S
: for<'lookup
> LookupSpan
<'lookup
>,
966 self.ctx
.lookup_current()
969 /// Returns the current span for this formatter.
970 pub fn current_span(&self) -> Current
{
971 self.ctx
.current_span()
974 /// Returns [stored data] for the parent span of the event currently being
977 /// If the event has a contextual parent, this will return the current span. If
978 /// the event has an explicit parent span, this will return that span. If
979 /// the event does not have a parent span, this will return `None`.
981 /// [stored data]: SpanRef
982 pub fn parent_span(&self) -> Option
<SpanRef
<'_
, S
>> {
983 self.ctx
.event_span(self.event
)
986 /// Returns an iterator over the [stored data] for all the spans in the
987 /// current context, starting with the specified span and ending with the
988 /// root of the trace tree and ending with the current span.
990 /// This is equivalent to the [`Context::span_scope`] method.
992 /// <div class="information">
993 /// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
995 /// <div class="example-wrap" style="display:inline-block">
996 /// <pre class="ignore" style="white-space:normal;font:inherit;">
997 /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
998 /// returns the spans in reverse order (from leaf to root). Use
999 /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
1000 /// in case root-to-leaf ordering is desired.
1003 /// <div class="example-wrap" style="display:inline-block">
1004 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1005 /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
1006 /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
1007 /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
1008 /// declaration</a> for details.
1011 /// [stored data]: crate::registry::SpanRef
1012 pub fn span_scope(&self, id
: &Id
) -> Option
<registry
::Scope
<'_
, S
>>
1014 S
: for<'lookup
> LookupSpan
<'lookup
>,
1016 self.ctx
.span_scope(id
)
1019 /// Returns an iterator over the [stored data] for all the spans in the
1020 /// event's span context, starting with its parent span and ending with the
1021 /// root of the trace tree.
1023 /// This is equivalent to calling the [`Context::event_scope`] method and
1024 /// passing the event currently being formatted.
1026 /// <div class="example-wrap" style="display:inline-block">
1027 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1028 /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
1029 /// returns the spans in reverse order (from leaf to root). Use
1030 /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
1031 /// in case root-to-leaf ordering is desired.
1034 /// <div class="example-wrap" style="display:inline-block">
1035 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1036 /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
1037 /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
1038 /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
1039 /// declaration</a> for details.
1042 /// [stored data]: crate::registry::SpanRef
1043 pub fn event_scope(&self) -> Option
<registry
::Scope
<'_
, S
>>
1045 S
: for<'lookup
> registry
::LookupSpan
<'lookup
>,
1047 self.ctx
.event_scope(self.event
)
1050 /// Returns the [field formatter] configured by the subscriber invoking
1053 /// The event formatter may use the returned field formatter to format the
1054 /// fields of any events it records.
1056 /// [field formatter]: FormatFields
1057 pub fn field_format(&self) -> &N
{
1073 last
: Instant
::now(),
1083 format
::{self, test::MockTime, Format}
,
1085 test
::{MockMakeWriter, MockWriter}
,
1088 use crate::Registry
;
1089 use format
::FmtSpan
;
1091 use tracing
::subscriber
::with_default
;
1092 use tracing_core
::dispatcher
::Dispatch
;
1096 let f
= Format
::default().with_timer(time
::Uptime
::default());
1097 let fmt
= fmt
::Layer
::default().event_format(f
);
1098 let subscriber
= fmt
.with_subscriber(Registry
::default());
1099 let _dispatch
= Dispatch
::new(subscriber
);
1101 let f
= format
::Format
::default();
1102 let fmt
= fmt
::Layer
::default().event_format(f
);
1103 let subscriber
= fmt
.with_subscriber(Registry
::default());
1104 let _dispatch
= Dispatch
::new(subscriber
);
1106 let f
= format
::Format
::default().compact();
1107 let fmt
= fmt
::Layer
::default().event_format(f
);
1108 let subscriber
= fmt
.with_subscriber(Registry
::default());
1109 let _dispatch
= Dispatch
::new(subscriber
);
1113 fn fmt_layer_downcasts() {
1114 let f
= format
::Format
::default();
1115 let fmt
= fmt
::Layer
::default().event_format(f
);
1116 let subscriber
= fmt
.with_subscriber(Registry
::default());
1118 let dispatch
= Dispatch
::new(subscriber
);
1119 assert
!(dispatch
.downcast_ref
::<fmt
::Layer
<Registry
>>().is_some());
1123 fn fmt_layer_downcasts_to_parts() {
1124 let f
= format
::Format
::default();
1125 let fmt
= fmt
::Layer
::default().event_format(f
);
1126 let subscriber
= fmt
.with_subscriber(Registry
::default());
1127 let dispatch
= Dispatch
::new(subscriber
);
1128 assert
!(dispatch
.downcast_ref
::<format
::DefaultFields
>().is_some());
1129 assert
!(dispatch
.downcast_ref
::<format
::Format
>().is_some())
1133 fn is_lookup_span() {
1134 fn assert_lookup_span
<T
: for<'a
> crate::registry
::LookupSpan
<'a
>>(_
: T
) {}
1135 let fmt
= fmt
::Layer
::default();
1136 let subscriber
= fmt
.with_subscriber(Registry
::default());
1137 assert_lookup_span(subscriber
)
1140 fn sanitize_timings(s
: String
) -> String
{
1141 let re
= Regex
::new("time\\.(idle|busy)=([0-9.]+)[mµn]s").unwrap();
1142 re
.replace_all(s
.as_str(), "timing").to_string()
1146 fn synthesize_span_none() {
1147 let make_writer
= MockMakeWriter
::default();
1148 let subscriber
= crate::fmt
::Subscriber
::builder()
1149 .with_writer(make_writer
.clone())
1152 .with_timer(MockTime
)
1153 // check that FmtSpan::NONE is the default
1156 with_default(subscriber
, || {
1157 let span1
= tracing
::info_span
!("span1", x
= 42);
1158 let _e
= span1
.enter();
1160 let actual
= sanitize_timings(make_writer
.get_string());
1161 assert_eq
!("", actual
.as_str());
1165 fn synthesize_span_active() {
1166 let make_writer
= MockMakeWriter
::default();
1167 let subscriber
= crate::fmt
::Subscriber
::builder()
1168 .with_writer(make_writer
.clone())
1171 .with_timer(MockTime
)
1172 .with_span_events(FmtSpan
::ACTIVE
)
1175 with_default(subscriber
, || {
1176 let span1
= tracing
::info_span
!("span1", x
= 42);
1177 let _e
= span1
.enter();
1179 let actual
= sanitize_timings(make_writer
.get_string());
1181 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter\n\
1182 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit\n",
1188 fn synthesize_span_close() {
1189 let make_writer
= MockMakeWriter
::default();
1190 let subscriber
= crate::fmt
::Subscriber
::builder()
1191 .with_writer(make_writer
.clone())
1194 .with_timer(MockTime
)
1195 .with_span_events(FmtSpan
::CLOSE
)
1198 with_default(subscriber
, || {
1199 let span1
= tracing
::info_span
!("span1", x
= 42);
1200 let _e
= span1
.enter();
1202 let actual
= sanitize_timings(make_writer
.get_string());
1204 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing\n",
1210 fn synthesize_span_close_no_timing() {
1211 let make_writer
= MockMakeWriter
::default();
1212 let subscriber
= crate::fmt
::Subscriber
::builder()
1213 .with_writer(make_writer
.clone())
1216 .with_timer(MockTime
)
1218 .with_span_events(FmtSpan
::CLOSE
)
1221 with_default(subscriber
, || {
1222 let span1
= tracing
::info_span
!("span1", x
= 42);
1223 let _e
= span1
.enter();
1225 let actual
= sanitize_timings(make_writer
.get_string());
1227 "span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close\n",
1233 fn synthesize_span_full() {
1234 let make_writer
= MockMakeWriter
::default();
1235 let subscriber
= crate::fmt
::Subscriber
::builder()
1236 .with_writer(make_writer
.clone())
1239 .with_timer(MockTime
)
1240 .with_span_events(FmtSpan
::FULL
)
1243 with_default(subscriber
, || {
1244 let span1
= tracing
::info_span
!("span1", x
= 42);
1245 let _e
= span1
.enter();
1247 let actual
= sanitize_timings(make_writer
.get_string());
1249 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: new\n\
1250 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter\n\
1251 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit\n\
1252 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing\n",
1258 fn make_writer_based_on_meta() {
1259 struct MakeByTarget
{
1260 make_writer1
: MockMakeWriter
,
1261 make_writer2
: MockMakeWriter
,
1264 impl<'a
> MakeWriter
<'a
> for MakeByTarget
{
1265 type Writer
= MockWriter
;
1267 fn make_writer(&'a
self) -> Self::Writer
{
1268 self.make_writer1
.make_writer()
1271 fn make_writer_for(&'a
self, meta
: &Metadata
<'_
>) -> Self::Writer
{
1272 if meta
.target() == "writer2" {
1273 return self.make_writer2
.make_writer();
1279 let make_writer1
= MockMakeWriter
::default();
1280 let make_writer2
= MockMakeWriter
::default();
1282 let make_writer
= MakeByTarget
{
1283 make_writer1
: make_writer1
.clone(),
1284 make_writer2
: make_writer2
.clone(),
1287 let subscriber
= crate::fmt
::Subscriber
::builder()
1288 .with_writer(make_writer
)
1292 .with_timer(MockTime
)
1293 .with_span_events(FmtSpan
::CLOSE
)
1296 with_default(subscriber
, || {
1297 let span1
= tracing
::info_span
!("writer1_span", x
= 42);
1298 let _e
= span1
.enter();
1299 tracing
::info
!(target
: "writer2", "hello writer2!");
1300 let span2
= tracing
::info_span
!(target
: "writer2", "writer2_span");
1301 let _e
= span2
.enter();
1302 tracing
::warn
!(target
: "writer1", "hello writer1!");
1305 let actual
= sanitize_timings(make_writer1
.get_string());
1307 "fake time writer1_span{x=42}:writer2_span: hello writer1!\n\
1308 fake time writer1_span{x=42}: close timing timing\n",
1311 let actual
= sanitize_timings(make_writer2
.get_string());
1313 "fake time writer1_span{x=42}: hello writer2!\n\
1314 fake time writer1_span{x=42}:writer2_span: close timing timing\n",