• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Abstractions for creating [`io::Write`] instances.
2 //!
3 //! [`io::Write`]: std::io::Write
4 use std::{
5     fmt,
6     io::{self, Write},
7     sync::{Arc, Mutex, MutexGuard},
8 };
9 use tracing_core::Metadata;
10 
11 /// A type that can create [`io::Write`] instances.
12 ///
13 /// `MakeWriter` is used by [`fmt::Layer`] or [`fmt::Subscriber`] to print
14 /// formatted text representations of [`Event`]s.
15 ///
16 /// This trait is already implemented for function pointers and
17 /// immutably-borrowing closures that return an instance of [`io::Write`], such
18 /// as [`io::stdout`] and [`io::stderr`]. Additionally, it is implemented for
19 /// [`std::sync::Mutex`][mutex] when the tyoe inside the mutex implements
20 /// [`io::Write`].
21 ///
22 /// # Examples
23 ///
24 /// The simplest usage is to pass in a named function that returns a writer. For
25 /// example, to log all events to stderr, we could write:
26 /// ```
27 /// let subscriber = tracing_subscriber::fmt()
28 ///     .with_writer(std::io::stderr)
29 ///     .finish();
30 /// # drop(subscriber);
31 /// ```
32 ///
33 /// Any function that returns a writer can be used:
34 ///
35 /// ```
36 /// fn make_my_great_writer() -> impl std::io::Write {
37 ///     // ...
38 ///     # std::io::stdout()
39 /// }
40 ///
41 /// let subscriber = tracing_subscriber::fmt()
42 ///     .with_writer(make_my_great_writer)
43 ///     .finish();
44 /// # drop(subscriber);
45 /// ```
46 ///
47 /// A closure can be used to introduce arbitrary logic into how the writer is
48 /// created. Consider the (admittedly rather silly) example of sending every 5th
49 /// event to stderr, and all other events to stdout:
50 ///
51 /// ```
52 /// use std::io;
53 /// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
54 ///
55 /// let n = AtomicUsize::new(0);
56 /// let subscriber = tracing_subscriber::fmt()
57 ///     .with_writer(move || -> Box<dyn io::Write> {
58 ///         if n.fetch_add(1, Relaxed) % 5 == 0 {
59 ///             Box::new(io::stderr())
60 ///         } else {
61 ///             Box::new(io::stdout())
62 ///        }
63 ///     })
64 ///     .finish();
65 /// # drop(subscriber);
66 /// ```
67 ///
68 /// A single instance of a type implementing [`io::Write`] may be used as a
69 /// `MakeWriter` by wrapping it in a [`Mutex`][mutex]. For example, we could
70 /// write to a file like so:
71 ///
72 /// ```
73 /// use std::{fs::File, sync::Mutex};
74 ///
75 /// # fn docs() -> Result<(), Box<dyn std::error::Error>> {
76 /// let log_file = File::create("my_cool_trace.log")?;
77 /// let subscriber = tracing_subscriber::fmt()
78 ///     .with_writer(Mutex::new(log_file))
79 ///     .finish();
80 /// # drop(subscriber);
81 /// # Ok(())
82 /// # }
83 /// ```
84 ///
85 /// [`io::Write`]: std::io::Write
86 /// [`fmt::Layer`]: crate::fmt::Layer
87 /// [`fmt::Subscriber`]: crate::fmt::Subscriber
88 /// [`Event`]: tracing_core::event::Event
89 /// [`io::stdout`]: std::io::stdout()
90 /// [`io::stderr`]: std::io::stderr()
91 /// [mutex]: std::sync::Mutex
92 /// [`MakeWriter::make_writer_for`]: MakeWriter::make_writer_for
93 /// [`Metadata`]: tracing_core::Metadata
94 /// [levels]: tracing_core::Level
95 /// [targets]: tracing_core::Metadata::target
96 pub trait MakeWriter<'a> {
97     /// The concrete [`io::Write`] implementation returned by [`make_writer`].
98     ///
99     /// [`io::Write`]: std::io::Write
100     /// [`make_writer`]: MakeWriter::make_writer
101     type Writer: io::Write;
102 
103     /// Returns an instance of [`Writer`].
104     ///
105     /// # Implementer notes
106     ///
107     /// [`fmt::Layer`] or [`fmt::Subscriber`] will call this method each time an event is recorded. Ensure any state
108     /// that must be saved across writes is not lost when the [`Writer`] instance is dropped. If
109     /// creating a [`io::Write`] instance is expensive, be sure to cache it when implementing
110     /// [`MakeWriter`] to improve performance.
111     ///
112     /// [`Writer`]: MakeWriter::Writer
113     /// [`fmt::Layer`]: crate::fmt::Layer
114     /// [`fmt::Subscriber`]: crate::fmt::Subscriber
115     /// [`io::Write`]: std::io::Write
make_writer(&'a self) -> Self::Writer116     fn make_writer(&'a self) -> Self::Writer;
117 
118     /// Returns a [`Writer`] for writing data from the span or event described
119     /// by the provided [`Metadata`].
120     ///
121     /// By default, this calls [`self.make_writer()`][make_writer], ignoring
122     /// the provided metadata, but implementations can override this to provide
123     /// metadata-specific behaviors.
124     ///
125     /// This method allows `MakeWriter` implementations to implement different
126     /// behaviors based on the span or event being written. The `MakeWriter`
127     /// type might return different writers based on the provided metadata, or
128     /// might write some values to the writer before or after providing it to
129     /// the caller.
130     ///
131     /// For example, we might want to write data from spans and events at the
132     /// [`ERROR`] and [`WARN`] levels to `stderr`, and data from spans or events
133     /// at lower levels to stdout:
134     ///
135     /// ```
136     /// use std::io::{self, Stdout, Stderr, StdoutLock, StderrLock};
137     /// use tracing_subscriber::fmt::writer::MakeWriter;
138     /// use tracing_core::{Metadata, Level};
139     ///
140     /// pub struct MyMakeWriter {
141     ///     stdout: Stdout,
142     ///     stderr: Stderr,
143     /// }
144     ///
145     /// /// A lock on either stdout or stderr, depending on the verbosity level
146     /// /// of the event being written.
147     /// pub enum StdioLock<'a> {
148     ///     Stdout(StdoutLock<'a>),
149     ///     Stderr(StderrLock<'a>),
150     /// }
151     ///
152     /// impl<'a> io::Write for StdioLock<'a> {
153     ///     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
154     ///         match self {
155     ///             StdioLock::Stdout(lock) => lock.write(buf),
156     ///             StdioLock::Stderr(lock) => lock.write(buf),
157     ///         }
158     ///     }
159     ///
160     ///     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
161     ///         // ...
162     ///         # match self {
163     ///         #     StdioLock::Stdout(lock) => lock.write_all(buf),
164     ///         #     StdioLock::Stderr(lock) => lock.write_all(buf),
165     ///         # }
166     ///     }
167     ///
168     ///     fn flush(&mut self) -> io::Result<()> {
169     ///         // ...
170     ///         # match self {
171     ///         #     StdioLock::Stdout(lock) => lock.flush(),
172     ///         #     StdioLock::Stderr(lock) => lock.flush(),
173     ///         # }
174     ///     }
175     /// }
176     ///
177     /// impl<'a> MakeWriter<'a> for MyMakeWriter {
178     ///     type Writer = StdioLock<'a>;
179     ///
180     ///     fn make_writer(&'a self) -> Self::Writer {
181     ///         // We must have an implementation of `make_writer` that makes
182     ///         // a "default" writer without any configuring metadata. Let's
183     ///         // just return stdout in that case.
184     ///         StdioLock::Stdout(self.stdout.lock())
185     ///     }
186     ///
187     ///     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
188     ///         // Here's where we can implement our special behavior. We'll
189     ///         // check if the metadata's verbosity level is WARN or ERROR,
190     ///         // and return stderr in that case.
191     ///         if meta.level() <= &Level::WARN {
192     ///             return StdioLock::Stderr(self.stderr.lock());
193     ///         }
194     ///
195     ///         // Otherwise, we'll return stdout.
196     ///         StdioLock::Stdout(self.stdout.lock())
197     ///     }
198     /// }
199     /// ```
200     ///
201     /// [`Writer`]: MakeWriter::Writer
202     /// [`Metadata`]: tracing_core::Metadata
203     /// [make_writer]: MakeWriter::make_writer
204     /// [`WARN`]: tracing_core::Level::WARN
205     /// [`ERROR`]: tracing_core::Level::ERROR
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer206     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
207         let _ = meta;
208         self.make_writer()
209     }
210 }
211 
212 /// Extension trait adding combinators for working with types implementing
213 /// [`MakeWriter`].
214 ///
215 /// This is not intended to be implemented directly for user-defined
216 /// [`MakeWriter`]s; instead, it should be imported when the desired methods are
217 /// used.
218 pub trait MakeWriterExt<'a>: MakeWriter<'a> {
219     /// Wraps `self` and returns a [`MakeWriter`] that will only write output
220     /// for events at or below the provided verbosity [`Level`]. For instance,
221     /// `Level::TRACE` is considered to be _more verbose` than `Level::INFO`.
222     ///
223     /// Events whose level is more verbose than `level` will be ignored, and no
224     /// output will be written.
225     ///
226     /// # Examples
227     ///
228     /// ```
229     /// use tracing::Level;
230     /// use tracing_subscriber::fmt::writer::MakeWriterExt;
231     ///
232     /// // Construct a writer that outputs events to `stderr` only if the span or
233     /// // event's level is >= WARN (WARN and ERROR).
234     /// let mk_writer = std::io::stderr.with_max_level(Level::WARN);
235     ///
236     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
237     /// ```
238     ///
239     /// Writing the `ERROR` and `WARN` levels to `stderr`, and everything else
240     /// to `stdout`:
241     ///
242     /// ```
243     /// # use tracing::Level;
244     /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
245     ///
246     /// let mk_writer = std::io::stderr
247     ///     .with_max_level(Level::WARN)
248     ///     .or_else(std::io::stdout);
249     ///
250     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
251     /// ```
252     ///
253     /// Writing the `ERROR` level to `stderr`, the `INFO` and `WARN` levels to
254     /// `stdout`, and the `INFO` and DEBUG` levels to a file:
255     ///
256     /// ```
257     /// # use tracing::Level;
258     /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
259     /// use std::{sync::Arc, fs::File};
260     /// # // don't actually create the file when running the tests.
261     /// # fn docs() -> std::io::Result<()> {
262     /// let debug_log = Arc::new(File::create("debug.log")?);
263     ///
264     /// let mk_writer = std::io::stderr
265     ///     .with_max_level(Level::ERROR)
266     ///     .or_else(std::io::stdout
267     ///         .with_max_level(Level::INFO)
268     ///         .and(debug_log.with_max_level(Level::DEBUG))
269     ///     );
270     ///
271     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
272     /// # Ok(()) }
273     /// ```
274     ///
275     /// [`Level`]: tracing_core::Level
276     /// [`io::Write`]: std::io::Write
with_max_level(self, level: tracing_core::Level) -> WithMaxLevel<Self> where Self: Sized,277     fn with_max_level(self, level: tracing_core::Level) -> WithMaxLevel<Self>
278     where
279         Self: Sized,
280     {
281         WithMaxLevel::new(self, level)
282     }
283 
284     /// Wraps `self` and returns a [`MakeWriter`] that will only write output
285     /// for events at or above the provided verbosity [`Level`].
286     ///
287     /// Events whose level is less verbose than `level` will be ignored, and no
288     /// output will be written.
289     ///
290     /// # Examples
291     ///
292     /// ```
293     /// use tracing::Level;
294     /// use tracing_subscriber::fmt::writer::MakeWriterExt;
295     ///
296     /// // Construct a writer that outputs events to `stdout` only if the span or
297     /// // event's level is <= DEBUG (DEBUG and TRACE).
298     /// let mk_writer = std::io::stdout.with_min_level(Level::DEBUG);
299     ///
300     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
301     /// ```
302     /// This can be combined with [`MakeWriterExt::with_max_level`] to write
303     /// only within a range of levels:
304     ///
305     /// ```
306     /// # use tracing::Level;
307     /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
308     /// // Only write the `DEBUG` and `INFO` levels to stdout.
309     /// let mk_writer = std::io::stdout
310     ///     .with_max_level(Level::DEBUG)
311     ///     .with_min_level(Level::INFO)
312     ///     // Write the `WARN` and `ERROR` levels to stderr.
313     ///     .and(std::io::stderr.with_min_level(Level::WARN));
314     ///
315     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
316     /// ```
317     /// [`Level`]: tracing_core::Level
318     /// [`io::Write`]: std::io::Write
with_min_level(self, level: tracing_core::Level) -> WithMinLevel<Self> where Self: Sized,319     fn with_min_level(self, level: tracing_core::Level) -> WithMinLevel<Self>
320     where
321         Self: Sized,
322     {
323         WithMinLevel::new(self, level)
324     }
325 
326     /// Wraps `self` with a predicate that takes a span or event's [`Metadata`]
327     /// and returns a `bool`. The returned [`MakeWriter`]'s
328     /// [`MakeWriter::make_writer_for`][mwf] method will check the predicate to
329     /// determine if  a writer should be produced for a given span or event.
330     ///
331     /// If the predicate returns `false`, the wrapped [`MakeWriter`]'s
332     /// [`make_writer_for`][mwf] will return [`OptionalWriter::none`][own].
333     /// Otherwise, it calls the wrapped [`MakeWriter`]'s
334     /// [`make_writer_for`][mwf] method, and returns the produced writer.
335     ///
336     /// This can be used to filter an output based on arbitrary [`Metadata`]
337     /// parameters.
338     ///
339     /// # Examples
340     ///
341     /// Writing events with a specific target to an HTTP access log, and other
342     /// events to stdout:
343     ///
344     /// ```
345     /// use tracing_subscriber::fmt::writer::MakeWriterExt;
346     /// use std::{sync::Arc, fs::File};
347     /// # // don't actually create the file when running the tests.
348     /// # fn docs() -> std::io::Result<()> {
349     /// let access_log = Arc::new(File::create("access.log")?);
350     ///
351     /// let mk_writer = access_log
352     ///     // Only write events with the target "http::access_log" to the
353     ///     // access log file.
354     ///     .with_filter(|meta| meta.target() == "http::access_log")
355     ///     // Write events with all other targets to stdout.
356     ///     .or_else(std::io::stdout);
357     ///
358     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
359     /// # Ok(())
360     /// # }
361     /// ```
362     ///
363     /// Conditionally enabling or disabling a log file:
364     /// ```
365     /// use tracing_subscriber::fmt::writer::MakeWriterExt;
366     /// use std::{
367     ///     sync::{Arc, atomic::{AtomicBool, Ordering}},
368     ///     fs::File,
369     /// };
370     ///
371     /// static DEBUG_LOG_ENABLED: AtomicBool = AtomicBool::new(false);
372     ///
373     /// # // don't actually create the file when running the tests.
374     /// # fn docs() -> std::io::Result<()> {
375     /// // Create the debug log file
376     /// let debug_file = Arc::new(File::create("debug.log")?)
377     ///     // Enable the debug log only if the flag is enabled.
378     ///     .with_filter(|_| DEBUG_LOG_ENABLED.load(Ordering::Acquire));
379     ///
380     /// // Always write to stdout
381     /// let mk_writer = std::io::stdout
382     ///     // Write to the debug file if it's enabled
383     ///     .and(debug_file);
384     ///
385     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
386     ///
387     /// // ...
388     ///
389     /// // Later, we can toggle on or off the debug log file.
390     /// DEBUG_LOG_ENABLED.store(true, Ordering::Release);
391     /// # Ok(())
392     /// # }
393     /// ```
394     ///
395     /// [`Metadata`]: tracing_core::Metadata
396     /// [mwf]: MakeWriter::make_writer_for
397     /// [own]: EitherWriter::none
with_filter<F>(self, filter: F) -> WithFilter<Self, F> where Self: Sized, F: Fn(&Metadata<'_>) -> bool,398     fn with_filter<F>(self, filter: F) -> WithFilter<Self, F>
399     where
400         Self: Sized,
401         F: Fn(&Metadata<'_>) -> bool,
402     {
403         WithFilter::new(self, filter)
404     }
405 
406     /// Combines `self` with another type implementing [`MakeWriter`], returning
407     /// a new [`MakeWriter`] that produces [writers] that write to *both*
408     /// outputs.
409     ///
410     /// If writing to either writer returns an error, the returned writer will
411     /// return that error. However, both writers will still be written to before
412     /// the error is returned, so it is possible for one writer to fail while
413     /// the other is written to successfully.
414     ///
415     /// # Examples
416     ///
417     /// ```
418     /// use tracing_subscriber::fmt::writer::MakeWriterExt;
419     ///
420     /// // Construct a writer that outputs events to `stdout` *and* `stderr`.
421     /// let mk_writer = std::io::stdout.and(std::io::stderr);
422     ///
423     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
424     /// ```
425     ///
426     /// `and` can be used in conjunction with filtering combinators. For
427     /// example, if we want to write to a number of outputs depending on the
428     /// level of an event, we could write:
429     ///
430     /// ```
431     /// use tracing::Level;
432     /// # use tracing_subscriber::fmt::writer::MakeWriterExt;
433     /// use std::{sync::Arc, fs::File};
434     /// # // don't actually create the file when running the tests.
435     /// # fn docs() -> std::io::Result<()> {
436     /// let debug_log = Arc::new(File::create("debug.log")?);
437     ///
438     /// // Write everything to the debug log.
439     /// let mk_writer = debug_log
440     ///     // Write the `ERROR` and `WARN` levels to stderr.
441     ///     .and(std::io::stderr.with_max_level(Level::WARN))
442     ///     // Write `INFO` to `stdout`.
443     ///     .and(std::io::stdout
444     ///         .with_max_level(Level::INFO)
445     ///         .with_min_level(Level::INFO)
446     ///     );
447     ///
448     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
449     /// # Ok(()) }
450     /// ```
451     ///
452     /// [writers]: std::io::Write
and<B>(self, other: B) -> Tee<Self, B> where Self: Sized, B: MakeWriter<'a> + Sized,453     fn and<B>(self, other: B) -> Tee<Self, B>
454     where
455         Self: Sized,
456         B: MakeWriter<'a> + Sized,
457     {
458         Tee::new(self, other)
459     }
460 
461     /// Combines `self` with another type implementing [`MakeWriter`], returning
462     /// a new [`MakeWriter`] that calls `other`'s [`make_writer`] if `self`'s
463     /// `make_writer` returns [`OptionalWriter::none`][own].
464     ///
465     /// # Examples
466     ///
467     /// ```
468     /// use tracing::Level;
469     /// use tracing_subscriber::fmt::writer::MakeWriterExt;
470     ///
471     /// // Produces a writer that writes to `stderr` if the level is >= WARN,
472     /// // or returns `OptionalWriter::none()` otherwise.
473     /// let stderr = std::io::stderr.with_max_level(Level::WARN);
474     ///
475     /// // If the `stderr` `MakeWriter` is disabled by the max level filter,
476     /// // write to stdout instead:
477     /// let mk_writer = stderr.or_else(std::io::stdout);
478     ///
479     /// tracing_subscriber::fmt().with_writer(mk_writer).init();
480     /// ```
481     ///
482     /// [`make_writer`]: MakeWriter::make_writer
483     /// [own]: EitherWriter::none
or_else<W, B>(self, other: B) -> OrElse<Self, B> where Self: MakeWriter<'a, Writer = OptionalWriter<W>> + Sized, B: MakeWriter<'a> + Sized, W: Write,484     fn or_else<W, B>(self, other: B) -> OrElse<Self, B>
485     where
486         Self: MakeWriter<'a, Writer = OptionalWriter<W>> + Sized,
487         B: MakeWriter<'a> + Sized,
488         W: Write,
489     {
490         OrElse::new(self, other)
491     }
492 }
493 
494 /// A writer intended to support [`libtest`'s output capturing][capturing] for use in unit tests.
495 ///
496 /// `TestWriter` is used by [`fmt::Subscriber`] or [`fmt::Layer`] to enable capturing support.
497 ///
498 /// `cargo test` can only capture output from the standard library's [`print!`] macro. See
499 /// [`libtest`'s output capturing][capturing] for more details about output capturing.
500 ///
501 /// Writing to [`io::stdout`] and [`io::stderr`] produces the same results as using
502 /// [`libtest`'s `--nocapture` option][nocapture] which may make the results look unreadable.
503 ///
504 /// [`fmt::Subscriber`]: super::Subscriber
505 /// [`fmt::Layer`]: super::Layer
506 /// [capturing]: https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
507 /// [nocapture]: https://doc.rust-lang.org/cargo/commands/cargo-test.html
508 /// [`io::stdout`]: std::io::stdout
509 /// [`io::stderr`]: std::io::stderr
510 /// [`print!`]: std::print!
511 #[derive(Default, Debug)]
512 pub struct TestWriter {
513     _p: (),
514 }
515 
516 /// A writer that erases the specific [`io::Write`] and [`MakeWriter`] types being used.
517 ///
518 /// This is useful in cases where the concrete type of the writer cannot be known
519 /// until runtime.
520 ///
521 /// # Examples
522 ///
523 /// A function that returns a [`Subscriber`] that will write to either stdout or stderr:
524 ///
525 /// ```rust
526 /// # use tracing::Subscriber;
527 /// # use tracing_subscriber::fmt::writer::BoxMakeWriter;
528 ///
529 /// fn dynamic_writer(use_stderr: bool) -> impl Subscriber {
530 ///     let writer = if use_stderr {
531 ///         BoxMakeWriter::new(std::io::stderr)
532 ///     } else {
533 ///         BoxMakeWriter::new(std::io::stdout)
534 ///     };
535 ///
536 ///     tracing_subscriber::fmt().with_writer(writer).finish()
537 /// }
538 /// ```
539 ///
540 /// [`Subscriber`]: tracing::Subscriber
541 /// [`io::Write`]: std::io::Write
542 pub struct BoxMakeWriter {
543     inner: Box<dyn for<'a> MakeWriter<'a, Writer = Box<dyn Write + 'a>> + Send + Sync>,
544     name: &'static str,
545 }
546 
547 /// A [writer] that is one of two types implementing [`io::Write`][writer].
548 ///
549 /// This may be used by [`MakeWriter`] implementations that may conditionally
550 /// return one of two writers.
551 ///
552 /// [writer]: std::io::Write
553 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
554 pub enum EitherWriter<A, B> {
555     /// A writer of type `A`.
556     A(A),
557     /// A writer of type `B`.
558     B(B),
559 }
560 
561 /// A [writer] which may or may not be enabled.
562 ///
563 /// This may be used by [`MakeWriter`] implementations that wish to
564 /// conditionally enable or disable the returned writer based on a span or
565 /// event's [`Metadata`].
566 ///
567 /// [writer]: std::io::Write
568 pub type OptionalWriter<T> = EitherWriter<T, std::io::Sink>;
569 
570 /// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans
571 /// and events with metadata at or below a specified verbosity [`Level`].
572 ///
573 /// This is returned by the [`MakeWriterExt::with_max_level`] method. See the
574 /// method documentation for details.
575 ///
576 /// [writer]: std::io::Write
577 /// [`Level`]: tracing_core::Level
578 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
579 pub struct WithMaxLevel<M> {
580     make: M,
581     level: tracing_core::Level,
582 }
583 
584 /// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans
585 /// and events with metadata at or above a specified verbosity [`Level`].
586 ///
587 /// This is returned by the [`MakeWriterExt::with_min_level`] method. See the
588 /// method documentation for details.
589 ///
590 /// [writer]: std::io::Write
591 /// [`Level`]: tracing_core::Level
592 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
593 pub struct WithMinLevel<M> {
594     make: M,
595     level: tracing_core::Level,
596 }
597 
598 /// A [`MakeWriter`] combinator that wraps a [`MakeWriter`] with a predicate for
599 /// span and event [`Metadata`], so that the [`MakeWriter::make_writer_for`]
600 /// method returns [`OptionalWriter::some`][ows] when the predicate returns `true`,
601 /// and [`OptionalWriter::none`][own] when the predicate returns `false`.
602 ///
603 /// This is returned by the [`MakeWriterExt::with_filter`] method. See the
604 /// method documentation for details.
605 ///
606 /// [`Metadata`]: tracing_core::Metadata
607 /// [ows]: EitherWriter::some
608 /// [own]: EitherWriter::none
609 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
610 pub struct WithFilter<M, F> {
611     make: M,
612     filter: F,
613 }
614 
615 /// Combines a [`MakeWriter`] that returns an [`OptionalWriter`] with another
616 /// [`MakeWriter`], so that the second [`MakeWriter`] is used when the first
617 /// [`MakeWriter`] returns [`OptionalWriter::none`][own].
618 ///
619 /// This is returned by the [`MakeWriterExt::or_else] method. See the
620 /// method documentation for details.
621 ///
622 /// [own]: EitherWriter::none
623 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
624 pub struct OrElse<A, B> {
625     inner: A,
626     or_else: B,
627 }
628 
629 /// Combines two types implementing [`MakeWriter`] (or [`std::io::Write`]) to
630 /// produce a writer that writes to both [`MakeWriter`]'s returned writers.
631 ///
632 /// This is returned by the [`MakeWriterExt::and`] method. See the method
633 /// documentation for details.
634 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
635 pub struct Tee<A, B> {
636     a: A,
637     b: B,
638 }
639 
640 /// A type implementing [`io::Write`] for a [`MutexGuard`] where the type
641 /// inside the [`Mutex`] implements [`io::Write`].
642 ///
643 /// This is used by the [`MakeWriter`] implementation for [`Mutex`], because
644 /// [`MutexGuard`] itself will not implement [`io::Write`] — instead, it
645 /// _dereferences_ to a type implementing [`io::Write`]. Because [`MakeWriter`]
646 /// requires the `Writer` type to implement [`io::Write`], it's necessary to add
647 /// a newtype that forwards the trait implementation.
648 ///
649 /// [`io::Write`]: std::io::Write
650 /// [`MutexGuard`]: std::sync::MutexGuard
651 /// [`Mutex`]: std::sync::Mutex
652 #[derive(Debug)]
653 pub struct MutexGuardWriter<'a, W>(MutexGuard<'a, W>);
654 
655 /// Implements [`std::io::Write`] for an [`Arc`]<W> where `&W: Write`.
656 ///
657 /// This is an implementation detail of the [`MakeWriter`] impl for [`Arc`].
658 #[derive(Clone, Debug)]
659 pub struct ArcWriter<W>(Arc<W>);
660 
661 /// A bridge between `fmt::Write` and `io::Write`.
662 ///
663 /// This is used by the timestamp formatting implementation for the `time`
664 /// crate and by the JSON formatter. In both cases, this is needed because
665 /// `tracing-subscriber`'s `FormatEvent`/`FormatTime` traits expect a
666 /// `fmt::Write` implementation, while `serde_json::Serializer` and `time`'s
667 /// `format_into` methods expect an `io::Write`.
668 #[cfg(any(feature = "json", feature = "time"))]
669 pub(in crate::fmt) struct WriteAdaptor<'a> {
670     fmt_write: &'a mut dyn fmt::Write,
671 }
672 
673 impl<'a, F, W> MakeWriter<'a> for F
674 where
675     F: Fn() -> W,
676     W: io::Write,
677 {
678     type Writer = W;
679 
make_writer(&'a self) -> Self::Writer680     fn make_writer(&'a self) -> Self::Writer {
681         (self)()
682     }
683 }
684 
685 impl<'a, W> MakeWriter<'a> for Arc<W>
686 where
687     &'a W: io::Write + 'a,
688 {
689     type Writer = &'a W;
make_writer(&'a self) -> Self::Writer690     fn make_writer(&'a self) -> Self::Writer {
691         self
692     }
693 }
694 
695 impl<'a> MakeWriter<'a> for std::fs::File {
696     type Writer = &'a std::fs::File;
make_writer(&'a self) -> Self::Writer697     fn make_writer(&'a self) -> Self::Writer {
698         self
699     }
700 }
701 
702 // === impl TestWriter ===
703 
704 impl TestWriter {
705     /// Returns a new `TestWriter` with the default configuration.
new() -> Self706     pub fn new() -> Self {
707         Self::default()
708     }
709 }
710 
711 impl io::Write for TestWriter {
write(&mut self, buf: &[u8]) -> io::Result<usize>712     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
713         let out_str = String::from_utf8_lossy(buf);
714         print!("{}", out_str);
715         Ok(buf.len())
716     }
717 
flush(&mut self) -> io::Result<()>718     fn flush(&mut self) -> io::Result<()> {
719         Ok(())
720     }
721 }
722 
723 impl<'a> MakeWriter<'a> for TestWriter {
724     type Writer = Self;
725 
make_writer(&'a self) -> Self::Writer726     fn make_writer(&'a self) -> Self::Writer {
727         Self::default()
728     }
729 }
730 
731 // === impl BoxMakeWriter ===
732 
733 impl BoxMakeWriter {
734     /// Constructs a `BoxMakeWriter` wrapping a type implementing [`MakeWriter`].
735     ///
new<M>(make_writer: M) -> Self where M: for<'a> MakeWriter<'a> + Send + Sync + 'static,736     pub fn new<M>(make_writer: M) -> Self
737     where
738         M: for<'a> MakeWriter<'a> + Send + Sync + 'static,
739     {
740         Self {
741             inner: Box::new(Boxed(make_writer)),
742             name: std::any::type_name::<M>(),
743         }
744     }
745 }
746 
747 impl fmt::Debug for BoxMakeWriter {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result748     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
749         f.debug_tuple("BoxMakeWriter")
750             .field(&format_args!("<{}>", self.name))
751             .finish()
752     }
753 }
754 
755 impl<'a> MakeWriter<'a> for BoxMakeWriter {
756     type Writer = Box<dyn Write + 'a>;
757 
758     #[inline]
make_writer(&'a self) -> Self::Writer759     fn make_writer(&'a self) -> Self::Writer {
760         self.inner.make_writer()
761     }
762 
763     #[inline]
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer764     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
765         self.inner.make_writer_for(meta)
766     }
767 }
768 
769 struct Boxed<M>(M);
770 
771 impl<'a, M> MakeWriter<'a> for Boxed<M>
772 where
773     M: MakeWriter<'a>,
774 {
775     type Writer = Box<dyn Write + 'a>;
776 
make_writer(&'a self) -> Self::Writer777     fn make_writer(&'a self) -> Self::Writer {
778         let w = self.0.make_writer();
779         Box::new(w)
780     }
781 
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer782     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
783         let w = self.0.make_writer_for(meta);
784         Box::new(w)
785     }
786 }
787 
788 // === impl Mutex/MutexGuardWriter ===
789 
790 impl<'a, W> MakeWriter<'a> for Mutex<W>
791 where
792     W: io::Write + 'a,
793 {
794     type Writer = MutexGuardWriter<'a, W>;
795 
make_writer(&'a self) -> Self::Writer796     fn make_writer(&'a self) -> Self::Writer {
797         MutexGuardWriter(self.lock().expect("lock poisoned"))
798     }
799 }
800 
801 impl<'a, W> io::Write for MutexGuardWriter<'a, W>
802 where
803     W: io::Write,
804 {
805     #[inline]
write(&mut self, buf: &[u8]) -> io::Result<usize>806     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
807         self.0.write(buf)
808     }
809 
810     #[inline]
flush(&mut self) -> io::Result<()>811     fn flush(&mut self) -> io::Result<()> {
812         self.0.flush()
813     }
814 
815     #[inline]
write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>816     fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
817         self.0.write_vectored(bufs)
818     }
819 
820     #[inline]
write_all(&mut self, buf: &[u8]) -> io::Result<()>821     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
822         self.0.write_all(buf)
823     }
824 
825     #[inline]
write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()>826     fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
827         self.0.write_fmt(fmt)
828     }
829 }
830 
831 // === impl EitherWriter ===
832 
833 impl<A, B> io::Write for EitherWriter<A, B>
834 where
835     A: io::Write,
836     B: io::Write,
837 {
838     #[inline]
write(&mut self, buf: &[u8]) -> io::Result<usize>839     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
840         match self {
841             EitherWriter::A(a) => a.write(buf),
842             EitherWriter::B(b) => b.write(buf),
843         }
844     }
845 
846     #[inline]
flush(&mut self) -> io::Result<()>847     fn flush(&mut self) -> io::Result<()> {
848         match self {
849             EitherWriter::A(a) => a.flush(),
850             EitherWriter::B(b) => b.flush(),
851         }
852     }
853 
854     #[inline]
write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>855     fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
856         match self {
857             EitherWriter::A(a) => a.write_vectored(bufs),
858             EitherWriter::B(b) => b.write_vectored(bufs),
859         }
860     }
861 
862     #[inline]
write_all(&mut self, buf: &[u8]) -> io::Result<()>863     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
864         match self {
865             EitherWriter::A(a) => a.write_all(buf),
866             EitherWriter::B(b) => b.write_all(buf),
867         }
868     }
869 
870     #[inline]
write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()>871     fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
872         match self {
873             EitherWriter::A(a) => a.write_fmt(fmt),
874             EitherWriter::B(b) => b.write_fmt(fmt),
875         }
876     }
877 }
878 
879 impl<T> OptionalWriter<T> {
880     /// Returns a [disabled writer].
881     ///
882     /// Any bytes written to the returned writer are discarded.
883     ///
884     /// This is equivalent to returning [`Option::None`].
885     ///
886     /// [disabled writer]: std::io::sink
887     #[inline]
none() -> Self888     pub fn none() -> Self {
889         EitherWriter::B(std::io::sink())
890     }
891 
892     /// Returns an enabled writer of type `T`.
893     ///
894     /// This is equivalent to returning [`Option::Some`].
895     #[inline]
some(t: T) -> Self896     pub fn some(t: T) -> Self {
897         EitherWriter::A(t)
898     }
899 }
900 
901 impl<T> From<Option<T>> for OptionalWriter<T> {
902     #[inline]
from(opt: Option<T>) -> Self903     fn from(opt: Option<T>) -> Self {
904         match opt {
905             Some(writer) => Self::some(writer),
906             None => Self::none(),
907         }
908     }
909 }
910 
911 // === impl WithMaxLevel ===
912 
913 impl<M> WithMaxLevel<M> {
914     /// Wraps the provided [`MakeWriter`] with a maximum [`Level`], so that it
915     /// returns [`OptionalWriter::none`] for spans and events whose level is
916     /// more verbose than the maximum level.
917     ///
918     /// See [`MakeWriterExt::with_max_level`] for details.
919     ///
920     /// [`Level`]: tracing_core::Level
new(make: M, level: tracing_core::Level) -> Self921     pub fn new(make: M, level: tracing_core::Level) -> Self {
922         Self { make, level }
923     }
924 }
925 
926 impl<'a, M: MakeWriter<'a>> MakeWriter<'a> for WithMaxLevel<M> {
927     type Writer = OptionalWriter<M::Writer>;
928 
929     #[inline]
make_writer(&'a self) -> Self::Writer930     fn make_writer(&'a self) -> Self::Writer {
931         // If we don't know the level, assume it's disabled.
932         OptionalWriter::none()
933     }
934 
935     #[inline]
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer936     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
937         if meta.level() <= &self.level {
938             return OptionalWriter::some(self.make.make_writer_for(meta));
939         }
940         OptionalWriter::none()
941     }
942 }
943 
944 // === impl WithMinLevel ===
945 
946 impl<M> WithMinLevel<M> {
947     /// Wraps the provided [`MakeWriter`] with a minimum [`Level`], so that it
948     /// returns [`OptionalWriter::none`] for spans and events whose level is
949     /// less verbose than the maximum level.
950     ///
951     /// See [`MakeWriterExt::with_min_level`] for details.
952     ///
953     /// [`Level`]: tracing_core::Level
new(make: M, level: tracing_core::Level) -> Self954     pub fn new(make: M, level: tracing_core::Level) -> Self {
955         Self { make, level }
956     }
957 }
958 
959 impl<'a, M: MakeWriter<'a>> MakeWriter<'a> for WithMinLevel<M> {
960     type Writer = OptionalWriter<M::Writer>;
961 
962     #[inline]
make_writer(&'a self) -> Self::Writer963     fn make_writer(&'a self) -> Self::Writer {
964         // If we don't know the level, assume it's disabled.
965         OptionalWriter::none()
966     }
967 
968     #[inline]
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer969     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
970         if meta.level() >= &self.level {
971             return OptionalWriter::some(self.make.make_writer_for(meta));
972         }
973         OptionalWriter::none()
974     }
975 }
976 
977 // ==== impl WithFilter ===
978 
979 impl<M, F> WithFilter<M, F> {
980     /// Wraps `make` with the provided `filter`, returning a [`MakeWriter`] that
981     /// will call `make.make_writer_for()` when `filter` returns `true` for a
982     /// span or event's [`Metadata`], and returns a [`sink`] otherwise.
983     ///
984     /// See [`MakeWriterExt::with_filter`] for details.
985     ///
986     /// [`Metadata`]: tracing_core::Metadata
987     /// [`sink`]: std::io::sink
new(make: M, filter: F) -> Self where F: Fn(&Metadata<'_>) -> bool,988     pub fn new(make: M, filter: F) -> Self
989     where
990         F: Fn(&Metadata<'_>) -> bool,
991     {
992         Self { make, filter }
993     }
994 }
995 
996 impl<'a, M, F> MakeWriter<'a> for WithFilter<M, F>
997 where
998     M: MakeWriter<'a>,
999     F: Fn(&Metadata<'_>) -> bool,
1000 {
1001     type Writer = OptionalWriter<M::Writer>;
1002 
1003     #[inline]
make_writer(&'a self) -> Self::Writer1004     fn make_writer(&'a self) -> Self::Writer {
1005         OptionalWriter::some(self.make.make_writer())
1006     }
1007 
1008     #[inline]
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer1009     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
1010         if (self.filter)(meta) {
1011             OptionalWriter::some(self.make.make_writer_for(meta))
1012         } else {
1013             OptionalWriter::none()
1014         }
1015     }
1016 }
1017 
1018 // === impl Tee ===
1019 
1020 impl<A, B> Tee<A, B> {
1021     /// Combines two types implementing [`MakeWriter`], returning
1022     /// a new [`MakeWriter`] that produces [writers] that write to *both*
1023     /// outputs.
1024     ///
1025     /// See the documentation for [`MakeWriterExt::and`] for details.
1026     ///
1027     /// [writers]: std::io::Write
new(a: A, b: B) -> Self1028     pub fn new(a: A, b: B) -> Self {
1029         Self { a, b }
1030     }
1031 }
1032 
1033 impl<'a, A, B> MakeWriter<'a> for Tee<A, B>
1034 where
1035     A: MakeWriter<'a>,
1036     B: MakeWriter<'a>,
1037 {
1038     type Writer = Tee<A::Writer, B::Writer>;
1039 
1040     #[inline]
make_writer(&'a self) -> Self::Writer1041     fn make_writer(&'a self) -> Self::Writer {
1042         Tee::new(self.a.make_writer(), self.b.make_writer())
1043     }
1044 
1045     #[inline]
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer1046     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
1047         Tee::new(self.a.make_writer_for(meta), self.b.make_writer_for(meta))
1048     }
1049 }
1050 
1051 macro_rules! impl_tee {
1052     ($self_:ident.$f:ident($($arg:ident),*)) => {
1053         {
1054             let res_a = $self_.a.$f($($arg),*);
1055             let res_b = $self_.b.$f($($arg),*);
1056             (res_a?, res_b?)
1057         }
1058     }
1059 }
1060 
1061 impl<A, B> io::Write for Tee<A, B>
1062 where
1063     A: io::Write,
1064     B: io::Write,
1065 {
1066     #[inline]
write(&mut self, buf: &[u8]) -> io::Result<usize>1067     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1068         let (a, b) = impl_tee!(self.write(buf));
1069         Ok(std::cmp::max(a, b))
1070     }
1071 
1072     #[inline]
flush(&mut self) -> io::Result<()>1073     fn flush(&mut self) -> io::Result<()> {
1074         impl_tee!(self.flush());
1075         Ok(())
1076     }
1077 
1078     #[inline]
write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>1079     fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
1080         let (a, b) = impl_tee!(self.write_vectored(bufs));
1081         Ok(std::cmp::max(a, b))
1082     }
1083 
1084     #[inline]
write_all(&mut self, buf: &[u8]) -> io::Result<()>1085     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
1086         impl_tee!(self.write_all(buf));
1087         Ok(())
1088     }
1089 
1090     #[inline]
write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()>1091     fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
1092         impl_tee!(self.write_fmt(fmt));
1093         Ok(())
1094     }
1095 }
1096 
1097 // === impl OrElse ===
1098 
1099 impl<A, B> OrElse<A, B> {
1100     /// Combines
new<'a, W>(inner: A, or_else: B) -> Self where A: MakeWriter<'a, Writer = OptionalWriter<W>>, B: MakeWriter<'a>, W: Write,1101     pub fn new<'a, W>(inner: A, or_else: B) -> Self
1102     where
1103         A: MakeWriter<'a, Writer = OptionalWriter<W>>,
1104         B: MakeWriter<'a>,
1105         W: Write,
1106     {
1107         Self { inner, or_else }
1108     }
1109 }
1110 
1111 impl<'a, A, B, W> MakeWriter<'a> for OrElse<A, B>
1112 where
1113     A: MakeWriter<'a, Writer = OptionalWriter<W>>,
1114     B: MakeWriter<'a>,
1115     W: io::Write,
1116 {
1117     type Writer = EitherWriter<W, B::Writer>;
1118 
1119     #[inline]
make_writer(&'a self) -> Self::Writer1120     fn make_writer(&'a self) -> Self::Writer {
1121         match self.inner.make_writer() {
1122             EitherWriter::A(writer) => EitherWriter::A(writer),
1123             EitherWriter::B(_) => EitherWriter::B(self.or_else.make_writer()),
1124         }
1125     }
1126 
1127     #[inline]
make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer1128     fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
1129         match self.inner.make_writer_for(meta) {
1130             EitherWriter::A(writer) => EitherWriter::A(writer),
1131             EitherWriter::B(_) => EitherWriter::B(self.or_else.make_writer_for(meta)),
1132         }
1133     }
1134 }
1135 
1136 // === impl ArcWriter ===
1137 
1138 impl<W> io::Write for ArcWriter<W>
1139 where
1140     for<'a> &'a W: io::Write,
1141 {
1142     #[inline]
write(&mut self, buf: &[u8]) -> io::Result<usize>1143     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1144         (&*self.0).write(buf)
1145     }
1146 
1147     #[inline]
flush(&mut self) -> io::Result<()>1148     fn flush(&mut self) -> io::Result<()> {
1149         (&*self.0).flush()
1150     }
1151 
1152     #[inline]
write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>1153     fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
1154         (&*self.0).write_vectored(bufs)
1155     }
1156 
1157     #[inline]
write_all(&mut self, buf: &[u8]) -> io::Result<()>1158     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
1159         (&*self.0).write_all(buf)
1160     }
1161 
1162     #[inline]
write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()>1163     fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
1164         (&*self.0).write_fmt(fmt)
1165     }
1166 }
1167 
1168 // === impl WriteAdaptor ===
1169 
1170 #[cfg(any(feature = "json", feature = "time"))]
1171 impl<'a> WriteAdaptor<'a> {
new(fmt_write: &'a mut dyn fmt::Write) -> Self1172     pub(in crate::fmt) fn new(fmt_write: &'a mut dyn fmt::Write) -> Self {
1173         Self { fmt_write }
1174     }
1175 }
1176 #[cfg(any(feature = "json", feature = "time"))]
1177 impl<'a> io::Write for WriteAdaptor<'a> {
write(&mut self, buf: &[u8]) -> io::Result<usize>1178     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1179         let s =
1180             std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
1181 
1182         self.fmt_write
1183             .write_str(s)
1184             .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
1185 
1186         Ok(s.as_bytes().len())
1187     }
1188 
flush(&mut self) -> io::Result<()>1189     fn flush(&mut self) -> io::Result<()> {
1190         Ok(())
1191     }
1192 }
1193 
1194 #[cfg(any(feature = "json", feature = "time"))]
1195 impl<'a> fmt::Debug for WriteAdaptor<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1196     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1197         f.pad("WriteAdaptor { .. }")
1198     }
1199 }
1200 // === blanket impls ===
1201 
1202 impl<'a, M> MakeWriterExt<'a> for M where M: MakeWriter<'a> {}
1203 #[cfg(test)]
1204 mod test {
1205     use super::*;
1206     use crate::fmt::format::Format;
1207     use crate::fmt::test::{MockMakeWriter, MockWriter};
1208     use crate::fmt::Subscriber;
1209     use std::sync::atomic::{AtomicBool, Ordering};
1210     use std::sync::{Arc, Mutex};
1211     use tracing::{debug, error, info, trace, warn, Level};
1212     use tracing_core::dispatcher::{self, Dispatch};
1213 
test_writer<T>(make_writer: T, msg: &str, buf: &Mutex<Vec<u8>>) where T: for<'writer> MakeWriter<'writer> + Send + Sync + 'static,1214     fn test_writer<T>(make_writer: T, msg: &str, buf: &Mutex<Vec<u8>>)
1215     where
1216         T: for<'writer> MakeWriter<'writer> + Send + Sync + 'static,
1217     {
1218         let subscriber = {
1219             #[cfg(feature = "ansi")]
1220             let f = Format::default().without_time().with_ansi(false);
1221             #[cfg(not(feature = "ansi"))]
1222             let f = Format::default().without_time();
1223             Subscriber::builder()
1224                 .event_format(f)
1225                 .with_writer(make_writer)
1226                 .finish()
1227         };
1228         let dispatch = Dispatch::from(subscriber);
1229 
1230         dispatcher::with_default(&dispatch, || {
1231             error!("{}", msg);
1232         });
1233 
1234         let expected = format!("ERROR {}: {}\n", module_path!(), msg);
1235         let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap();
1236         assert!(actual.contains(expected.as_str()));
1237     }
1238 
has_lines(buf: &Mutex<Vec<u8>>, msgs: &[(tracing::Level, &str)])1239     fn has_lines(buf: &Mutex<Vec<u8>>, msgs: &[(tracing::Level, &str)]) {
1240         let actual = String::from_utf8(buf.try_lock().unwrap().to_vec()).unwrap();
1241         let mut expected_lines = msgs.iter();
1242         for line in actual.lines() {
1243             let line = dbg!(line).trim();
1244             let (level, msg) = expected_lines
1245                 .next()
1246                 .unwrap_or_else(|| panic!("expected no more lines, but got: {:?}", line));
1247             let expected = format!("{} {}: {}", level, module_path!(), msg);
1248             assert_eq!(line, expected.as_str());
1249         }
1250     }
1251 
1252     #[test]
custom_writer_closure()1253     fn custom_writer_closure() {
1254         let buf = Arc::new(Mutex::new(Vec::new()));
1255         let buf2 = buf.clone();
1256         let make_writer = move || MockWriter::new(buf2.clone());
1257         let msg = "my custom writer closure error";
1258         test_writer(make_writer, msg, &buf);
1259     }
1260 
1261     #[test]
custom_writer_struct()1262     fn custom_writer_struct() {
1263         let buf = Arc::new(Mutex::new(Vec::new()));
1264         let make_writer = MockMakeWriter::new(buf.clone());
1265         let msg = "my custom writer struct error";
1266         test_writer(make_writer, msg, &buf);
1267     }
1268 
1269     #[test]
custom_writer_mutex()1270     fn custom_writer_mutex() {
1271         let buf = Arc::new(Mutex::new(Vec::new()));
1272         let writer = MockWriter::new(buf.clone());
1273         let make_writer = Mutex::new(writer);
1274         let msg = "my mutex writer error";
1275         test_writer(make_writer, msg, &buf);
1276     }
1277 
1278     #[test]
combinators_level_filters()1279     fn combinators_level_filters() {
1280         let info_buf = Arc::new(Mutex::new(Vec::new()));
1281         let info = MockMakeWriter::new(info_buf.clone());
1282 
1283         let debug_buf = Arc::new(Mutex::new(Vec::new()));
1284         let debug = MockMakeWriter::new(debug_buf.clone());
1285 
1286         let warn_buf = Arc::new(Mutex::new(Vec::new()));
1287         let warn = MockMakeWriter::new(warn_buf.clone());
1288 
1289         let err_buf = Arc::new(Mutex::new(Vec::new()));
1290         let err = MockMakeWriter::new(err_buf.clone());
1291 
1292         let make_writer = info
1293             .with_max_level(Level::INFO)
1294             .and(debug.with_max_level(Level::DEBUG))
1295             .and(warn.with_max_level(Level::WARN))
1296             .and(err.with_max_level(Level::ERROR));
1297 
1298         let c = {
1299             #[cfg(feature = "ansi")]
1300             let f = Format::default().without_time().with_ansi(false);
1301             #[cfg(not(feature = "ansi"))]
1302             let f = Format::default().without_time();
1303             Subscriber::builder()
1304                 .event_format(f)
1305                 .with_writer(make_writer)
1306                 .with_max_level(Level::TRACE)
1307                 .finish()
1308         };
1309 
1310         let _s = tracing::subscriber::set_default(c);
1311 
1312         trace!("trace");
1313         debug!("debug");
1314         info!("info");
1315         warn!("warn");
1316         error!("error");
1317 
1318         let all_lines = [
1319             (Level::TRACE, "trace"),
1320             (Level::DEBUG, "debug"),
1321             (Level::INFO, "info"),
1322             (Level::WARN, "warn"),
1323             (Level::ERROR, "error"),
1324         ];
1325 
1326         println!("max level debug");
1327         has_lines(&debug_buf, &all_lines[1..]);
1328 
1329         println!("max level info");
1330         has_lines(&info_buf, &all_lines[2..]);
1331 
1332         println!("max level warn");
1333         has_lines(&warn_buf, &all_lines[3..]);
1334 
1335         println!("max level error");
1336         has_lines(&err_buf, &all_lines[4..]);
1337     }
1338 
1339     #[test]
combinators_or_else()1340     fn combinators_or_else() {
1341         let some_buf = Arc::new(Mutex::new(Vec::new()));
1342         let some = MockMakeWriter::new(some_buf.clone());
1343 
1344         let or_else_buf = Arc::new(Mutex::new(Vec::new()));
1345         let or_else = MockMakeWriter::new(or_else_buf.clone());
1346 
1347         let return_some = AtomicBool::new(true);
1348         let make_writer = move || {
1349             if return_some.swap(false, Ordering::Relaxed) {
1350                 OptionalWriter::some(some.make_writer())
1351             } else {
1352                 OptionalWriter::none()
1353             }
1354         };
1355         let make_writer = make_writer.or_else(or_else);
1356         let c = {
1357             #[cfg(feature = "ansi")]
1358             let f = Format::default().without_time().with_ansi(false);
1359             #[cfg(not(feature = "ansi"))]
1360             let f = Format::default().without_time();
1361             Subscriber::builder()
1362                 .event_format(f)
1363                 .with_writer(make_writer)
1364                 .with_max_level(Level::TRACE)
1365                 .finish()
1366         };
1367 
1368         let _s = tracing::subscriber::set_default(c);
1369         info!("hello");
1370         info!("world");
1371         info!("goodbye");
1372 
1373         has_lines(&some_buf, &[(Level::INFO, "hello")]);
1374         has_lines(
1375             &or_else_buf,
1376             &[(Level::INFO, "world"), (Level::INFO, "goodbye")],
1377         );
1378     }
1379 
1380     #[test]
combinators_or_else_chain()1381     fn combinators_or_else_chain() {
1382         let info_buf = Arc::new(Mutex::new(Vec::new()));
1383         let info = MockMakeWriter::new(info_buf.clone());
1384 
1385         let debug_buf = Arc::new(Mutex::new(Vec::new()));
1386         let debug = MockMakeWriter::new(debug_buf.clone());
1387 
1388         let warn_buf = Arc::new(Mutex::new(Vec::new()));
1389         let warn = MockMakeWriter::new(warn_buf.clone());
1390 
1391         let err_buf = Arc::new(Mutex::new(Vec::new()));
1392         let err = MockMakeWriter::new(err_buf.clone());
1393 
1394         let make_writer = err.with_max_level(Level::ERROR).or_else(
1395             warn.with_max_level(Level::WARN).or_else(
1396                 info.with_max_level(Level::INFO)
1397                     .or_else(debug.with_max_level(Level::DEBUG)),
1398             ),
1399         );
1400 
1401         let c = {
1402             #[cfg(feature = "ansi")]
1403             let f = Format::default().without_time().with_ansi(false);
1404             #[cfg(not(feature = "ansi"))]
1405             let f = Format::default().without_time();
1406             Subscriber::builder()
1407                 .event_format(f)
1408                 .with_writer(make_writer)
1409                 .with_max_level(Level::TRACE)
1410                 .finish()
1411         };
1412 
1413         let _s = tracing::subscriber::set_default(c);
1414 
1415         trace!("trace");
1416         debug!("debug");
1417         info!("info");
1418         warn!("warn");
1419         error!("error");
1420 
1421         println!("max level debug");
1422         has_lines(&debug_buf, &[(Level::DEBUG, "debug")]);
1423 
1424         println!("max level info");
1425         has_lines(&info_buf, &[(Level::INFO, "info")]);
1426 
1427         println!("max level warn");
1428         has_lines(&warn_buf, &[(Level::WARN, "warn")]);
1429 
1430         println!("max level error");
1431         has_lines(&err_buf, &[(Level::ERROR, "error")]);
1432     }
1433 
1434     #[test]
combinators_and()1435     fn combinators_and() {
1436         let a_buf = Arc::new(Mutex::new(Vec::new()));
1437         let a = MockMakeWriter::new(a_buf.clone());
1438 
1439         let b_buf = Arc::new(Mutex::new(Vec::new()));
1440         let b = MockMakeWriter::new(b_buf.clone());
1441 
1442         let lines = &[(Level::INFO, "hello"), (Level::INFO, "world")];
1443 
1444         let make_writer = a.and(b);
1445         let c = {
1446             #[cfg(feature = "ansi")]
1447             let f = Format::default().without_time().with_ansi(false);
1448             #[cfg(not(feature = "ansi"))]
1449             let f = Format::default().without_time();
1450             Subscriber::builder()
1451                 .event_format(f)
1452                 .with_writer(make_writer)
1453                 .with_max_level(Level::TRACE)
1454                 .finish()
1455         };
1456 
1457         let _s = tracing::subscriber::set_default(c);
1458         info!("hello");
1459         info!("world");
1460 
1461         has_lines(&a_buf, &lines[..]);
1462         has_lines(&b_buf, &lines[..]);
1463     }
1464 }
1465