1 //! Formatters for logging `tracing` events.
2 use super::time::{FormatTime, SystemTime};
3 use crate::{
4     field::{MakeOutput, MakeVisitor, RecordFields, VisitFmt, VisitOutput},
5     fmt::fmt_layer::FmtContext,
6     fmt::fmt_layer::FormattedFields,
7     registry::LookupSpan,
8 };
9 
10 use std::fmt::{self, Debug, Display, Write};
11 use tracing_core::{
12     field::{self, Field, Visit},
13     span, Event, Level, Subscriber,
14 };
15 
16 #[cfg(feature = "tracing-log")]
17 use tracing_log::NormalizeEvent;
18 
19 #[cfg(feature = "ansi")]
20 use ansi_term::{Colour, Style};
21 
22 #[cfg(feature = "json")]
23 mod json;
24 #[cfg(feature = "json")]
25 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
26 pub use json::*;
27 
28 #[cfg(feature = "ansi")]
29 mod pretty;
30 #[cfg(feature = "ansi")]
31 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
32 pub use pretty::*;
33 
34 /// A type that can format a tracing [`Event`] to a [`Writer`].
35 ///
36 /// `FormatEvent` is primarily used in the context of [`fmt::Subscriber`] or
37 /// [`fmt::Layer`]. Each time an event is dispatched to [`fmt::Subscriber`] or
38 /// [`fmt::Layer`], the subscriber or layer
39 /// forwards it to its associated `FormatEvent` to emit a log message.
40 ///
41 /// This trait is already implemented for function pointers with the same
42 /// signature as `format_event`.
43 ///
44 /// # Arguments
45 ///
46 /// The following arguments are passed to `FormatEvent::format_event`:
47 ///
48 /// * A [`FmtContext`]. This is an extension of the [`layer::Context`] type,
49 ///   which can be used for accessing stored information such as the current
50 ///   span context an event occurred in.
51 ///
52 ///   In addition, [`FmtContext`] exposes access to the [`FormatFields`]
53 ///   implementation that the subscriber was configured to use via the
54 ///   [`FmtContext::field_format`] method. This can be used when the
55 ///   [`FormatEvent`] implementation needs to format the event's fields.
56 ///
57 ///   For convenience, [`FmtContext`] also [implements `FormatFields`],
58 ///   forwarding to the configured [`FormatFields`] type.
59 ///
60 /// * A [`Writer`] to which the formatted representation of the event is
61 ///   written. This type implements the [`std::fmt::Write`] trait, and therefore
62 ///   can be used with the [`std::write!`] and [`std::writeln!`] macros, as well
63 ///   as calling [`std::fmt::Write`] methods directly.
64 ///
65 ///   The [`Writer`] type also implements additional methods that provide
66 ///   information about how the event should be formatted. The
67 ///   [`Writer::has_ansi_escapes`] method indicates whether [ANSI terminal
68 ///   escape codes] are supported by the underlying I/O writer that the event
69 ///   will be written to. If this returns `true`, the formatter is permitted to
70 ///   use ANSI escape codes to add colors and other text formatting to its
71 ///   output. If it returns `false`, the event will be written to an output that
72 ///   does not support ANSI escape codes (such as a log file), and they should
73 ///   not be emitted.
74 ///
75 ///   Crates like [`ansi_term`] and [`owo-colors`] can be used to add ANSI
76 ///   escape codes to formatted output.
77 ///
78 /// * The actual [`Event`] to be formatted.
79 ///
80 /// # Examples
81 ///
82 /// This example re-implements a simiplified version of this crate's [default
83 /// formatter]:
84 ///
85 /// ```rust
86 /// use std::fmt;
87 /// use tracing_core::{Subscriber, Event};
88 /// use tracing_subscriber::fmt::{
89 ///     format::{self, FormatEvent, FormatFields},
90 ///     FmtContext,
91 ///     FormattedFields,
92 /// };
93 /// use tracing_subscriber::registry::LookupSpan;
94 ///
95 /// struct MyFormatter;
96 ///
97 /// impl<S, N> FormatEvent<S, N> for MyFormatter
98 /// where
99 ///     S: Subscriber + for<'a> LookupSpan<'a>,
100 ///     N: for<'a> FormatFields<'a> + 'static,
101 /// {
102 ///     fn format_event(
103 ///         &self,
104 ///         ctx: &FmtContext<'_, S, N>,
105 ///         mut writer: format::Writer<'_>,
106 ///         event: &Event<'_>,
107 ///     ) -> fmt::Result {
108 ///         // Format values from the event's's metadata:
109 ///         let metadata = event.metadata();
110 ///         write!(&mut writer, "{} {}: ", metadata.level(), metadata.target())?;
111 ///
112 ///         // Format all the spans in the event's span context.
113 ///         if let Some(scope) = ctx.event_scope() {
114 ///             for span in scope.from_root() {
115 ///                 write!(writer, "{}", span.name())?;
116 ///
117 ///                 // `FormattedFields` is a formatted representation of the span's
118 ///                 // fields, which is stored in its extensions by the `fmt` layer's
119 ///                 // `new_span` method. The fields will have been formatted
120 ///                 // by the same field formatter that's provided to the event
121 ///                 // formatter in the `FmtContext`.
122 ///                 let ext = span.extensions();
123 ///                 let fields = &ext
124 ///                     .get::<FormattedFields<N>>()
125 ///                     .expect("will never be `None`");
126 ///
127 ///                 // Skip formatting the fields if the span had no fields.
128 ///                 if !fields.is_empty() {
129 ///                     write!(writer, "{{{}}}", fields)?;
130 ///                 }
131 ///                 write!(writer, ": ")?;
132 ///             }
133 ///         }
134 ///
135 ///         // Write fields on the event
136 ///         ctx.field_format().format_fields(writer.by_ref(), event)?;
137 ///
138 ///         writeln!(writer)
139 ///     }
140 /// }
141 ///
142 /// let _subscriber = tracing_subscriber::fmt()
143 ///     .event_format(MyFormatter)
144 ///     .init();
145 ///
146 /// let _span = tracing::info_span!("my_span", answer = 42).entered();
147 /// tracing::info!(question = "life, the universe, and everything", "hello world");
148 /// ```
149 ///
150 /// This formatter will print events like this:
151 ///
152 /// ```text
153 /// DEBUG yak_shaving::shaver: some-span{field-on-span=foo}: started shaving yak
154 /// ```
155 ///
156 /// [`fmt::Layer`]: super::Layer
157 /// [`fmt::Subscriber`]: super::Subscriber
158 /// [`Event`]: tracing::Event
159 /// [implements `FormatFields`]: super::FmtContext#impl-FormatFields<'writer>
160 /// [ANSI terminal escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code
161 /// [`Writer::has_ansi_escapes`]: Writer::has_ansi_escapes
162 /// [`ansi_term`]: https://crates.io/crates/ansi_term
163 /// [`owo-colors`]: https://crates.io/crates/owo-colors
164 /// [default formatter]: Full
165 pub trait FormatEvent<S, N>
166 where
167     S: Subscriber + for<'a> LookupSpan<'a>,
168     N: for<'a> FormatFields<'a> + 'static,
169 {
170     /// Write a log message for `Event` in `Context` to the given [`Writer`].
format_event( &self, ctx: &FmtContext<'_, S, N>, writer: Writer<'_>, event: &Event<'_>, ) -> fmt::Result171     fn format_event(
172         &self,
173         ctx: &FmtContext<'_, S, N>,
174         writer: Writer<'_>,
175         event: &Event<'_>,
176     ) -> fmt::Result;
177 }
178 
179 impl<S, N> FormatEvent<S, N>
180     for fn(ctx: &FmtContext<'_, S, N>, Writer<'_>, &Event<'_>) -> fmt::Result
181 where
182     S: Subscriber + for<'a> LookupSpan<'a>,
183     N: for<'a> FormatFields<'a> + 'static,
184 {
format_event( &self, ctx: &FmtContext<'_, S, N>, writer: Writer<'_>, event: &Event<'_>, ) -> fmt::Result185     fn format_event(
186         &self,
187         ctx: &FmtContext<'_, S, N>,
188         writer: Writer<'_>,
189         event: &Event<'_>,
190     ) -> fmt::Result {
191         (*self)(ctx, writer, event)
192     }
193 }
194 /// A type that can format a [set of fields] to a [`Writer`].
195 ///
196 /// `FormatFields` is primarily used in the context of [`FmtSubscriber`]. Each
197 /// time a span or event with fields is recorded, the subscriber will format
198 /// those fields with its associated `FormatFields` implementation.
199 ///
200 /// [set of fields]: ../field/trait.RecordFields.html
201 /// [`FmtSubscriber`]: ../fmt/struct.Subscriber.html
202 pub trait FormatFields<'writer> {
203     /// Format the provided `fields` to the provided [`Writer`], returning a result.
format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result204     fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result;
205 
206     /// Record additional field(s) on an existing span.
207     ///
208     /// By default, this appends a space to the current set of fields if it is
209     /// non-empty, and then calls `self.format_fields`. If different behavior is
210     /// required, the default implementation of this method can be overridden.
add_fields( &self, current: &'writer mut FormattedFields<Self>, fields: &span::Record<'_>, ) -> fmt::Result211     fn add_fields(
212         &self,
213         current: &'writer mut FormattedFields<Self>,
214         fields: &span::Record<'_>,
215     ) -> fmt::Result {
216         if !current.fields.is_empty() {
217             current.fields.push(' ');
218         }
219         self.format_fields(current.as_writer(), fields)
220     }
221 }
222 
223 /// Returns the default configuration for an [event formatter].
224 ///
225 /// Methods on the returned event formatter can be used for further
226 /// configuration. For example:
227 ///
228 /// ```rust
229 /// let format = tracing_subscriber::fmt::format()
230 ///     .without_time()         // Don't include timestamps
231 ///     .with_target(false)     // Don't include event targets.
232 ///     .with_level(false)      // Don't include event levels.
233 ///     .compact();             // Use a more compact, abbreviated format.
234 ///
235 /// // Use the configured formatter when building a new subscriber.
236 /// tracing_subscriber::fmt()
237 ///     .event_format(format)
238 ///     .init();
239 /// ```
format() -> Format240 pub fn format() -> Format {
241     Format::default()
242 }
243 
244 /// Returns the default configuration for a JSON [event formatter].
245 #[cfg(feature = "json")]
246 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
json() -> Format<Json>247 pub fn json() -> Format<Json> {
248     format().json()
249 }
250 
251 /// Returns a [`FormatFields`] implementation that formats fields using the
252 /// provided function or closure.
253 ///
254 /// [`FormatFields`]: trait.FormatFields.html
debug_fn<F>(f: F) -> FieldFn<F> where F: Fn(&mut Writer<'_>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone,255 pub fn debug_fn<F>(f: F) -> FieldFn<F>
256 where
257     F: Fn(&mut Writer<'_>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone,
258 {
259     FieldFn(f)
260 }
261 
262 /// A writer to which formatted representations of spans and events are written.
263 ///
264 /// This type is provided as input to the [`FormatEvent::format_event`] and
265 /// [`FormatFields::format_fields`] methods, which will write formatted
266 /// representations of [`Event`]s and [fields] to the `Writer`.
267 ///
268 /// This type implements the [`std::fmt::Write`] trait, allowing it to be used
269 /// with any function that takes an instance of [`std::fmt::Write`].
270 /// Additionally, it can be used with the standard library's [`std::write!`] and
271 /// [`std::writeln!`] macros.
272 ///
273 /// Additionally, a `Writer` may expose additional `tracing`-specific
274 /// information to the formatter implementation.
275 pub struct Writer<'writer> {
276     writer: &'writer mut dyn fmt::Write,
277     // TODO(eliza): add ANSI support
278     is_ansi: bool,
279 }
280 
281 /// A [`FormatFields`] implementation that formats fields by calling a function
282 /// or closure.
283 ///
284 /// [`FormatFields`]: trait.FormatFields.html
285 #[derive(Debug, Clone)]
286 pub struct FieldFn<F>(F);
287 /// The [visitor] produced by [`FieldFn`]'s [`MakeVisitor`] implementation.
288 ///
289 /// [visitor]: ../../field/trait.Visit.html
290 /// [`FieldFn`]: struct.FieldFn.html
291 /// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
292 pub struct FieldFnVisitor<'a, F> {
293     f: F,
294     writer: Writer<'a>,
295     result: fmt::Result,
296 }
297 /// Marker for `Format` that indicates that the compact log format should be used.
298 ///
299 /// The compact format only includes the fields from the most recently entered span.
300 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
301 pub struct Compact;
302 
303 /// Marker for `Format` that indicates that the verbose log format should be used.
304 ///
305 /// The full format includes fields from all entered spans.
306 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
307 pub struct Full;
308 
309 /// A pre-configured event formatter.
310 ///
311 /// You will usually want to use this as the `FormatEvent` for a `FmtSubscriber`.
312 ///
313 /// The default logging format, [`Full`] includes all fields in each event and its containing
314 /// spans. The [`Compact`] logging format includes only the fields from the most-recently-entered
315 /// span.
316 #[derive(Debug, Clone)]
317 pub struct Format<F = Full, T = SystemTime> {
318     format: F,
319     pub(crate) timer: T,
320     pub(crate) ansi: Option<bool>,
321     pub(crate) display_timestamp: bool,
322     pub(crate) display_target: bool,
323     pub(crate) display_level: bool,
324     pub(crate) display_thread_id: bool,
325     pub(crate) display_thread_name: bool,
326 }
327 
328 // === impl Writer ===
329 
330 impl<'writer> Writer<'writer> {
331     // TODO(eliza): consider making this a public API?
332     // We may not want to do that if we choose to expose specialized
333     // constructors instead (e.g. `from_string` that stores whether the string
334     // is empty...?)
new(writer: &'writer mut impl fmt::Write) -> Self335     pub(crate) fn new(writer: &'writer mut impl fmt::Write) -> Self {
336         Self {
337             writer: writer as &mut dyn fmt::Write,
338             is_ansi: false,
339         }
340     }
341 
342     // TODO(eliza): consider making this a public API?
with_ansi(self, is_ansi: bool) -> Self343     pub(crate) fn with_ansi(self, is_ansi: bool) -> Self {
344         Self { is_ansi, ..self }
345     }
346 
347     /// Return a new `Writer` that mutably borrows `self`.
348     ///
349     /// This can be used to temporarily borrow a `Writer` to pass a new `Writer`
350     /// to a function that takes a `Writer` by value, allowing the original writer
351     /// to still be used once that function returns.
by_ref(&mut self) -> Writer<'_>352     pub fn by_ref(&mut self) -> Writer<'_> {
353         let is_ansi = self.is_ansi;
354         Writer {
355             writer: self as &mut dyn fmt::Write,
356             is_ansi,
357         }
358     }
359 
360     /// Writes a string slice into this `Writer`, returning whether the write succeeded.
361     ///
362     /// This method can only succeed if the entire string slice was successfully
363     /// written, and this method will not return until all data has been written
364     /// or an error occurs.
365     ///
366     /// This is identical to calling the [`write_str` method] from the `Writer`'s
367     /// [`std::fmt::Write`] implementation. However, it is also provided as an
368     /// inherent method, so that `Writer`s can be used without needing to import the
369     /// [`std::fmt::Write`] trait.
370     ///
371     /// # Errors
372     ///
373     /// This function will return an instance of [`std::fmt::Error`] on error.
374     ///
375     /// [`write_str` method]: std::fmt::Write::write_str
376     #[inline]
write_str(&mut self, s: &str) -> fmt::Result377     pub fn write_str(&mut self, s: &str) -> fmt::Result {
378         self.writer.write_str(s)
379     }
380 
381     /// Writes a [`char`] into this writer, returning whether the write succeeded.
382     ///
383     /// A single [`char`] may be encoded as more than one byte.
384     /// This method can only succeed if the entire byte sequence was successfully
385     /// written, and this method will not return until all data has been
386     /// written or an error occurs.
387     ///
388     /// This is identical to calling the [`write_char` method] from the `Writer`'s
389     /// [`std::fmt::Write`] implementation. However, it is also provided as an
390     /// inherent method, so that `Writer`s can be used without needing to import the
391     /// [`std::fmt::Write`] trait.
392     ///
393     /// # Errors
394     ///
395     /// This function will return an instance of [`std::fmt::Error`] on error.
396     ///
397     /// [`write_char` method]: std::fmt::Write::write_char
398     #[inline]
write_char(&mut self, c: char) -> fmt::Result399     pub fn write_char(&mut self, c: char) -> fmt::Result {
400         self.writer.write_char(c)
401     }
402 
403     /// Glue for usage of the [`write!`] macro with `Writer`s.
404     ///
405     /// This method should generally not be invoked manually, but rather through
406     /// the [`write!`] macro itself.
407     ///
408     /// This is identical to calling the [`write_fmt` method] from the `Writer`'s
409     /// [`std::fmt::Write`] implementation. However, it is also provided as an
410     /// inherent method, so that `Writer`s can be used with the [`write!` macro]
411     /// without needing to import the
412     /// [`std::fmt::Write`] trait.
413     ///
414     /// [`write_fmt` method]: std::fmt::Write::write_fmt
write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result415     pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
416         self.writer.write_fmt(args)
417     }
418 
419     /// Returns `true` if [ANSI escape codes] may be used to add colors
420     /// and other formatting when writing to this `Writer`.
421     ///
422     /// If this returns `false`, formatters should not emit ANSI escape codes.
423     ///
424     /// [ANSI escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code
has_ansi_escapes(&self) -> bool425     pub fn has_ansi_escapes(&self) -> bool {
426         self.is_ansi
427     }
428 
bold(&self) -> Style429     pub(in crate::fmt::format) fn bold(&self) -> Style {
430         #[cfg(feature = "ansi")]
431         {
432             if self.is_ansi {
433                 return Style::new().bold();
434             }
435         }
436 
437         Style::new()
438     }
439 
dimmed(&self) -> Style440     pub(in crate::fmt::format) fn dimmed(&self) -> Style {
441         #[cfg(feature = "ansi")]
442         {
443             if self.is_ansi {
444                 return Style::new().dimmed();
445             }
446         }
447 
448         Style::new()
449     }
450 
italic(&self) -> Style451     pub(in crate::fmt::format) fn italic(&self) -> Style {
452         #[cfg(feature = "ansi")]
453         {
454             if self.is_ansi {
455                 return Style::new().italic();
456             }
457         }
458 
459         Style::new()
460     }
461 }
462 
463 impl fmt::Write for Writer<'_> {
464     #[inline]
write_str(&mut self, s: &str) -> fmt::Result465     fn write_str(&mut self, s: &str) -> fmt::Result {
466         Writer::write_str(self, s)
467     }
468 
469     #[inline]
write_char(&mut self, c: char) -> fmt::Result470     fn write_char(&mut self, c: char) -> fmt::Result {
471         Writer::write_char(self, c)
472     }
473 
474     #[inline]
write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result475     fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
476         Writer::write_fmt(self, args)
477     }
478 }
479 
480 impl fmt::Debug for Writer<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result481     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
482         f.debug_struct("Writer")
483             .field("writer", &format_args!("<&mut dyn fmt::Write>"))
484             .field("is_ansi", &self.is_ansi)
485             .finish()
486     }
487 }
488 
489 // === impl Format ===
490 
491 impl Default for Format<Full, SystemTime> {
default() -> Self492     fn default() -> Self {
493         Format {
494             format: Full,
495             timer: SystemTime,
496             ansi: None,
497             display_timestamp: true,
498             display_target: true,
499             display_level: true,
500             display_thread_id: false,
501             display_thread_name: false,
502         }
503     }
504 }
505 
506 impl<F, T> Format<F, T> {
507     /// Use a less verbose output format.
508     ///
509     /// See [`Compact`].
compact(self) -> Format<Compact, T>510     pub fn compact(self) -> Format<Compact, T> {
511         Format {
512             format: Compact,
513             timer: self.timer,
514             ansi: self.ansi,
515             display_target: self.display_target,
516             display_timestamp: self.display_timestamp,
517             display_level: self.display_level,
518             display_thread_id: self.display_thread_id,
519             display_thread_name: self.display_thread_name,
520         }
521     }
522 
523     /// Use an excessively pretty, human-readable output format.
524     ///
525     /// See [`Pretty`].
526     ///
527     /// Note that this requires the "ansi" feature to be enabled.
528     ///
529     /// # Options
530     ///
531     /// [`Format::with_ansi`] can be used to disable ANSI terminal escape codes (which enable
532     /// formatting such as colors, bold, italic, etc) in event formatting. However, a field
533     /// formatter must be manually provided to avoid ANSI in the formatting of parent spans, like
534     /// so:
535     ///
536     /// ```
537     /// # use tracing_subscriber::fmt::format;
538     /// tracing_subscriber::fmt()
539     ///    .pretty()
540     ///    .with_ansi(false)
541     ///    .fmt_fields(format::PrettyFields::new().with_ansi(false))
542     ///    // ... other settings ...
543     ///    .init();
544     /// ```
545     #[cfg(feature = "ansi")]
546     #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
pretty(self) -> Format<Pretty, T>547     pub fn pretty(self) -> Format<Pretty, T> {
548         Format {
549             format: Pretty::default(),
550             timer: self.timer,
551             ansi: self.ansi,
552             display_target: self.display_target,
553             display_timestamp: self.display_timestamp,
554             display_level: self.display_level,
555             display_thread_id: self.display_thread_id,
556             display_thread_name: self.display_thread_name,
557         }
558     }
559 
560     /// Use the full JSON format.
561     ///
562     /// The full format includes fields from all entered spans.
563     ///
564     /// # Example Output
565     ///
566     /// ```ignore,json
567     /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate","fields":{"message":"some message", "key": "value"}}
568     /// ```
569     ///
570     /// # Options
571     ///
572     /// - [`Format::flatten_event`] can be used to enable flattening event fields into the root
573     /// object.
574     ///
575     /// [`Format::flatten_event`]: #method.flatten_event
576     #[cfg(feature = "json")]
577     #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
json(self) -> Format<Json, T>578     pub fn json(self) -> Format<Json, T> {
579         Format {
580             format: Json::default(),
581             timer: self.timer,
582             ansi: self.ansi,
583             display_target: self.display_target,
584             display_timestamp: self.display_timestamp,
585             display_level: self.display_level,
586             display_thread_id: self.display_thread_id,
587             display_thread_name: self.display_thread_name,
588         }
589     }
590 
591     /// Use the given [`timer`] for log message timestamps.
592     ///
593     /// See [`time` module] for the provided timer implementations.
594     ///
595     /// Note that using the `"time"` feature flag enables the
596     /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the
597     /// [`time` crate] to provide more sophisticated timestamp formatting
598     /// options.
599     ///
600     /// [`timer`]: super::time::FormatTime
601     /// [`time` module]: mod@super::time
602     /// [`UtcTime`]: super::time::UtcTime
603     /// [`LocalTime`]: super::time::LocalTime
604     /// [`time` crate]: https://docs.rs/time/0.3
with_timer<T2>(self, timer: T2) -> Format<F, T2>605     pub fn with_timer<T2>(self, timer: T2) -> Format<F, T2> {
606         Format {
607             format: self.format,
608             timer,
609             ansi: self.ansi,
610             display_target: self.display_target,
611             display_timestamp: self.display_timestamp,
612             display_level: self.display_level,
613             display_thread_id: self.display_thread_id,
614             display_thread_name: self.display_thread_name,
615         }
616     }
617 
618     /// Do not emit timestamps with log messages.
without_time(self) -> Format<F, ()>619     pub fn without_time(self) -> Format<F, ()> {
620         Format {
621             format: self.format,
622             timer: (),
623             ansi: self.ansi,
624             display_timestamp: false,
625             display_target: self.display_target,
626             display_level: self.display_level,
627             display_thread_id: self.display_thread_id,
628             display_thread_name: self.display_thread_name,
629         }
630     }
631 
632     /// Enable ANSI terminal colors for formatted output.
with_ansi(self, ansi: bool) -> Format<F, T>633     pub fn with_ansi(self, ansi: bool) -> Format<F, T> {
634         Format {
635             ansi: Some(ansi),
636             ..self
637         }
638     }
639 
640     /// Sets whether or not an event's target is displayed.
with_target(self, display_target: bool) -> Format<F, T>641     pub fn with_target(self, display_target: bool) -> Format<F, T> {
642         Format {
643             display_target,
644             ..self
645         }
646     }
647 
648     /// Sets whether or not an event's level is displayed.
with_level(self, display_level: bool) -> Format<F, T>649     pub fn with_level(self, display_level: bool) -> Format<F, T> {
650         Format {
651             display_level,
652             ..self
653         }
654     }
655 
656     /// Sets whether or not the [thread ID] of the current thread is displayed
657     /// when formatting events
658     ///
659     /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
with_thread_ids(self, display_thread_id: bool) -> Format<F, T>660     pub fn with_thread_ids(self, display_thread_id: bool) -> Format<F, T> {
661         Format {
662             display_thread_id,
663             ..self
664         }
665     }
666 
667     /// Sets whether or not the [name] of the current thread is displayed
668     /// when formatting events
669     ///
670     /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
with_thread_names(self, display_thread_name: bool) -> Format<F, T>671     pub fn with_thread_names(self, display_thread_name: bool) -> Format<F, T> {
672         Format {
673             display_thread_name,
674             ..self
675         }
676     }
677 
678     #[inline]
format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result where T: FormatTime,679     fn format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result
680     where
681         T: FormatTime,
682     {
683         // If timestamps are disabled, do nothing.
684         if !self.display_timestamp {
685             return Ok(());
686         }
687 
688         // If ANSI color codes are enabled, format the timestamp with ANSI
689         // colors.
690         #[cfg(feature = "ansi")]
691         {
692             if writer.has_ansi_escapes() {
693                 let style = Style::new().dimmed();
694                 write!(writer, "{}", style.prefix())?;
695                 self.timer.format_time(writer)?;
696                 write!(writer, "{} ", style.suffix())?;
697                 return Ok(());
698             }
699         }
700 
701         // Otherwise, just format the timestamp without ANSI formatting.
702         self.timer.format_time(writer)?;
703         writer.write_char(' ')
704     }
705 }
706 
707 #[cfg(feature = "json")]
708 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
709 impl<T> Format<Json, T> {
710     /// Use the full JSON format with the event's event fields flattened.
711     ///
712     /// # Example Output
713     ///
714     /// ```ignore,json
715     /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate", "message":"some message", "key": "value"}
716     /// ```
717     /// See [`Json`](../format/struct.Json.html).
718     #[cfg(feature = "json")]
719     #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
flatten_event(mut self, flatten_event: bool) -> Format<Json, T>720     pub fn flatten_event(mut self, flatten_event: bool) -> Format<Json, T> {
721         self.format.flatten_event(flatten_event);
722         self
723     }
724 
725     /// Sets whether or not the formatter will include the current span in
726     /// formatted events.
727     ///
728     /// See [`format::Json`](../fmt/format/struct.Json.html)
729     #[cfg(feature = "json")]
730     #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
with_current_span(mut self, display_current_span: bool) -> Format<Json, T>731     pub fn with_current_span(mut self, display_current_span: bool) -> Format<Json, T> {
732         self.format.with_current_span(display_current_span);
733         self
734     }
735 
736     /// Sets whether or not the formatter will include a list (from root to
737     /// leaf) of all currently entered spans in formatted events.
738     ///
739     /// See [`format::Json`](../fmt/format/struct.Json.html)
740     #[cfg(feature = "json")]
741     #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
with_span_list(mut self, display_span_list: bool) -> Format<Json, T>742     pub fn with_span_list(mut self, display_span_list: bool) -> Format<Json, T> {
743         self.format.with_span_list(display_span_list);
744         self
745     }
746 }
747 
748 impl<S, N, T> FormatEvent<S, N> for Format<Full, T>
749 where
750     S: Subscriber + for<'a> LookupSpan<'a>,
751     N: for<'a> FormatFields<'a> + 'static,
752     T: FormatTime,
753 {
format_event( &self, ctx: &FmtContext<'_, S, N>, mut writer: Writer<'_>, event: &Event<'_>, ) -> fmt::Result754     fn format_event(
755         &self,
756         ctx: &FmtContext<'_, S, N>,
757         mut writer: Writer<'_>,
758         event: &Event<'_>,
759     ) -> fmt::Result {
760         #[cfg(feature = "tracing-log")]
761         let normalized_meta = event.normalized_metadata();
762         #[cfg(feature = "tracing-log")]
763         let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
764         #[cfg(not(feature = "tracing-log"))]
765         let meta = event.metadata();
766 
767         // if the `Format` struct *also* has an ANSI color configuration,
768         // override the writer...the API for configuring ANSI color codes on the
769         // `Format` struct is deprecated, but we still need to honor those
770         // configurations.
771         if let Some(ansi) = self.ansi {
772             writer = writer.with_ansi(ansi);
773         }
774 
775         self.format_timestamp(&mut writer)?;
776 
777         if self.display_level {
778             let fmt_level = {
779                 #[cfg(feature = "ansi")]
780                 {
781                     FmtLevel::new(meta.level(), writer.has_ansi_escapes())
782                 }
783                 #[cfg(not(feature = "ansi"))]
784                 {
785                     FmtLevel::new(meta.level())
786                 }
787             };
788             write!(writer, "{} ", fmt_level)?;
789         }
790 
791         if self.display_thread_name {
792             let current_thread = std::thread::current();
793             match current_thread.name() {
794                 Some(name) => {
795                     write!(writer, "{} ", FmtThreadName::new(name))?;
796                 }
797                 // fall-back to thread id when name is absent and ids are not enabled
798                 None if !self.display_thread_id => {
799                     write!(writer, "{:0>2?} ", current_thread.id())?;
800                 }
801                 _ => {}
802             }
803         }
804 
805         if self.display_thread_id {
806             write!(writer, "{:0>2?} ", std::thread::current().id())?;
807         }
808 
809         let dimmed = writer.dimmed();
810 
811         if let Some(scope) = ctx.event_scope() {
812             let bold = writer.bold();
813 
814             let mut seen = false;
815 
816             for span in scope.from_root() {
817                 write!(writer, "{}", bold.paint(span.metadata().name()))?;
818                 seen = true;
819 
820                 let ext = span.extensions();
821                 if let Some(fields) = &ext.get::<FormattedFields<N>>() {
822                     if !fields.is_empty() {
823                         write!(writer, "{}{}{}", bold.paint("{"), fields, bold.paint("}"))?;
824                     }
825                 }
826                 write!(writer, "{}", dimmed.paint(":"))?;
827             }
828 
829             if seen {
830                 writer.write_char(' ')?;
831             }
832         };
833 
834         if self.display_target {
835             write!(
836                 writer,
837                 "{}{} ",
838                 dimmed.paint(meta.target()),
839                 dimmed.paint(":")
840             )?;
841         }
842 
843         ctx.format_fields(writer.by_ref(), event)?;
844         writeln!(writer)
845     }
846 }
847 
848 impl<S, N, T> FormatEvent<S, N> for Format<Compact, T>
849 where
850     S: Subscriber + for<'a> LookupSpan<'a>,
851     N: for<'a> FormatFields<'a> + 'static,
852     T: FormatTime,
853 {
format_event( &self, ctx: &FmtContext<'_, S, N>, mut writer: Writer<'_>, event: &Event<'_>, ) -> fmt::Result854     fn format_event(
855         &self,
856         ctx: &FmtContext<'_, S, N>,
857         mut writer: Writer<'_>,
858         event: &Event<'_>,
859     ) -> fmt::Result {
860         #[cfg(feature = "tracing-log")]
861         let normalized_meta = event.normalized_metadata();
862         #[cfg(feature = "tracing-log")]
863         let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
864         #[cfg(not(feature = "tracing-log"))]
865         let meta = event.metadata();
866 
867         // if the `Format` struct *also* has an ANSI color configuration,
868         // override the writer...the API for configuring ANSI color codes on the
869         // `Format` struct is deprecated, but we still need to honor those
870         // configurations.
871         if let Some(ansi) = self.ansi {
872             writer = writer.with_ansi(ansi);
873         }
874 
875         self.format_timestamp(&mut writer)?;
876 
877         if self.display_level {
878             let fmt_level = {
879                 #[cfg(feature = "ansi")]
880                 {
881                     FmtLevel::new(meta.level(), writer.has_ansi_escapes())
882                 }
883                 #[cfg(not(feature = "ansi"))]
884                 {
885                     FmtLevel::new(meta.level())
886                 }
887             };
888             write!(writer, "{} ", fmt_level)?;
889         }
890 
891         if self.display_thread_name {
892             let current_thread = std::thread::current();
893             match current_thread.name() {
894                 Some(name) => {
895                     write!(writer, "{} ", FmtThreadName::new(name))?;
896                 }
897                 // fall-back to thread id when name is absent and ids are not enabled
898                 None if !self.display_thread_id => {
899                     write!(writer, "{:0>2?} ", current_thread.id())?;
900                 }
901                 _ => {}
902             }
903         }
904 
905         if self.display_thread_id {
906             write!(writer, "{:0>2?} ", std::thread::current().id())?;
907         }
908 
909         let fmt_ctx = {
910             #[cfg(feature = "ansi")]
911             {
912                 FmtCtx::new(ctx, event.parent(), writer.has_ansi_escapes())
913             }
914             #[cfg(not(feature = "ansi"))]
915             {
916                 FmtCtx::new(&ctx, event.parent())
917             }
918         };
919         write!(writer, "{}", fmt_ctx)?;
920 
921         if self.display_target {
922             write!(
923                 writer,
924                 "{}{} ",
925                 writer.bold().paint(meta.target()),
926                 writer.dimmed().paint(":")
927             )?;
928         }
929 
930         ctx.format_fields(writer.by_ref(), event)?;
931 
932         let dimmed = writer.dimmed();
933         for span in ctx
934             .event_scope()
935             .into_iter()
936             .map(crate::registry::Scope::from_root)
937             .flatten()
938         {
939             let exts = span.extensions();
940             if let Some(fields) = exts.get::<FormattedFields<N>>() {
941                 if !fields.is_empty() {
942                     write!(writer, " {}", dimmed.paint(&fields.fields))?;
943                 }
944             }
945         }
946         writeln!(writer)
947     }
948 }
949 
950 // === impl FormatFields ===
951 impl<'writer, M> FormatFields<'writer> for M
952 where
953     M: MakeOutput<Writer<'writer>, fmt::Result>,
954     M::Visitor: VisitFmt + VisitOutput<fmt::Result>,
955 {
format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result956     fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result {
957         let mut v = self.make_visitor(writer);
958         fields.record(&mut v);
959         v.finish()
960     }
961 }
962 
963 /// The default [`FormatFields`] implementation.
964 ///
965 /// [`FormatFields`]: trait.FormatFields.html
966 #[derive(Debug)]
967 pub struct DefaultFields {
968     // reserve the ability to add fields to this without causing a breaking
969     // change in the future.
970     _private: (),
971 }
972 
973 /// The [visitor] produced by [`DefaultFields`]'s [`MakeVisitor`] implementation.
974 ///
975 /// [visitor]: super::super::field::Visit
976 /// [`MakeVisitor`]: super::super::field::MakeVisitor
977 #[derive(Debug)]
978 pub struct DefaultVisitor<'a> {
979     writer: Writer<'a>,
980     is_empty: bool,
981     result: fmt::Result,
982 }
983 
984 impl DefaultFields {
985     /// Returns a new default [`FormatFields`] implementation.
986     ///
987     /// [`FormatFields`]: trait.FormatFields.html
new() -> Self988     pub fn new() -> Self {
989         Self { _private: () }
990     }
991 }
992 
993 impl Default for DefaultFields {
default() -> Self994     fn default() -> Self {
995         Self::new()
996     }
997 }
998 
999 impl<'a> MakeVisitor<Writer<'a>> for DefaultFields {
1000     type Visitor = DefaultVisitor<'a>;
1001 
1002     #[inline]
make_visitor(&self, target: Writer<'a>) -> Self::Visitor1003     fn make_visitor(&self, target: Writer<'a>) -> Self::Visitor {
1004         DefaultVisitor::new(target, true)
1005     }
1006 }
1007 
1008 // === impl DefaultVisitor ===
1009 
1010 impl<'a> DefaultVisitor<'a> {
1011     /// Returns a new default visitor that formats to the provided `writer`.
1012     ///
1013     /// # Arguments
1014     /// - `writer`: the writer to format to.
1015     /// - `is_empty`: whether or not any fields have been previously written to
1016     ///   that writer.
new(writer: Writer<'a>, is_empty: bool) -> Self1017     pub fn new(writer: Writer<'a>, is_empty: bool) -> Self {
1018         Self {
1019             writer,
1020             is_empty,
1021             result: Ok(()),
1022         }
1023     }
1024 
maybe_pad(&mut self)1025     fn maybe_pad(&mut self) {
1026         if self.is_empty {
1027             self.is_empty = false;
1028         } else {
1029             self.result = write!(self.writer, " ");
1030         }
1031     }
1032 }
1033 
1034 impl<'a> field::Visit for DefaultVisitor<'a> {
record_str(&mut self, field: &Field, value: &str)1035     fn record_str(&mut self, field: &Field, value: &str) {
1036         if self.result.is_err() {
1037             return;
1038         }
1039 
1040         if field.name() == "message" {
1041             self.record_debug(field, &format_args!("{}", value))
1042         } else {
1043             self.record_debug(field, &value)
1044         }
1045     }
1046 
record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static))1047     fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
1048         if let Some(source) = value.source() {
1049             let italic = self.writer.italic();
1050             self.record_debug(
1051                 field,
1052                 &format_args!(
1053                     "{} {}{}{}{}",
1054                     value,
1055                     italic.paint(field.name()),
1056                     italic.paint(".sources"),
1057                     self.writer.dimmed().paint("="),
1058                     ErrorSourceList(source)
1059                 ),
1060             )
1061         } else {
1062             self.record_debug(field, &format_args!("{}", value))
1063         }
1064     }
1065 
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)1066     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
1067         if self.result.is_err() {
1068             return;
1069         }
1070 
1071         self.maybe_pad();
1072         self.result = match field.name() {
1073             "message" => write!(self.writer, "{:?}", value),
1074             // Skip fields that are actually log metadata that have already been handled
1075             #[cfg(feature = "tracing-log")]
1076             name if name.starts_with("log.") => Ok(()),
1077             name if name.starts_with("r#") => write!(
1078                 self.writer,
1079                 "{}{}{:?}",
1080                 self.writer.italic().paint(&name[2..]),
1081                 self.writer.dimmed().paint("="),
1082                 value
1083             ),
1084             name => write!(
1085                 self.writer,
1086                 "{}{}{:?}",
1087                 self.writer.italic().paint(name),
1088                 self.writer.dimmed().paint("="),
1089                 value
1090             ),
1091         };
1092     }
1093 }
1094 
1095 impl<'a> crate::field::VisitOutput<fmt::Result> for DefaultVisitor<'a> {
finish(self) -> fmt::Result1096     fn finish(self) -> fmt::Result {
1097         self.result
1098     }
1099 }
1100 
1101 impl<'a> crate::field::VisitFmt for DefaultVisitor<'a> {
writer(&mut self) -> &mut dyn fmt::Write1102     fn writer(&mut self) -> &mut dyn fmt::Write {
1103         &mut self.writer
1104     }
1105 }
1106 
1107 /// Renders an error into a list of sources, *including* the error
1108 struct ErrorSourceList<'a>(&'a (dyn std::error::Error + 'static));
1109 
1110 impl<'a> Display for ErrorSourceList<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1111     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1112         let mut list = f.debug_list();
1113         let mut curr = Some(self.0);
1114         while let Some(curr_err) = curr {
1115             list.entry(&format_args!("{}", curr_err));
1116             curr = curr_err.source();
1117         }
1118         list.finish()
1119     }
1120 }
1121 
1122 struct FmtCtx<'a, S, N> {
1123     ctx: &'a FmtContext<'a, S, N>,
1124     span: Option<&'a span::Id>,
1125     #[cfg(feature = "ansi")]
1126     ansi: bool,
1127 }
1128 
1129 impl<'a, S, N: 'a> FmtCtx<'a, S, N>
1130 where
1131     S: Subscriber + for<'lookup> LookupSpan<'lookup>,
1132     N: for<'writer> FormatFields<'writer> + 'static,
1133 {
1134     #[cfg(feature = "ansi")]
new( ctx: &'a FmtContext<'_, S, N>, span: Option<&'a span::Id>, ansi: bool, ) -> Self1135     pub(crate) fn new(
1136         ctx: &'a FmtContext<'_, S, N>,
1137         span: Option<&'a span::Id>,
1138         ansi: bool,
1139     ) -> Self {
1140         Self { ctx, span, ansi }
1141     }
1142 
1143     #[cfg(not(feature = "ansi"))]
new(ctx: &'a FmtContext<'_, S, N>, span: Option<&'a span::Id>) -> Self1144     pub(crate) fn new(ctx: &'a FmtContext<'_, S, N>, span: Option<&'a span::Id>) -> Self {
1145         Self { ctx, span }
1146     }
1147 
bold(&self) -> Style1148     fn bold(&self) -> Style {
1149         #[cfg(feature = "ansi")]
1150         {
1151             if self.ansi {
1152                 return Style::new().bold();
1153             }
1154         }
1155 
1156         Style::new()
1157     }
1158 }
1159 
1160 impl<'a, S, N: 'a> fmt::Display for FmtCtx<'a, S, N>
1161 where
1162     S: Subscriber + for<'lookup> LookupSpan<'lookup>,
1163     N: for<'writer> FormatFields<'writer> + 'static,
1164 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1165     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1166         let bold = self.bold();
1167         let mut seen = false;
1168 
1169         let span = self
1170             .span
1171             .and_then(|id| self.ctx.ctx.span(id))
1172             .or_else(|| self.ctx.ctx.lookup_current());
1173 
1174         let scope = span.into_iter().flat_map(|span| span.scope().from_root());
1175 
1176         for span in scope {
1177             seen = true;
1178             write!(f, "{}:", bold.paint(span.metadata().name()))?;
1179         }
1180 
1181         if seen {
1182             f.write_char(' ')?;
1183         }
1184         Ok(())
1185     }
1186 }
1187 
1188 #[cfg(not(feature = "ansi"))]
1189 struct Style;
1190 
1191 #[cfg(not(feature = "ansi"))]
1192 impl Style {
new() -> Self1193     fn new() -> Self {
1194         Style
1195     }
1196 
bold(self) -> Self1197     fn bold(self) -> Self {
1198         self
1199     }
1200 
paint(&self, d: impl fmt::Display) -> impl fmt::Display1201     fn paint(&self, d: impl fmt::Display) -> impl fmt::Display {
1202         d
1203     }
1204 }
1205 
1206 struct FmtThreadName<'a> {
1207     name: &'a str,
1208 }
1209 
1210 impl<'a> FmtThreadName<'a> {
new(name: &'a str) -> Self1211     pub(crate) fn new(name: &'a str) -> Self {
1212         Self { name }
1213     }
1214 }
1215 
1216 impl<'a> fmt::Display for FmtThreadName<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1217     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1218         use std::sync::atomic::{
1219             AtomicUsize,
1220             Ordering::{AcqRel, Acquire, Relaxed},
1221         };
1222 
1223         // Track the longest thread name length we've seen so far in an atomic,
1224         // so that it can be updated by any thread.
1225         static MAX_LEN: AtomicUsize = AtomicUsize::new(0);
1226         let len = self.name.len();
1227         // Snapshot the current max thread name length.
1228         let mut max_len = MAX_LEN.load(Relaxed);
1229 
1230         while len > max_len {
1231             // Try to set a new max length, if it is still the value we took a
1232             // snapshot of.
1233             match MAX_LEN.compare_exchange(max_len, len, AcqRel, Acquire) {
1234                 // We successfully set the new max value
1235                 Ok(_) => break,
1236                 // Another thread set a new max value since we last observed
1237                 // it! It's possible that the new length is actually longer than
1238                 // ours, so we'll loop again and check whether our length is
1239                 // still the longest. If not, we'll just use the newer value.
1240                 Err(actual) => max_len = actual,
1241             }
1242         }
1243 
1244         // pad thread name using `max_len`
1245         write!(f, "{:>width$}", self.name, width = max_len)
1246     }
1247 }
1248 
1249 struct FmtLevel<'a> {
1250     level: &'a Level,
1251     #[cfg(feature = "ansi")]
1252     ansi: bool,
1253 }
1254 
1255 impl<'a> FmtLevel<'a> {
1256     #[cfg(feature = "ansi")]
new(level: &'a Level, ansi: bool) -> Self1257     pub(crate) fn new(level: &'a Level, ansi: bool) -> Self {
1258         Self { level, ansi }
1259     }
1260 
1261     #[cfg(not(feature = "ansi"))]
new(level: &'a Level) -> Self1262     pub(crate) fn new(level: &'a Level) -> Self {
1263         Self { level }
1264     }
1265 }
1266 
1267 const TRACE_STR: &str = "TRACE";
1268 const DEBUG_STR: &str = "DEBUG";
1269 const INFO_STR: &str = " INFO";
1270 const WARN_STR: &str = " WARN";
1271 const ERROR_STR: &str = "ERROR";
1272 
1273 #[cfg(not(feature = "ansi"))]
1274 impl<'a> fmt::Display for FmtLevel<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1275     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1276         match *self.level {
1277             Level::TRACE => f.pad(TRACE_STR),
1278             Level::DEBUG => f.pad(DEBUG_STR),
1279             Level::INFO => f.pad(INFO_STR),
1280             Level::WARN => f.pad(WARN_STR),
1281             Level::ERROR => f.pad(ERROR_STR),
1282         }
1283     }
1284 }
1285 
1286 #[cfg(feature = "ansi")]
1287 impl<'a> fmt::Display for FmtLevel<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1288     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1289         if self.ansi {
1290             match *self.level {
1291                 Level::TRACE => write!(f, "{}", Colour::Purple.paint(TRACE_STR)),
1292                 Level::DEBUG => write!(f, "{}", Colour::Blue.paint(DEBUG_STR)),
1293                 Level::INFO => write!(f, "{}", Colour::Green.paint(INFO_STR)),
1294                 Level::WARN => write!(f, "{}", Colour::Yellow.paint(WARN_STR)),
1295                 Level::ERROR => write!(f, "{}", Colour::Red.paint(ERROR_STR)),
1296             }
1297         } else {
1298             match *self.level {
1299                 Level::TRACE => f.pad(TRACE_STR),
1300                 Level::DEBUG => f.pad(DEBUG_STR),
1301                 Level::INFO => f.pad(INFO_STR),
1302                 Level::WARN => f.pad(WARN_STR),
1303                 Level::ERROR => f.pad(ERROR_STR),
1304             }
1305         }
1306     }
1307 }
1308 
1309 // === impl FieldFn ===
1310 
1311 impl<'a, F> MakeVisitor<Writer<'a>> for FieldFn<F>
1312 where
1313     F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone,
1314 {
1315     type Visitor = FieldFnVisitor<'a, F>;
1316 
make_visitor(&self, writer: Writer<'a>) -> Self::Visitor1317     fn make_visitor(&self, writer: Writer<'a>) -> Self::Visitor {
1318         FieldFnVisitor {
1319             writer,
1320             f: self.0.clone(),
1321             result: Ok(()),
1322         }
1323     }
1324 }
1325 
1326 impl<'a, F> Visit for FieldFnVisitor<'a, F>
1327 where
1328     F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result,
1329 {
record_debug(&mut self, field: &Field, value: &dyn fmt::Debug)1330     fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
1331         if self.result.is_ok() {
1332             self.result = (self.f)(&mut self.writer, field, value)
1333         }
1334     }
1335 }
1336 
1337 impl<'a, F> VisitOutput<fmt::Result> for FieldFnVisitor<'a, F>
1338 where
1339     F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result,
1340 {
finish(self) -> fmt::Result1341     fn finish(self) -> fmt::Result {
1342         self.result
1343     }
1344 }
1345 
1346 impl<'a, F> VisitFmt for FieldFnVisitor<'a, F>
1347 where
1348     F: Fn(&mut Writer<'a>, &Field, &dyn fmt::Debug) -> fmt::Result,
1349 {
writer(&mut self) -> &mut dyn fmt::Write1350     fn writer(&mut self) -> &mut dyn fmt::Write {
1351         &mut self.writer
1352     }
1353 }
1354 
1355 impl<'a, F> fmt::Debug for FieldFnVisitor<'a, F> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1356     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1357         f.debug_struct("FieldFnVisitor")
1358             .field("f", &format_args!("{}", std::any::type_name::<F>()))
1359             .field("writer", &self.writer)
1360             .field("result", &self.result)
1361             .finish()
1362     }
1363 }
1364 
1365 // === printing synthetic Span events ===
1366 
1367 /// Configures what points in the span lifecycle are logged as events.
1368 ///
1369 /// See also [`with_span_events`](../struct.SubscriberBuilder.html#method.with_span_events).
1370 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
1371 pub struct FmtSpan(u8);
1372 
1373 impl FmtSpan {
1374     /// one event when span is created
1375     pub const NEW: FmtSpan = FmtSpan(1 << 0);
1376     /// one event per enter of a span
1377     pub const ENTER: FmtSpan = FmtSpan(1 << 1);
1378     /// one event per exit of a span
1379     pub const EXIT: FmtSpan = FmtSpan(1 << 2);
1380     /// one event when the span is dropped
1381     pub const CLOSE: FmtSpan = FmtSpan(1 << 3);
1382 
1383     /// spans are ignored (this is the default)
1384     pub const NONE: FmtSpan = FmtSpan(0);
1385     /// one event per enter/exit of a span
1386     pub const ACTIVE: FmtSpan = FmtSpan(FmtSpan::ENTER.0 | FmtSpan::EXIT.0);
1387     /// events at all points (new, enter, exit, drop)
1388     pub const FULL: FmtSpan =
1389         FmtSpan(FmtSpan::NEW.0 | FmtSpan::ENTER.0 | FmtSpan::EXIT.0 | FmtSpan::CLOSE.0);
1390 
1391     /// Check whether or not a certain flag is set for this [`FmtSpan`]
contains(&self, other: FmtSpan) -> bool1392     fn contains(&self, other: FmtSpan) -> bool {
1393         self.clone() & other.clone() == other
1394     }
1395 }
1396 
1397 macro_rules! impl_fmt_span_bit_op {
1398     ($trait:ident, $func:ident, $op:tt) => {
1399         impl std::ops::$trait for FmtSpan {
1400             type Output = FmtSpan;
1401 
1402             fn $func(self, rhs: Self) -> Self::Output {
1403                 FmtSpan(self.0 $op rhs.0)
1404             }
1405         }
1406     };
1407 }
1408 
1409 macro_rules! impl_fmt_span_bit_assign_op {
1410     ($trait:ident, $func:ident, $op:tt) => {
1411         impl std::ops::$trait for FmtSpan {
1412             fn $func(&mut self, rhs: Self) {
1413                 *self = FmtSpan(self.0 $op rhs.0)
1414             }
1415         }
1416     };
1417 }
1418 
1419 impl_fmt_span_bit_op!(BitAnd, bitand, &);
1420 impl_fmt_span_bit_op!(BitOr, bitor, |);
1421 impl_fmt_span_bit_op!(BitXor, bitxor, ^);
1422 
1423 impl_fmt_span_bit_assign_op!(BitAndAssign, bitand_assign, &);
1424 impl_fmt_span_bit_assign_op!(BitOrAssign, bitor_assign, |);
1425 impl_fmt_span_bit_assign_op!(BitXorAssign, bitxor_assign, ^);
1426 
1427 impl Debug for FmtSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1428     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1429         let mut wrote_flag = false;
1430         let mut write_flags = |flag, flag_str| -> fmt::Result {
1431             if self.contains(flag) {
1432                 if wrote_flag {
1433                     f.write_str(" | ")?;
1434                 }
1435 
1436                 f.write_str(flag_str)?;
1437                 wrote_flag = true;
1438             }
1439 
1440             Ok(())
1441         };
1442 
1443         if FmtSpan::NONE | self.clone() == FmtSpan::NONE {
1444             f.write_str("FmtSpan::NONE")?;
1445         } else {
1446             write_flags(FmtSpan::NEW, "FmtSpan::NEW")?;
1447             write_flags(FmtSpan::ENTER, "FmtSpan::ENTER")?;
1448             write_flags(FmtSpan::EXIT, "FmtSpan::EXIT")?;
1449             write_flags(FmtSpan::CLOSE, "FmtSpan::CLOSE")?;
1450         }
1451 
1452         Ok(())
1453     }
1454 }
1455 
1456 pub(super) struct FmtSpanConfig {
1457     pub(super) kind: FmtSpan,
1458     pub(super) fmt_timing: bool,
1459 }
1460 
1461 impl FmtSpanConfig {
without_time(self) -> Self1462     pub(super) fn without_time(self) -> Self {
1463         Self {
1464             kind: self.kind,
1465             fmt_timing: false,
1466         }
1467     }
with_kind(self, kind: FmtSpan) -> Self1468     pub(super) fn with_kind(self, kind: FmtSpan) -> Self {
1469         Self {
1470             kind,
1471             fmt_timing: self.fmt_timing,
1472         }
1473     }
trace_new(&self) -> bool1474     pub(super) fn trace_new(&self) -> bool {
1475         self.kind.contains(FmtSpan::NEW)
1476     }
trace_enter(&self) -> bool1477     pub(super) fn trace_enter(&self) -> bool {
1478         self.kind.contains(FmtSpan::ENTER)
1479     }
trace_exit(&self) -> bool1480     pub(super) fn trace_exit(&self) -> bool {
1481         self.kind.contains(FmtSpan::EXIT)
1482     }
trace_close(&self) -> bool1483     pub(super) fn trace_close(&self) -> bool {
1484         self.kind.contains(FmtSpan::CLOSE)
1485     }
1486 }
1487 
1488 impl Debug for FmtSpanConfig {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1489     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1490         self.kind.fmt(f)
1491     }
1492 }
1493 
1494 impl Default for FmtSpanConfig {
default() -> Self1495     fn default() -> Self {
1496         Self {
1497             kind: FmtSpan::NONE,
1498             fmt_timing: true,
1499         }
1500     }
1501 }
1502 
1503 pub(super) struct TimingDisplay(pub(super) u64);
1504 impl Display for TimingDisplay {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1505     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1506         let mut t = self.0 as f64;
1507         for unit in ["ns", "µs", "ms", "s"].iter() {
1508             if t < 10.0 {
1509                 return write!(f, "{:.2}{}", t, unit);
1510             } else if t < 100.0 {
1511                 return write!(f, "{:.1}{}", t, unit);
1512             } else if t < 1000.0 {
1513                 return write!(f, "{:.0}{}", t, unit);
1514             }
1515             t /= 1000.0;
1516         }
1517         write!(f, "{:.0}s", t * 1000.0)
1518     }
1519 }
1520 
1521 #[cfg(test)]
1522 pub(super) mod test {
1523     use crate::fmt::{test::MockMakeWriter, time::FormatTime};
1524     use tracing::{
1525         self,
1526         dispatcher::{set_default, Dispatch},
1527         subscriber::with_default,
1528     };
1529 
1530     use super::*;
1531     use std::fmt;
1532 
1533     pub(crate) struct MockTime;
1534     impl FormatTime for MockTime {
format_time(&self, w: &mut Writer<'_>) -> fmt::Result1535         fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
1536             write!(w, "fake time")
1537         }
1538     }
1539 
1540     #[test]
disable_everything()1541     fn disable_everything() {
1542         // This test reproduces https://github.com/tokio-rs/tracing/issues/1354
1543         let make_writer = MockMakeWriter::default();
1544         let subscriber = crate::fmt::Subscriber::builder()
1545             .with_writer(make_writer.clone())
1546             .without_time()
1547             .with_level(false)
1548             .with_target(false)
1549             .with_thread_ids(false)
1550             .with_thread_names(false);
1551         #[cfg(feature = "ansi")]
1552         let subscriber = subscriber.with_ansi(false);
1553         run_test(subscriber, make_writer, "hello\n")
1554     }
1555 
test_ansi<T>( is_ansi: bool, expected: &str, builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, ) where Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, T: Send + Sync + 'static,1556     fn test_ansi<T>(
1557         is_ansi: bool,
1558         expected: &str,
1559         builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>,
1560     ) where
1561         Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>,
1562         T: Send + Sync + 'static,
1563     {
1564         let make_writer = MockMakeWriter::default();
1565         let subscriber = builder
1566             .with_writer(make_writer.clone())
1567             .with_ansi(is_ansi)
1568             .with_timer(MockTime);
1569         run_test(subscriber, make_writer, expected)
1570     }
1571 
1572     #[cfg(not(feature = "ansi"))]
test_without_ansi<T>( expected: &str, builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, ) where Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, T: Send + Sync,1573     fn test_without_ansi<T>(
1574         expected: &str,
1575         builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>,
1576     ) where
1577         Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>,
1578         T: Send + Sync,
1579     {
1580         let make_writer = MockMakeWriter::default();
1581         let subscriber = builder.with_writer(make_writer).with_timer(MockTime);
1582         run_test(subscriber, make_writer, expected)
1583     }
1584 
test_without_level<T>( expected: &str, builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, ) where Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, T: Send + Sync + 'static,1585     fn test_without_level<T>(
1586         expected: &str,
1587         builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>,
1588     ) where
1589         Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>,
1590         T: Send + Sync + 'static,
1591     {
1592         let make_writer = MockMakeWriter::default();
1593         let subscriber = builder
1594             .with_writer(make_writer.clone())
1595             .with_level(false)
1596             .with_ansi(false)
1597             .with_timer(MockTime);
1598         run_test(subscriber, make_writer, expected);
1599     }
1600 
test_overridden_parents<T>( expected: &str, builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, ) where Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, T: Send + Sync + 'static,1601     fn test_overridden_parents<T>(
1602         expected: &str,
1603         builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>,
1604     ) where
1605         Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>,
1606         T: Send + Sync + 'static,
1607     {
1608         let make_writer = MockMakeWriter::default();
1609         let collector = builder
1610             .with_writer(make_writer.clone())
1611             .with_level(false)
1612             .with_ansi(false)
1613             .with_timer(MockTime)
1614             .finish();
1615 
1616         with_default(collector, || {
1617             let span1 = tracing::info_span!("span1", span = 1);
1618             let span2 = tracing::info_span!(parent: &span1, "span2", span = 2);
1619             tracing::info!(parent: &span2, "hello");
1620         });
1621         assert_eq!(expected, make_writer.get_string());
1622     }
1623 
test_overridden_parents_in_scope<T>( expected1: &str, expected2: &str, builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>, ) where Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>, T: Send + Sync + 'static,1624     fn test_overridden_parents_in_scope<T>(
1625         expected1: &str,
1626         expected2: &str,
1627         builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>,
1628     ) where
1629         Format<T, MockTime>: FormatEvent<crate::Registry, DefaultFields>,
1630         T: Send + Sync + 'static,
1631     {
1632         let make_writer = MockMakeWriter::default();
1633         let subscriber = builder
1634             .with_writer(make_writer.clone())
1635             .with_level(false)
1636             .with_ansi(false)
1637             .with_timer(MockTime)
1638             .finish();
1639 
1640         with_default(subscriber, || {
1641             let span1 = tracing::info_span!("span1", span = 1);
1642             let span2 = tracing::info_span!(parent: &span1, "span2", span = 2);
1643             let span3 = tracing::info_span!("span3", span = 3);
1644             let _e3 = span3.enter();
1645 
1646             tracing::info!("hello");
1647             assert_eq!(expected1, make_writer.get_string().as_str());
1648 
1649             tracing::info!(parent: &span2, "hello");
1650             assert_eq!(expected2, make_writer.get_string().as_str());
1651         });
1652     }
1653 
run_test(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str)1654     fn run_test(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) {
1655         let _default = set_default(&subscriber.into());
1656         tracing::info!("hello");
1657         assert_eq!(expected, buf.get_string())
1658     }
1659 
1660     mod default {
1661         use super::*;
1662         #[cfg(feature = "ansi")]
1663         #[test]
with_ansi_true()1664         fn with_ansi_true() {
1665             let expected = "\u{1b}[2mfake time\u{1b}[0m \u{1b}[32m INFO\u{1b}[0m \u{1b}[2mtracing_subscriber::fmt::format::test\u{1b}[0m\u{1b}[2m:\u{1b}[0m hello\n";
1666             test_ansi(true, expected, crate::fmt::Subscriber::builder());
1667         }
1668 
1669         #[cfg(feature = "ansi")]
1670         #[test]
with_ansi_false()1671         fn with_ansi_false() {
1672             let expected = "fake time  INFO tracing_subscriber::fmt::format::test: hello\n";
1673             test_ansi(false, expected, crate::fmt::Subscriber::builder());
1674         }
1675 
1676         #[cfg(not(feature = "ansi"))]
1677         #[test]
without_ansi()1678         fn without_ansi() {
1679             let expected = "fake time  INFO tracing_subscriber::fmt::format::test: hello\n";
1680             test_without_ansi(expected, crate::fmt::Subscriber::builder())
1681         }
1682 
1683         #[test]
without_level()1684         fn without_level() {
1685             let expected = "fake time tracing_subscriber::fmt::format::test: hello\n";
1686             test_without_level(expected, crate::fmt::Subscriber::builder())
1687         }
1688 
1689         #[test]
overridden_parents()1690         fn overridden_parents() {
1691             let expected = "fake time span1{span=1}:span2{span=2}: tracing_subscriber::fmt::format::test: hello\n";
1692             test_overridden_parents(expected, crate::fmt::Subscriber::builder())
1693         }
1694 
1695         #[test]
overridden_parents_in_scope()1696         fn overridden_parents_in_scope() {
1697             test_overridden_parents_in_scope(
1698                 "fake time span3{span=3}: tracing_subscriber::fmt::format::test: hello\n",
1699                 "fake time span1{span=1}:span2{span=2}: tracing_subscriber::fmt::format::test: hello\n",
1700                 crate::fmt::Subscriber::builder(),
1701             )
1702         }
1703     }
1704 
1705     mod compact {
1706         use super::*;
1707 
1708         #[cfg(feature = "ansi")]
1709         #[test]
with_ansi_true()1710         fn with_ansi_true() {
1711             let expected = "\u{1b}[2mfake time\u{1b}[0m \u{1b}[32m INFO\u{1b}[0m \u{1b}[1mtracing_subscriber::fmt::format::test\u{1b}[0m\u{1b}[2m:\u{1b}[0m hello\n";
1712             test_ansi(true, expected, crate::fmt::Subscriber::builder().compact())
1713         }
1714 
1715         #[cfg(feature = "ansi")]
1716         #[test]
with_ansi_false()1717         fn with_ansi_false() {
1718             let expected = "fake time  INFO tracing_subscriber::fmt::format::test: hello\n";
1719             test_ansi(false, expected, crate::fmt::Subscriber::builder().compact());
1720         }
1721 
1722         #[cfg(not(feature = "ansi"))]
1723         #[test]
without_ansi()1724         fn without_ansi() {
1725             let expected = "fake time  INFO tracing_subscriber::fmt::format::test: hello\n";
1726             test_without_ansi(expected, crate::fmt::Subscriber::builder().compact())
1727         }
1728 
1729         #[test]
without_level()1730         fn without_level() {
1731             let expected = "fake time tracing_subscriber::fmt::format::test: hello\n";
1732             test_without_level(expected, crate::fmt::Subscriber::builder().compact());
1733         }
1734 
1735         #[test]
overridden_parents()1736         fn overridden_parents() {
1737             let expected = "fake time span1:span2: tracing_subscriber::fmt::format::test: hello span=1 span=2\n";
1738             test_overridden_parents(expected, crate::fmt::Subscriber::builder().compact())
1739         }
1740 
1741         #[test]
overridden_parents_in_scope()1742         fn overridden_parents_in_scope() {
1743             test_overridden_parents_in_scope(
1744                 "fake time span3: tracing_subscriber::fmt::format::test: hello span=3\n",
1745                 "fake time span1:span2: tracing_subscriber::fmt::format::test: hello span=1 span=2\n",
1746                 crate::fmt::Subscriber::builder().compact(),
1747             )
1748         }
1749     }
1750 
1751     #[test]
format_nanos()1752     fn format_nanos() {
1753         fn fmt(t: u64) -> String {
1754             TimingDisplay(t).to_string()
1755         }
1756 
1757         assert_eq!(fmt(1), "1.00ns");
1758         assert_eq!(fmt(12), "12.0ns");
1759         assert_eq!(fmt(123), "123ns");
1760         assert_eq!(fmt(1234), "1.23µs");
1761         assert_eq!(fmt(12345), "12.3µs");
1762         assert_eq!(fmt(123456), "123µs");
1763         assert_eq!(fmt(1234567), "1.23ms");
1764         assert_eq!(fmt(12345678), "12.3ms");
1765         assert_eq!(fmt(123456789), "123ms");
1766         assert_eq!(fmt(1234567890), "1.23s");
1767         assert_eq!(fmt(12345678901), "12.3s");
1768         assert_eq!(fmt(123456789012), "123s");
1769         assert_eq!(fmt(1234567890123), "1235s");
1770     }
1771 
1772     #[test]
fmt_span_combinations()1773     fn fmt_span_combinations() {
1774         let f = FmtSpan::NONE;
1775         assert!(!f.contains(FmtSpan::NEW));
1776         assert!(!f.contains(FmtSpan::ENTER));
1777         assert!(!f.contains(FmtSpan::EXIT));
1778         assert!(!f.contains(FmtSpan::CLOSE));
1779 
1780         let f = FmtSpan::ACTIVE;
1781         assert!(!f.contains(FmtSpan::NEW));
1782         assert!(f.contains(FmtSpan::ENTER));
1783         assert!(f.contains(FmtSpan::EXIT));
1784         assert!(!f.contains(FmtSpan::CLOSE));
1785 
1786         let f = FmtSpan::FULL;
1787         assert!(f.contains(FmtSpan::NEW));
1788         assert!(f.contains(FmtSpan::ENTER));
1789         assert!(f.contains(FmtSpan::EXIT));
1790         assert!(f.contains(FmtSpan::CLOSE));
1791 
1792         let f = FmtSpan::NEW | FmtSpan::CLOSE;
1793         assert!(f.contains(FmtSpan::NEW));
1794         assert!(!f.contains(FmtSpan::ENTER));
1795         assert!(!f.contains(FmtSpan::EXIT));
1796         assert!(f.contains(FmtSpan::CLOSE));
1797     }
1798 }
1799