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