1use crate::{
2 field::RecordFields,
3 fmt::{format, FormatEvent, FormatFields, MakeWriter, TestWriter},
4 layer::{self, Context},
5 registry::{self, LookupSpan, SpanRef},
6};
7use format::{FmtSpan, TimingDisplay};
8use std::{
9 any::TypeId, cell::RefCell, env, fmt, io, marker::PhantomData, ops::Deref, time::Instant,
10};
11use tracing_core::{
12 field,
13 span::{Attributes, Current, Id, Record},
14 Event, Metadata, Subscriber,
15};
16
17/// A [`Layer`] that logs formatted representations of `tracing` events.
18///
19/// ## Examples
20///
21/// Constructing a layer with the default configuration:
22///
23/// ```rust
24/// use tracing_subscriber::{fmt, Registry};
25/// use tracing_subscriber::prelude::*;
26///
27/// let subscriber = Registry::default()
28/// .with(fmt::Layer::default());
29///
30/// tracing::subscriber::set_global_default(subscriber).unwrap();
31/// ```
32///
33/// Overriding the layer's behavior:
34///
35/// ```rust
36/// use tracing_subscriber::{fmt, Registry};
37/// use tracing_subscriber::prelude::*;
38///
39/// let fmt_layer = fmt::layer()
40/// .with_target(false) // don't include event targets when logging
41/// .with_level(false); // don't include event levels when logging
42///
43/// let subscriber = Registry::default().with(fmt_layer);
44/// # tracing::subscriber::set_global_default(subscriber).unwrap();
45/// ```
46///
47/// Setting a custom event formatter:
48///
49/// ```rust
50/// use tracing_subscriber::fmt::{self, format, time};
51/// use tracing_subscriber::prelude::*;
52///
53/// let fmt = format().with_timer(time::Uptime::default());
54/// let fmt_layer = fmt::layer()
55/// .event_format(fmt)
56/// .with_target(false);
57/// # let subscriber = fmt_layer.with_subscriber(tracing_subscriber::registry::Registry::default());
58/// # tracing::subscriber::set_global_default(subscriber).unwrap();
59/// ```
60///
61/// [`Layer`]: super::layer::Layer
62#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
63#[derive(Debug)]
64pub struct Layer<
65 S,
66 N = format::DefaultFields,
67 E = format::Format<format::Full>,
68 W = fn() -> io::Stdout,
69> {
70 make_writer: W,
71 fmt_fields: N,
72 fmt_event: E,
73 fmt_span: format::FmtSpanConfig,
74 is_ansi: bool,
75 log_internal_errors: bool,
76 _inner: PhantomData<fn(S)>,
77}
78
79impl<S> Layer<S> {
80 /// Returns a new [`Layer`][self::Layer] with the default configuration.
81 pub fn new() -> Self {
82 Self::default()
83 }
84}
85
86// This needs to be a seperate impl block because they place different bounds on the type parameters.
87impl<S, N, E, W> Layer<S, N, E, W>
88where
89 S: Subscriber + for<'a> LookupSpan<'a>,
90 N: for<'writer> FormatFields<'writer> + 'static,
91 W: for<'writer> MakeWriter<'writer> + 'static,
92{
93 /// Sets the [event formatter][`FormatEvent`] that the layer being built will
94 /// use to format events.
95 ///
96 /// The event formatter may be any type implementing the [`FormatEvent`]
97 /// trait, which is implemented for all functions taking a [`FmtContext`], a
98 /// [`Writer`], and an [`Event`].
99 ///
100 /// # Examples
101 ///
102 /// Setting a type implementing [`FormatEvent`] as the formatter:
103 /// ```rust
104 /// use tracing_subscriber::fmt::{self, format};
105 ///
106 /// let layer = fmt::layer()
107 /// .event_format(format().compact());
108 /// # // this is necessary for type inference.
109 /// # use tracing_subscriber::Layer as _;
110 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
111 /// ```
112 /// [`FormatEvent`]: format::FormatEvent
113 /// [`Event`]: tracing::Event
114 /// [`Writer`]: format::Writer
115 pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W>
116 where
117 E2: FormatEvent<S, N> + 'static,
118 {
119 Layer {
120 fmt_fields: self.fmt_fields,
121 fmt_event: e,
122 fmt_span: self.fmt_span,
123 make_writer: self.make_writer,
124 is_ansi: self.is_ansi,
125 log_internal_errors: self.log_internal_errors,
126 _inner: self._inner,
127 }
128 }
129
130 /// Updates the event formatter by applying a function to the existing event formatter.
131 ///
132 /// This sets the event formatter that the layer being built will use to record fields.
133 ///
134 /// # Examples
135 ///
136 /// Updating an event formatter:
137 ///
138 /// ```rust
139 /// let layer = tracing_subscriber::fmt::layer()
140 /// .map_event_format(|e| e.compact());
141 /// # // this is necessary for type inference.
142 /// # use tracing_subscriber::Layer as _;
143 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
144 /// ```
145 pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> Layer<S, N, E2, W>
146 where
147 E2: FormatEvent<S, N> + 'static,
148 {
149 Layer {
150 fmt_fields: self.fmt_fields,
151 fmt_event: f(self.fmt_event),
152 fmt_span: self.fmt_span,
153 make_writer: self.make_writer,
154 is_ansi: self.is_ansi,
155 log_internal_errors: self.log_internal_errors,
156 _inner: self._inner,
157 }
158 }
159}
160
161// This needs to be a seperate impl block because they place different bounds on the type parameters.
162impl<S, N, E, W> Layer<S, N, E, W> {
163 /// Sets the [`MakeWriter`] that the layer being built will use to write events.
164 ///
165 /// # Examples
166 ///
167 /// Using `stderr` rather than `stdout`:
168 ///
169 /// ```rust
170 /// use std::io;
171 /// use tracing_subscriber::fmt;
172 ///
173 /// let layer = fmt::layer()
174 /// .with_writer(io::stderr);
175 /// # // this is necessary for type inference.
176 /// # use tracing_subscriber::Layer as _;
177 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
178 /// ```
179 pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, N, E, W2>
180 where
181 W2: for<'writer> MakeWriter<'writer> + 'static,
182 {
183 Layer {
184 fmt_fields: self.fmt_fields,
185 fmt_event: self.fmt_event,
186 fmt_span: self.fmt_span,
187 is_ansi: self.is_ansi,
188 log_internal_errors: self.log_internal_errors,
189 make_writer,
190 _inner: self._inner,
191 }
192 }
193
194 /// Borrows the [writer] for this [`Layer`].
195 ///
196 /// [writer]: MakeWriter
197 pub fn writer(&self) -> &W {
198 &self.make_writer
199 }
200
201 /// Mutably borrows the [writer] for this [`Layer`].
202 ///
203 /// This method is primarily expected to be used with the
204 /// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
205 ///
206 /// # Examples
207 ///
208 /// ```
209 /// # use tracing::info;
210 /// # use tracing_subscriber::{fmt,reload,Registry,prelude::*};
211 /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) {
212 /// # std::io::stdout
213 /// # }
214 /// # fn main() {
215 /// let layer = fmt::layer().with_writer(non_blocking(std::io::stderr()));
216 /// let (layer, reload_handle) = reload::Layer::new(layer);
217 /// #
218 /// # // specifying the Registry type is required
219 /// # let _: &reload::Handle<fmt::Layer<Registry, _, _, _>, Registry> = &reload_handle;
220 /// #
221 /// info!("This will be logged to stderr");
222 /// reload_handle.modify(|layer| *layer.writer_mut() = non_blocking(std::io::stdout()));
223 /// info!("This will be logged to stdout");
224 /// # }
225 /// ```
226 ///
227 /// [writer]: MakeWriter
228 pub fn writer_mut(&mut self) -> &mut W {
229 &mut self.make_writer
230 }
231
232 /// Sets whether this layer should use ANSI terminal formatting
233 /// escape codes (such as colors).
234 ///
235 /// This method is primarily expected to be used with the
236 /// [`reload::Handle::modify`](crate::reload::Handle::modify) method when changing
237 /// the writer.
238 #[cfg(feature = "ansi")]
239 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
240 pub fn set_ansi(&mut self, ansi: bool) {
241 self.is_ansi = ansi;
242 }
243
244 /// Configures the layer to support [`libtest`'s output capturing][capturing] when used in
245 /// unit tests.
246 ///
247 /// See [`TestWriter`] for additional details.
248 ///
249 /// # Examples
250 ///
251 /// Using [`TestWriter`] to let `cargo test` capture test output:
252 ///
253 /// ```rust
254 /// use std::io;
255 /// use tracing_subscriber::fmt;
256 ///
257 /// let layer = fmt::layer()
258 /// .with_test_writer();
259 /// # // this is necessary for type inference.
260 /// # use tracing_subscriber::Layer as _;
261 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
262 /// ```
263 /// [capturing]:
264 /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
265 /// [`TestWriter`]: super::writer::TestWriter
266 pub fn with_test_writer(self) -> Layer<S, N, E, TestWriter> {
267 Layer {
268 fmt_fields: self.fmt_fields,
269 fmt_event: self.fmt_event,
270 fmt_span: self.fmt_span,
271 is_ansi: self.is_ansi,
272 log_internal_errors: self.log_internal_errors,
273 make_writer: TestWriter::default(),
274 _inner: self._inner,
275 }
276 }
277
278 /// Sets whether or not the formatter emits ANSI terminal escape codes
279 /// for colors and other text formatting.
280 ///
281 /// When the "ansi" crate feature flag is enabled, ANSI colors are enabled
282 /// by default unless the [`NO_COLOR`] environment variable is set to
283 /// a non-empty value. If the [`NO_COLOR`] environment variable is set to
284 /// any non-empty value, then ANSI colors will be suppressed by default.
285 /// The [`with_ansi`] and [`set_ansi`] methods can be used to forcibly
286 /// enable ANSI colors, overriding any [`NO_COLOR`] environment variable.
287 ///
288 /// [`NO_COLOR`]: https://no-color.org/
289 ///
290 /// Enabling ANSI escapes (calling `with_ansi(true)`) requires the "ansi"
291 /// crate feature flag. Calling `with_ansi(true)` without the "ansi"
292 /// feature flag enabled will panic if debug assertions are enabled, or
293 /// print a warning otherwise.
294 ///
295 /// This method itself is still available without the feature flag. This
296 /// is to allow ANSI escape codes to be explicitly *disabled* without
297 /// having to opt-in to the dependencies required to emit ANSI formatting.
298 /// This way, code which constructs a formatter that should never emit
299 /// ANSI escape codes can ensure that they are not used, regardless of
300 /// whether or not other crates in the dependency graph enable the "ansi"
301 /// feature flag.
302 ///
303 /// [`with_ansi`]: Subscriber::with_ansi
304 /// [`set_ansi`]: Subscriber::set_ansi
305 pub fn with_ansi(self, ansi: bool) -> Self {
306 #[cfg(not(feature = "ansi"))]
307 if ansi {
308 const ERROR: &str =
309 "tracing-subscriber: the `ansi` crate feature is required to enable ANSI terminal colors";
310 #[cfg(debug_assertions)]
311 panic!("{}", ERROR);
312 #[cfg(not(debug_assertions))]
313 eprintln!("{}", ERROR);
314 }
315
316 Self {
317 is_ansi: ansi,
318 ..self
319 }
320 }
321
322 /// Sets whether to write errors from [`FormatEvent`] to the writer.
323 /// Defaults to true.
324 ///
325 /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to
326 /// the writer. These errors are unlikely and will only occur if there is a
327 /// bug in the `FormatEvent` implementation or its dependencies.
328 ///
329 /// If writing to the writer fails, the error message is printed to stderr
330 /// as a fallback.
331 ///
332 /// [`FormatEvent`]: crate::fmt::FormatEvent
333 pub fn log_internal_errors(self, log_internal_errors: bool) -> Self {
334 Self {
335 log_internal_errors,
336 ..self
337 }
338 }
339
340 /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`].
341 ///
342 /// This sets the [`MakeWriter`] that the layer being built will use to write events.
343 ///
344 /// # Examples
345 ///
346 /// Redirect output to stderr if level is <= WARN:
347 ///
348 /// ```rust
349 /// use tracing::Level;
350 /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt};
351 ///
352 /// let stderr = std::io::stderr.with_max_level(Level::WARN);
353 /// let layer = fmt::layer()
354 /// .map_writer(move |w| stderr.or_else(w));
355 /// # // this is necessary for type inference.
356 /// # use tracing_subscriber::Layer as _;
357 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
358 /// ```
359 pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> Layer<S, N, E, W2>
360 where
361 W2: for<'writer> MakeWriter<'writer> + 'static,
362 {
363 Layer {
364 fmt_fields: self.fmt_fields,
365 fmt_event: self.fmt_event,
366 fmt_span: self.fmt_span,
367 is_ansi: self.is_ansi,
368 log_internal_errors: self.log_internal_errors,
369 make_writer: f(self.make_writer),
370 _inner: self._inner,
371 }
372 }
373}
374
375impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W>
376where
377 N: for<'writer> FormatFields<'writer> + 'static,
378{
379 /// Use the given [`timer`] for span and event timestamps.
380 ///
381 /// See the [`time` module] for the provided timer implementations.
382 ///
383 /// Note that using the `"time`"" feature flag enables the
384 /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the
385 /// [`time` crate] to provide more sophisticated timestamp formatting
386 /// options.
387 ///
388 /// [`timer`]: super::time::FormatTime
389 /// [`time` module]: mod@super::time
390 /// [`UtcTime`]: super::time::UtcTime
391 /// [`LocalTime`]: super::time::LocalTime
392 /// [`time` crate]: https://docs.rs/time/0.3
393 pub fn with_timer<T2>(self, timer: T2) -> Layer<S, N, format::Format<L, T2>, W> {
394 Layer {
395 fmt_event: self.fmt_event.with_timer(timer),
396 fmt_fields: self.fmt_fields,
397 fmt_span: self.fmt_span,
398 make_writer: self.make_writer,
399 is_ansi: self.is_ansi,
400 log_internal_errors: self.log_internal_errors,
401 _inner: self._inner,
402 }
403 }
404
405 /// Do not emit timestamps with spans and event.
406 pub fn without_time(self) -> Layer<S, N, format::Format<L, ()>, W> {
407 Layer {
408 fmt_event: self.fmt_event.without_time(),
409 fmt_fields: self.fmt_fields,
410 fmt_span: self.fmt_span.without_time(),
411 make_writer: self.make_writer,
412 is_ansi: self.is_ansi,
413 log_internal_errors: self.log_internal_errors,
414 _inner: self._inner,
415 }
416 }
417
418 /// Configures how synthesized events are emitted at points in the [span
419 /// lifecycle][lifecycle].
420 ///
421 /// The following options are available:
422 ///
423 /// - `FmtSpan::NONE`: No events will be synthesized when spans are
424 /// created, entered, exited, or closed. Data from spans will still be
425 /// included as the context for formatted events. This is the default.
426 /// - `FmtSpan::NEW`: An event will be synthesized when spans are created.
427 /// - `FmtSpan::ENTER`: An event will be synthesized when spans are entered.
428 /// - `FmtSpan::EXIT`: An event will be synthesized when spans are exited.
429 /// - `FmtSpan::CLOSE`: An event will be synthesized when a span closes. If
430 /// [timestamps are enabled][time] for this formatter, the generated
431 /// event will contain fields with the span's _busy time_ (the total
432 /// time for which it was entered) and _idle time_ (the total time that
433 /// the span existed but was not entered).
434 /// - `FmtSpan::ACTIVE`: Events will be synthesized when spans are entered
435 /// or exited.
436 /// - `FmtSpan::FULL`: Events will be synthesized whenever a span is
437 /// created, entered, exited, or closed. If timestamps are enabled, the
438 /// close event will contain the span's busy and idle time, as
439 /// described above.
440 ///
441 /// The options can be enabled in any combination. For instance, the following
442 /// will synthesize events whenever spans are created and closed:
443 ///
444 /// ```rust
445 /// use tracing_subscriber::fmt;
446 /// use tracing_subscriber::fmt::format::FmtSpan;
447 ///
448 /// let subscriber = fmt()
449 /// .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
450 /// .finish();
451 /// ```
452 ///
453 /// Note that the generated events will only be part of the log output by
454 /// this formatter; they will not be recorded by other `Subscriber`s or by
455 /// `Layer`s added to this subscriber.
456 ///
457 /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
458 /// [time]: Layer::without_time()
459 pub fn with_span_events(self, kind: FmtSpan) -> Self {
460 Layer {
461 fmt_span: self.fmt_span.with_kind(kind),
462 ..self
463 }
464 }
465
466 /// Sets whether or not an event's target is displayed.
467 pub fn with_target(self, display_target: bool) -> Layer<S, N, format::Format<L, T>, W> {
468 Layer {
469 fmt_event: self.fmt_event.with_target(display_target),
470 ..self
471 }
472 }
473 /// Sets whether or not an event's [source code file path][file] is
474 /// displayed.
475 ///
476 /// [file]: tracing_core::Metadata::file
477 pub fn with_file(self, display_filename: bool) -> Layer<S, N, format::Format<L, T>, W> {
478 Layer {
479 fmt_event: self.fmt_event.with_file(display_filename),
480 ..self
481 }
482 }
483
484 /// Sets whether or not an event's [source code line number][line] is
485 /// displayed.
486 ///
487 /// [line]: tracing_core::Metadata::line
488 pub fn with_line_number(
489 self,
490 display_line_number: bool,
491 ) -> Layer<S, N, format::Format<L, T>, W> {
492 Layer {
493 fmt_event: self.fmt_event.with_line_number(display_line_number),
494 ..self
495 }
496 }
497
498 /// Sets whether or not an event's level is displayed.
499 pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> {
500 Layer {
501 fmt_event: self.fmt_event.with_level(display_level),
502 ..self
503 }
504 }
505
506 /// Sets whether or not the [thread ID] of the current thread is displayed
507 /// when formatting events.
508 ///
509 /// [thread ID]: std::thread::ThreadId
510 pub fn with_thread_ids(self, display_thread_ids: bool) -> Layer<S, N, format::Format<L, T>, W> {
511 Layer {
512 fmt_event: self.fmt_event.with_thread_ids(display_thread_ids),
513 ..self
514 }
515 }
516
517 /// Sets whether or not the [name] of the current thread is displayed
518 /// when formatting events.
519 ///
520 /// [name]: std::thread#naming-threads
521 pub fn with_thread_names(
522 self,
523 display_thread_names: bool,
524 ) -> Layer<S, N, format::Format<L, T>, W> {
525 Layer {
526 fmt_event: self.fmt_event.with_thread_names(display_thread_names),
527 ..self
528 }
529 }
530
531 /// Sets the layer being built to use a [less verbose formatter][super::format::Compact].
532 pub fn compact(self) -> Layer<S, N, format::Format<format::Compact, T>, W>
533 where
534 N: for<'writer> FormatFields<'writer> + 'static,
535 {
536 Layer {
537 fmt_event: self.fmt_event.compact(),
538 fmt_fields: self.fmt_fields,
539 fmt_span: self.fmt_span,
540 make_writer: self.make_writer,
541 is_ansi: self.is_ansi,
542 log_internal_errors: self.log_internal_errors,
543 _inner: self._inner,
544 }
545 }
546
547 /// Sets the layer being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty).
548 #[cfg(feature = "ansi")]
549 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
550 pub fn pretty(self) -> Layer<S, format::Pretty, format::Format<format::Pretty, T>, W> {
551 Layer {
552 fmt_event: self.fmt_event.pretty(),
553 fmt_fields: format::Pretty::default(),
554 fmt_span: self.fmt_span,
555 make_writer: self.make_writer,
556 is_ansi: self.is_ansi,
557 log_internal_errors: self.log_internal_errors,
558 _inner: self._inner,
559 }
560 }
561
562 /// Sets the layer being built to use a [JSON formatter][super::format::Json].
563 ///
564 /// The full format includes fields from all entered spans.
565 ///
566 /// # Example Output
567 ///
568 /// ```ignore,json
569 /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate","fields":{"message":"some message", "key": "value"}}
570 /// ```
571 ///
572 /// # Options
573 ///
574 /// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root
575 /// object.
576 ///
577 /// [`Layer::flatten_event`]: Layer::flatten_event()
578 #[cfg(feature = "json")]
579 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
580 pub fn json(self) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
581 Layer {
582 fmt_event: self.fmt_event.json(),
583 fmt_fields: format::JsonFields::new(),
584 fmt_span: self.fmt_span,
585 make_writer: self.make_writer,
586 // always disable ANSI escapes in JSON mode!
587 is_ansi: false,
588 log_internal_errors: self.log_internal_errors,
589 _inner: self._inner,
590 }
591 }
592}
593
594#[cfg(feature = "json")]
595#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
596impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
597 /// Sets the JSON layer being built to flatten event metadata.
598 ///
599 /// See [`format::Json`][super::format::Json]
600 pub fn flatten_event(
601 self,
602 flatten_event: bool,
603 ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
604 Layer {
605 fmt_event: self.fmt_event.flatten_event(flatten_event),
606 fmt_fields: format::JsonFields::new(),
607 ..self
608 }
609 }
610
611 /// Sets whether or not the formatter will include the current span in
612 /// formatted events.
613 ///
614 /// See [`format::Json`][super::format::Json]
615 pub fn with_current_span(
616 self,
617 display_current_span: bool,
618 ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
619 Layer {
620 fmt_event: self.fmt_event.with_current_span(display_current_span),
621 fmt_fields: format::JsonFields::new(),
622 ..self
623 }
624 }
625
626 /// Sets whether or not the formatter will include a list (from root to leaf)
627 /// of all currently entered spans in formatted events.
628 ///
629 /// See [`format::Json`][super::format::Json]
630 pub fn with_span_list(
631 self,
632 display_span_list: bool,
633 ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
634 Layer {
635 fmt_event: self.fmt_event.with_span_list(display_span_list),
636 fmt_fields: format::JsonFields::new(),
637 ..self
638 }
639 }
640}
641
642impl<S, N, E, W> Layer<S, N, E, W> {
643 /// Sets the field formatter that the layer being built will use to record
644 /// fields.
645 pub fn fmt_fields<N2>(self, fmt_fields: N2) -> Layer<S, N2, E, W>
646 where
647 N2: for<'writer> FormatFields<'writer> + 'static,
648 {
649 Layer {
650 fmt_event: self.fmt_event,
651 fmt_fields,
652 fmt_span: self.fmt_span,
653 make_writer: self.make_writer,
654 is_ansi: self.is_ansi,
655 log_internal_errors: self.log_internal_errors,
656 _inner: self._inner,
657 }
658 }
659
660 /// Updates the field formatter by applying a function to the existing field formatter.
661 ///
662 /// This sets the field formatter that the layer being built will use to record fields.
663 ///
664 /// # Examples
665 ///
666 /// Updating a field formatter:
667 ///
668 /// ```rust
669 /// use tracing_subscriber::field::MakeExt;
670 /// let layer = tracing_subscriber::fmt::layer()
671 /// .map_fmt_fields(|f| f.debug_alt());
672 /// # // this is necessary for type inference.
673 /// # use tracing_subscriber::Layer as _;
674 /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
675 /// ```
676 pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> Layer<S, N2, E, W>
677 where
678 N2: for<'writer> FormatFields<'writer> + 'static,
679 {
680 Layer {
681 fmt_event: self.fmt_event,
682 fmt_fields: f(self.fmt_fields),
683 fmt_span: self.fmt_span,
684 make_writer: self.make_writer,
685 is_ansi: self.is_ansi,
686 log_internal_errors: self.log_internal_errors,
687 _inner: self._inner,
688 }
689 }
690}
691
692impl<S> Default for Layer<S> {
693 fn default() -> Self {
694 // only enable ANSI when the feature is enabled, and the NO_COLOR
695 // environment variable is unset or empty.
696 let ansi = cfg!(feature = "ansi") && env::var("NO_COLOR").map_or(true, |v| v.is_empty());
697
698 Layer {
699 fmt_fields: format::DefaultFields::default(),
700 fmt_event: format::Format::default(),
701 fmt_span: format::FmtSpanConfig::default(),
702 make_writer: io::stdout,
703 is_ansi: ansi,
704 log_internal_errors: false,
705 _inner: PhantomData,
706 }
707 }
708}
709
710impl<S, N, E, W> Layer<S, N, E, W>
711where
712 S: Subscriber + for<'a> LookupSpan<'a>,
713 N: for<'writer> FormatFields<'writer> + 'static,
714 E: FormatEvent<S, N> + 'static,
715 W: for<'writer> MakeWriter<'writer> + 'static,
716{
717 #[inline]
718 fn make_ctx<'a>(&'a self, ctx: Context<'a, S>, event: &'a Event<'a>) -> FmtContext<'a, S, N> {
719 FmtContext {
720 ctx,
721 fmt_fields: &self.fmt_fields,
722 event,
723 }
724 }
725}
726
727/// A formatted representation of a span's fields stored in its [extensions].
728///
729/// Because `FormattedFields` is generic over the type of the formatter that
730/// produced it, multiple versions of a span's formatted fields can be stored in
731/// the [`Extensions`][extensions] type-map. This means that when multiple
732/// formatters are in use, each can store its own formatted representation
733/// without conflicting.
734///
735/// [extensions]: crate::registry::Extensions
736#[derive(Default)]
737pub struct FormattedFields<E: ?Sized> {
738 _format_fields: PhantomData<fn(E)>,
739 was_ansi: bool,
740 /// The formatted fields of a span.
741 pub fields: String,
742}
743
744impl<E: ?Sized> FormattedFields<E> {
745 /// Returns a new `FormattedFields`.
746 pub fn new(fields: String) -> Self {
747 Self {
748 fields,
749 was_ansi: false,
750 _format_fields: PhantomData,
751 }
752 }
753
754 /// Returns a new [`format::Writer`] for writing to this `FormattedFields`.
755 ///
756 /// The returned [`format::Writer`] can be used with the
757 /// [`FormatFields::format_fields`] method.
758 pub fn as_writer(&mut self) -> format::Writer<'_> {
759 format::Writer::new(&mut self.fields).with_ansi(self.was_ansi)
760 }
761}
762
763impl<E: ?Sized> fmt::Debug for FormattedFields<E> {
764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765 f.debug_struct("FormattedFields")
766 .field("fields", &self.fields)
767 .field("formatter", &format_args!("{}", std::any::type_name::<E>()))
768 .field("was_ansi", &self.was_ansi)
769 .finish()
770 }
771}
772
773impl<E: ?Sized> fmt::Display for FormattedFields<E> {
774 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
775 fmt::Display::fmt(&self.fields, f)
776 }
777}
778
779impl<E: ?Sized> Deref for FormattedFields<E> {
780 type Target = String;
781 fn deref(&self) -> &Self::Target {
782 &self.fields
783 }
784}
785
786// === impl FmtLayer ===
787
788macro_rules! with_event_from_span {
789 ($id:ident, $span:ident, $($field:literal = $value:expr),*, |$event:ident| $code:block) => {
790 let meta = $span.metadata();
791 let cs = meta.callsite();
792 let fs = field::FieldSet::new(&[$($field),*], cs);
793 #[allow(unused)]
794 let mut iter = fs.iter();
795 let v = [$(
796 (&iter.next().unwrap(), ::core::option::Option::Some(&$value as &dyn field::Value)),
797 )*];
798 let vs = fs.value_set(&v);
799 let $event = Event::new_child_of($id, meta, &vs);
800 $code
801 };
802}
803
804impl<S, N, E, W> layer::Layer<S> for Layer<S, N, E, W>
805where
806 S: Subscriber + for<'a> LookupSpan<'a>,
807 N: for<'writer> FormatFields<'writer> + 'static,
808 E: FormatEvent<S, N> + 'static,
809 W: for<'writer> MakeWriter<'writer> + 'static,
810{
811 fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
812 let span = ctx.span(id).expect("Span not found, this is a bug");
813 let mut extensions = span.extensions_mut();
814
815 if extensions.get_mut::<FormattedFields<N>>().is_none() {
816 let mut fields = FormattedFields::<N>::new(String::new());
817 if self
818 .fmt_fields
819 .format_fields(fields.as_writer().with_ansi(self.is_ansi), attrs)
820 .is_ok()
821 {
822 fields.was_ansi = self.is_ansi;
823 extensions.insert(fields);
824 } else {
825 eprintln!(
826 "[tracing-subscriber] Unable to format the following event, ignoring: {:?}",
827 attrs
828 );
829 }
830 }
831
832 if self.fmt_span.fmt_timing
833 && self.fmt_span.trace_close()
834 && extensions.get_mut::<Timings>().is_none()
835 {
836 extensions.insert(Timings::new());
837 }
838
839 if self.fmt_span.trace_new() {
840 with_event_from_span!(id, span, "message" = "new", |event| {
841 drop(extensions);
842 drop(span);
843 self.on_event(&event, ctx);
844 });
845 }
846 }
847
848 fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
849 let span = ctx.span(id).expect("Span not found, this is a bug");
850 let mut extensions = span.extensions_mut();
851 if let Some(fields) = extensions.get_mut::<FormattedFields<N>>() {
852 let _ = self.fmt_fields.add_fields(fields, values);
853 return;
854 }
855
856 let mut fields = FormattedFields::<N>::new(String::new());
857 if self
858 .fmt_fields
859 .format_fields(fields.as_writer().with_ansi(self.is_ansi), values)
860 .is_ok()
861 {
862 fields.was_ansi = self.is_ansi;
863 extensions.insert(fields);
864 }
865 }
866
867 fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
868 if self.fmt_span.trace_enter() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing {
869 let span = ctx.span(id).expect("Span not found, this is a bug");
870 let mut extensions = span.extensions_mut();
871 if let Some(timings) = extensions.get_mut::<Timings>() {
872 let now = Instant::now();
873 timings.idle += (now - timings.last).as_nanos() as u64;
874 timings.last = now;
875 }
876
877 if self.fmt_span.trace_enter() {
878 with_event_from_span!(id, span, "message" = "enter", |event| {
879 drop(extensions);
880 drop(span);
881 self.on_event(&event, ctx);
882 });
883 }
884 }
885 }
886
887 fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
888 if self.fmt_span.trace_exit() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing {
889 let span = ctx.span(id).expect("Span not found, this is a bug");
890 let mut extensions = span.extensions_mut();
891 if let Some(timings) = extensions.get_mut::<Timings>() {
892 let now = Instant::now();
893 timings.busy += (now - timings.last).as_nanos() as u64;
894 timings.last = now;
895 }
896
897 if self.fmt_span.trace_exit() {
898 with_event_from_span!(id, span, "message" = "exit", |event| {
899 drop(extensions);
900 drop(span);
901 self.on_event(&event, ctx);
902 });
903 }
904 }
905 }
906
907 fn on_close(&self, id: Id, ctx: Context<'_, S>) {
908 if self.fmt_span.trace_close() {
909 let span = ctx.span(&id).expect("Span not found, this is a bug");
910 let extensions = span.extensions();
911 if let Some(timing) = extensions.get::<Timings>() {
912 let Timings {
913 busy,
914 mut idle,
915 last,
916 } = *timing;
917 idle += (Instant::now() - last).as_nanos() as u64;
918
919 let t_idle = field::display(TimingDisplay(idle));
920 let t_busy = field::display(TimingDisplay(busy));
921
922 with_event_from_span!(
923 id,
924 span,
925 "message" = "close",
926 "time.busy" = t_busy,
927 "time.idle" = t_idle,
928 |event| {
929 drop(extensions);
930 drop(span);
931 self.on_event(&event, ctx);
932 }
933 );
934 } else {
935 with_event_from_span!(id, span, "message" = "close", |event| {
936 drop(extensions);
937 drop(span);
938 self.on_event(&event, ctx);
939 });
940 }
941 }
942 }
943
944 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
945 thread_local! {
946 static BUF: RefCell<String> = RefCell::new(String::new());
947 }
948
949 BUF.with(|buf| {
950 let borrow = buf.try_borrow_mut();
951 let mut a;
952 let mut b;
953 let mut buf = match borrow {
954 Ok(buf) => {
955 a = buf;
956 &mut *a
957 }
958 _ => {
959 b = String::new();
960 &mut b
961 }
962 };
963
964 let ctx = self.make_ctx(ctx, event);
965 if self
966 .fmt_event
967 .format_event(
968 &ctx,
969 format::Writer::new(&mut buf).with_ansi(self.is_ansi),
970 event,
971 )
972 .is_ok()
973 {
974 let mut writer = self.make_writer.make_writer_for(event.metadata());
975 let res = io::Write::write_all(&mut writer, buf.as_bytes());
976 if self.log_internal_errors {
977 if let Err(e) = res {
978 eprintln!("[tracing-subscriber] Unable to write an event to the Writer for this Subscriber! Error: {}\n", e);
979 }
980 }
981 } else if self.log_internal_errors {
982 let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?}\n",
983 event.metadata().name(), event.fields());
984 let mut writer = self.make_writer.make_writer_for(event.metadata());
985 let res = io::Write::write_all(&mut writer, err_msg.as_bytes());
986 if let Err(e) = res {
987 eprintln!("[tracing-subscriber] Unable to write an \"event formatting error\" to the Writer for this Subscriber! Error: {}\n", e);
988 }
989 }
990
991 buf.clear();
992 });
993 }
994
995 unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
996 // This `downcast_raw` impl allows downcasting a `fmt` layer to any of
997 // its components (event formatter, field formatter, and `MakeWriter`)
998 // as well as to the layer's type itself. The potential use-cases for
999 // this *may* be somewhat niche, though...
1000 match () {
1001 _ if id == TypeId::of::<Self>() => Some(self as *const Self as *const ()),
1002 _ if id == TypeId::of::<E>() => Some(&self.fmt_event as *const E as *const ()),
1003 _ if id == TypeId::of::<N>() => Some(&self.fmt_fields as *const N as *const ()),
1004 _ if id == TypeId::of::<W>() => Some(&self.make_writer as *const W as *const ()),
1005 _ => None,
1006 }
1007 }
1008}
1009
1010/// Provides the current span context to a formatter.
1011pub struct FmtContext<'a, S, N> {
1012 pub(crate) ctx: Context<'a, S>,
1013 pub(crate) fmt_fields: &'a N,
1014 pub(crate) event: &'a Event<'a>,
1015}
1016
1017impl<'a, S, N> fmt::Debug for FmtContext<'a, S, N> {
1018 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1019 f.debug_struct("FmtContext").finish()
1020 }
1021}
1022
1023impl<'cx, 'writer, S, N> FormatFields<'writer> for FmtContext<'cx, S, N>
1024where
1025 S: Subscriber + for<'lookup> LookupSpan<'lookup>,
1026 N: FormatFields<'writer> + 'static,
1027{
1028 fn format_fields<R: RecordFields>(
1029 &self,
1030 writer: format::Writer<'writer>,
1031 fields: R,
1032 ) -> fmt::Result {
1033 self.fmt_fields.format_fields(writer, fields)
1034 }
1035}
1036
1037impl<'a, S, N> FmtContext<'a, S, N>
1038where
1039 S: Subscriber + for<'lookup> LookupSpan<'lookup>,
1040 N: for<'writer> FormatFields<'writer> + 'static,
1041{
1042 /// Visits every span in the current context with a closure.
1043 ///
1044 /// The provided closure will be called first with the current span,
1045 /// and then with that span's parent, and then that span's parent,
1046 /// and so on until a root span is reached.
1047 pub fn visit_spans<E, F>(&self, mut f: F) -> Result<(), E>
1048 where
1049 F: FnMut(&SpanRef<'_, S>) -> Result<(), E>,
1050 {
1051 // visit all the current spans
1052 if let Some(scope) = self.event_scope() {
1053 for span in scope.from_root() {
1054 f(&span)?;
1055 }
1056 }
1057 Ok(())
1058 }
1059
1060 /// Returns metadata for the span with the given `id`, if it exists.
1061 ///
1062 /// If this returns `None`, then no span exists for that ID (either it has
1063 /// closed or the ID is invalid).
1064 #[inline]
1065 pub fn metadata(&self, id: &Id) -> Option<&'static Metadata<'static>>
1066 where
1067 S: for<'lookup> LookupSpan<'lookup>,
1068 {
1069 self.ctx.metadata(id)
1070 }
1071
1072 /// Returns [stored data] for the span with the given `id`, if it exists.
1073 ///
1074 /// If this returns `None`, then no span exists for that ID (either it has
1075 /// closed or the ID is invalid).
1076 ///
1077 /// [stored data]: crate::registry::SpanRef
1078 #[inline]
1079 pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>>
1080 where
1081 S: for<'lookup> LookupSpan<'lookup>,
1082 {
1083 self.ctx.span(id)
1084 }
1085
1086 /// Returns `true` if an active span exists for the given `Id`.
1087 #[inline]
1088 pub fn exists(&self, id: &Id) -> bool
1089 where
1090 S: for<'lookup> LookupSpan<'lookup>,
1091 {
1092 self.ctx.exists(id)
1093 }
1094
1095 /// Returns [stored data] for the span that the wrapped subscriber considers
1096 /// to be the current.
1097 ///
1098 /// If this returns `None`, then we are not currently within a span.
1099 ///
1100 /// [stored data]: crate::registry::SpanRef
1101 #[inline]
1102 pub fn lookup_current(&self) -> Option<SpanRef<'_, S>>
1103 where
1104 S: for<'lookup> LookupSpan<'lookup>,
1105 {
1106 self.ctx.lookup_current()
1107 }
1108
1109 /// Returns the current span for this formatter.
1110 pub fn current_span(&self) -> Current {
1111 self.ctx.current_span()
1112 }
1113
1114 /// Returns [stored data] for the parent span of the event currently being
1115 /// formatted.
1116 ///
1117 /// If the event has a contextual parent, this will return the current span. If
1118 /// the event has an explicit parent span, this will return that span. If
1119 /// the event does not have a parent span, this will return `None`.
1120 ///
1121 /// [stored data]: SpanRef
1122 pub fn parent_span(&self) -> Option<SpanRef<'_, S>> {
1123 self.ctx.event_span(self.event)
1124 }
1125
1126 /// Returns an iterator over the [stored data] for all the spans in the
1127 /// current context, starting with the specified span and ending with the
1128 /// root of the trace tree and ending with the current span.
1129 ///
1130 /// This is equivalent to the [`Context::span_scope`] method.
1131 ///
1132 /// <div class="information">
1133 /// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
1134 /// </div>
1135 /// <div class="example-wrap" style="display:inline-block">
1136 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1137 /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
1138 /// returns the spans in reverse order (from leaf to root). Use
1139 /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
1140 /// in case root-to-leaf ordering is desired.
1141 /// </pre></div>
1142 ///
1143 /// <div class="example-wrap" style="display:inline-block">
1144 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1145 /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
1146 /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
1147 /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
1148 /// declaration</a> for details.
1149 /// </pre></div>
1150 ///
1151 /// [stored data]: crate::registry::SpanRef
1152 pub fn span_scope(&self, id: &Id) -> Option<registry::Scope<'_, S>>
1153 where
1154 S: for<'lookup> LookupSpan<'lookup>,
1155 {
1156 self.ctx.span_scope(id)
1157 }
1158
1159 /// Returns an iterator over the [stored data] for all the spans in the
1160 /// event's span context, starting with its parent span and ending with the
1161 /// root of the trace tree.
1162 ///
1163 /// This is equivalent to calling the [`Context::event_scope`] method and
1164 /// passing the event currently being formatted.
1165 ///
1166 /// <div class="example-wrap" style="display:inline-block">
1167 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1168 /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
1169 /// returns the spans in reverse order (from leaf to root). Use
1170 /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
1171 /// in case root-to-leaf ordering is desired.
1172 /// </pre></div>
1173 ///
1174 /// <div class="example-wrap" style="display:inline-block">
1175 /// <pre class="ignore" style="white-space:normal;font:inherit;">
1176 /// <strong>Note</strong>: This requires the wrapped subscriber to implement the
1177 /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
1178 /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
1179 /// declaration</a> for details.
1180 /// </pre></div>
1181 ///
1182 /// [stored data]: crate::registry::SpanRef
1183 pub fn event_scope(&self) -> Option<registry::Scope<'_, S>>
1184 where
1185 S: for<'lookup> registry::LookupSpan<'lookup>,
1186 {
1187 self.ctx.event_scope(self.event)
1188 }
1189
1190 /// Returns the [field formatter] configured by the subscriber invoking
1191 /// `format_event`.
1192 ///
1193 /// The event formatter may use the returned field formatter to format the
1194 /// fields of any events it records.
1195 ///
1196 /// [field formatter]: FormatFields
1197 pub fn field_format(&self) -> &N {
1198 self.fmt_fields
1199 }
1200}
1201
1202struct Timings {
1203 idle: u64,
1204 busy: u64,
1205 last: Instant,
1206}
1207
1208impl Timings {
1209 fn new() -> Self {
1210 Self {
1211 idle: 0,
1212 busy: 0,
1213 last: Instant::now(),
1214 }
1215 }
1216}
1217
1218#[cfg(test)]
1219mod test {
1220 use super::*;
1221 use crate::fmt::{
1222 self,
1223 format::{self, test::MockTime, Format},
1224 layer::Layer as _,
1225 test::{MockMakeWriter, MockWriter},
1226 time,
1227 };
1228 use crate::Registry;
1229 use format::FmtSpan;
1230 use regex::Regex;
1231 use tracing::subscriber::with_default;
1232 use tracing_core::dispatcher::Dispatch;
1233
1234 #[test]
1235 fn impls() {
1236 let f = Format::default().with_timer(time::Uptime::default());
1237 let fmt = fmt::Layer::default().event_format(f);
1238 let subscriber = fmt.with_subscriber(Registry::default());
1239 let _dispatch = Dispatch::new(subscriber);
1240
1241 let f = format::Format::default();
1242 let fmt = fmt::Layer::default().event_format(f);
1243 let subscriber = fmt.with_subscriber(Registry::default());
1244 let _dispatch = Dispatch::new(subscriber);
1245
1246 let f = format::Format::default().compact();
1247 let fmt = fmt::Layer::default().event_format(f);
1248 let subscriber = fmt.with_subscriber(Registry::default());
1249 let _dispatch = Dispatch::new(subscriber);
1250 }
1251
1252 #[test]
1253 fn fmt_layer_downcasts() {
1254 let f = format::Format::default();
1255 let fmt = fmt::Layer::default().event_format(f);
1256 let subscriber = fmt.with_subscriber(Registry::default());
1257
1258 let dispatch = Dispatch::new(subscriber);
1259 assert!(dispatch.downcast_ref::<fmt::Layer<Registry>>().is_some());
1260 }
1261
1262 #[test]
1263 fn fmt_layer_downcasts_to_parts() {
1264 let f = format::Format::default();
1265 let fmt = fmt::Layer::default().event_format(f);
1266 let subscriber = fmt.with_subscriber(Registry::default());
1267 let dispatch = Dispatch::new(subscriber);
1268 assert!(dispatch.downcast_ref::<format::DefaultFields>().is_some());
1269 assert!(dispatch.downcast_ref::<format::Format>().is_some())
1270 }
1271
1272 #[test]
1273 fn is_lookup_span() {
1274 fn assert_lookup_span<T: for<'a> crate::registry::LookupSpan<'a>>(_: T) {}
1275 let fmt = fmt::Layer::default();
1276 let subscriber = fmt.with_subscriber(Registry::default());
1277 assert_lookup_span(subscriber)
1278 }
1279
1280 fn sanitize_timings(s: String) -> String {
1281 let re = Regex::new("time\\.(idle|busy)=([0-9.]+)[mµn]s").unwrap();
1282 re.replace_all(s.as_str(), "timing").to_string()
1283 }
1284
1285 #[test]
1286 fn format_error_print_to_stderr() {
1287 struct AlwaysError;
1288
1289 impl std::fmt::Debug for AlwaysError {
1290 fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1291 Err(std::fmt::Error)
1292 }
1293 }
1294
1295 let make_writer = MockMakeWriter::default();
1296 let subscriber = crate::fmt::Subscriber::builder()
1297 .with_writer(make_writer.clone())
1298 .with_level(false)
1299 .with_ansi(false)
1300 .with_timer(MockTime)
1301 .finish();
1302
1303 with_default(subscriber, || {
1304 tracing::info!(?AlwaysError);
1305 });
1306 let actual = sanitize_timings(make_writer.get_string());
1307
1308 // Only assert the start because the line number and callsite may change.
1309 let expected = concat!(
1310 "Unable to format the following event. Name: event ",
1311 file!(),
1312 ":"
1313 );
1314 assert!(
1315 actual.as_str().starts_with(expected),
1316 "\nactual = {}\nshould start with expected = {}\n",
1317 actual,
1318 expected
1319 );
1320 }
1321
1322 #[test]
1323 fn format_error_ignore_if_log_internal_errors_is_false() {
1324 struct AlwaysError;
1325
1326 impl std::fmt::Debug for AlwaysError {
1327 fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1328 Err(std::fmt::Error)
1329 }
1330 }
1331
1332 let make_writer = MockMakeWriter::default();
1333 let subscriber = crate::fmt::Subscriber::builder()
1334 .with_writer(make_writer.clone())
1335 .with_level(false)
1336 .with_ansi(false)
1337 .with_timer(MockTime)
1338 .log_internal_errors(false)
1339 .finish();
1340
1341 with_default(subscriber, || {
1342 tracing::info!(?AlwaysError);
1343 });
1344 let actual = sanitize_timings(make_writer.get_string());
1345 assert_eq!("", actual.as_str());
1346 }
1347
1348 #[test]
1349 fn synthesize_span_none() {
1350 let make_writer = MockMakeWriter::default();
1351 let subscriber = crate::fmt::Subscriber::builder()
1352 .with_writer(make_writer.clone())
1353 .with_level(false)
1354 .with_ansi(false)
1355 .with_timer(MockTime)
1356 // check that FmtSpan::NONE is the default
1357 .finish();
1358
1359 with_default(subscriber, || {
1360 let span1 = tracing::info_span!("span1", x = 42);
1361 let _e = span1.enter();
1362 });
1363 let actual = sanitize_timings(make_writer.get_string());
1364 assert_eq!("", actual.as_str());
1365 }
1366
1367 #[test]
1368 fn synthesize_span_active() {
1369 let make_writer = MockMakeWriter::default();
1370 let subscriber = crate::fmt::Subscriber::builder()
1371 .with_writer(make_writer.clone())
1372 .with_level(false)
1373 .with_ansi(false)
1374 .with_timer(MockTime)
1375 .with_span_events(FmtSpan::ACTIVE)
1376 .finish();
1377
1378 with_default(subscriber, || {
1379 let span1 = tracing::info_span!("span1", x = 42);
1380 let _e = span1.enter();
1381 });
1382 let actual = sanitize_timings(make_writer.get_string());
1383 assert_eq!(
1384 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter\n\
1385 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit\n",
1386 actual.as_str()
1387 );
1388 }
1389
1390 #[test]
1391 fn synthesize_span_close() {
1392 let make_writer = MockMakeWriter::default();
1393 let subscriber = crate::fmt::Subscriber::builder()
1394 .with_writer(make_writer.clone())
1395 .with_level(false)
1396 .with_ansi(false)
1397 .with_timer(MockTime)
1398 .with_span_events(FmtSpan::CLOSE)
1399 .finish();
1400
1401 with_default(subscriber, || {
1402 let span1 = tracing::info_span!("span1", x = 42);
1403 let _e = span1.enter();
1404 });
1405 let actual = sanitize_timings(make_writer.get_string());
1406 assert_eq!(
1407 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing\n",
1408 actual.as_str()
1409 );
1410 }
1411
1412 #[test]
1413 fn synthesize_span_close_no_timing() {
1414 let make_writer = MockMakeWriter::default();
1415 let subscriber = crate::fmt::Subscriber::builder()
1416 .with_writer(make_writer.clone())
1417 .with_level(false)
1418 .with_ansi(false)
1419 .with_timer(MockTime)
1420 .without_time()
1421 .with_span_events(FmtSpan::CLOSE)
1422 .finish();
1423
1424 with_default(subscriber, || {
1425 let span1 = tracing::info_span!("span1", x = 42);
1426 let _e = span1.enter();
1427 });
1428 let actual = sanitize_timings(make_writer.get_string());
1429 assert_eq!(
1430 "span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close\n",
1431 actual.as_str()
1432 );
1433 }
1434
1435 #[test]
1436 fn synthesize_span_full() {
1437 let make_writer = MockMakeWriter::default();
1438 let subscriber = crate::fmt::Subscriber::builder()
1439 .with_writer(make_writer.clone())
1440 .with_level(false)
1441 .with_ansi(false)
1442 .with_timer(MockTime)
1443 .with_span_events(FmtSpan::FULL)
1444 .finish();
1445
1446 with_default(subscriber, || {
1447 let span1 = tracing::info_span!("span1", x = 42);
1448 let _e = span1.enter();
1449 });
1450 let actual = sanitize_timings(make_writer.get_string());
1451 assert_eq!(
1452 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: new\n\
1453 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter\n\
1454 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit\n\
1455 fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing\n",
1456 actual.as_str()
1457 );
1458 }
1459
1460 #[test]
1461 fn make_writer_based_on_meta() {
1462 struct MakeByTarget {
1463 make_writer1: MockMakeWriter,
1464 make_writer2: MockMakeWriter,
1465 }
1466
1467 impl<'a> MakeWriter<'a> for MakeByTarget {
1468 type Writer = MockWriter;
1469
1470 fn make_writer(&'a self) -> Self::Writer {
1471 self.make_writer1.make_writer()
1472 }
1473
1474 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
1475 if meta.target() == "writer2" {
1476 return self.make_writer2.make_writer();
1477 }
1478 self.make_writer()
1479 }
1480 }
1481
1482 let make_writer1 = MockMakeWriter::default();
1483 let make_writer2 = MockMakeWriter::default();
1484
1485 let make_writer = MakeByTarget {
1486 make_writer1: make_writer1.clone(),
1487 make_writer2: make_writer2.clone(),
1488 };
1489
1490 let subscriber = crate::fmt::Subscriber::builder()
1491 .with_writer(make_writer)
1492 .with_level(false)
1493 .with_target(false)
1494 .with_ansi(false)
1495 .with_timer(MockTime)
1496 .with_span_events(FmtSpan::CLOSE)
1497 .finish();
1498
1499 with_default(subscriber, || {
1500 let span1 = tracing::info_span!("writer1_span", x = 42);
1501 let _e = span1.enter();
1502 tracing::info!(target: "writer2", "hello writer2!");
1503 let span2 = tracing::info_span!(target: "writer2", "writer2_span");
1504 let _e = span2.enter();
1505 tracing::warn!(target: "writer1", "hello writer1!");
1506 });
1507
1508 let actual = sanitize_timings(make_writer1.get_string());
1509 assert_eq!(
1510 "fake time writer1_span{x=42}:writer2_span: hello writer1!\n\
1511 fake time writer1_span{x=42}: close timing timing\n",
1512 actual.as_str()
1513 );
1514 let actual = sanitize_timings(make_writer2.get_string());
1515 assert_eq!(
1516 "fake time writer1_span{x=42}: hello writer2!\n\
1517 fake time writer1_span{x=42}:writer2_span: close timing timing\n",
1518 actual.as_str()
1519 );
1520 }
1521
1522 // Because we need to modify an environment variable for these test cases,
1523 // we do them all in a single test.
1524 #[cfg(feature = "ansi")]
1525 #[test]
1526 fn layer_no_color() {
1527 const NO_COLOR: &str = "NO_COLOR";
1528
1529 // Restores the previous value of the `NO_COLOR` env variable when
1530 // dropped.
1531 //
1532 // This is done in a `Drop` implementation, rather than just resetting
1533 // the value at the end of the test, so that the previous value is
1534 // restored even if the test panics.
1535 struct RestoreEnvVar(Result<String, env::VarError>);
1536 impl Drop for RestoreEnvVar {
1537 fn drop(&mut self) {
1538 match self.0 {
1539 Ok(ref var) => env::set_var(NO_COLOR, var),
1540 Err(_) => env::remove_var(NO_COLOR),
1541 }
1542 }
1543 }
1544
1545 let _saved_no_color = RestoreEnvVar(env::var(NO_COLOR));
1546
1547 let cases: Vec<(Option<&str>, bool)> = vec![
1548 (Some("0"), false), // any non-empty value disables ansi
1549 (Some("off"), false), // any non-empty value disables ansi
1550 (Some("1"), false),
1551 (Some(""), true), // empty value does not disable ansi
1552 (None, true),
1553 ];
1554
1555 for (var, ansi) in cases {
1556 if let Some(value) = var {
1557 env::set_var(NO_COLOR, value);
1558 } else {
1559 env::remove_var(NO_COLOR);
1560 }
1561
1562 let layer: Layer<()> = fmt::Layer::default();
1563 assert_eq!(
1564 layer.is_ansi, ansi,
1565 "NO_COLOR={:?}; Layer::default().is_ansi should be {}",
1566 var, ansi
1567 );
1568
1569 // with_ansi should override any `NO_COLOR` value
1570 let layer: Layer<()> = fmt::Layer::default().with_ansi(true);
1571 assert!(
1572 layer.is_ansi,
1573 "NO_COLOR={:?}; Layer::default().with_ansi(true).is_ansi should be true",
1574 var
1575 );
1576
1577 // set_ansi should override any `NO_COLOR` value
1578 let mut layer: Layer<()> = fmt::Layer::default();
1579 layer.set_ansi(true);
1580 assert!(
1581 layer.is_ansi,
1582 "NO_COLOR={:?}; layer.set_ansi(true); layer.is_ansi should be true",
1583 var
1584 );
1585 }
1586
1587 // dropping `_saved_no_color` will restore the previous value of
1588 // `NO_COLOR`.
1589 }
1590}
1591