]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | //! Extension traits and other utilities to make working with subscribers more |
2 | //! ergonomic. | |
3 | use std::{error::Error, fmt}; | |
4 | use tracing_core::dispatcher::{self, Dispatch}; | |
5 | ||
6 | /// Extension trait adding utility methods for subscriber initialization. | |
7 | /// | |
8 | /// This trait provides extension methods to make configuring and setting a | |
9 | /// [default subscriber] more ergonomic. It is automatically implemented for all | |
10 | /// types that can be converted into a [trace dispatcher]. Since `Dispatch` | |
11 | /// implements `From<T>` for all `T: Subscriber`, all `Subscriber` | |
12 | /// implementations will implement this extension trait as well. Types which | |
13 | /// can be converted into `Subscriber`s, such as builders that construct a | |
14 | /// `Subscriber`, may implement `Into<Dispatch>`, and will also receive an | |
15 | /// implementation of this trait. | |
16 | /// | |
29967ef6 XL |
17 | /// [default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber |
18 | /// [trace dispatcher]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html | |
f035d41b XL |
19 | pub trait SubscriberInitExt |
20 | where | |
21 | Self: Into<Dispatch>, | |
22 | { | |
23 | /// Sets `self` as the [default subscriber] in the current scope, returning a | |
24 | /// guard that will unset it when dropped. | |
25 | /// | |
26 | /// If the "tracing-log" feature flag is enabled, this will also initialize | |
27 | /// a [`log`] compatibility layer. This allows the subscriber to consume | |
28 | /// `log::Record`s as though they were `tracing` `Event`s. | |
29 | /// | |
29967ef6 | 30 | /// [default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber |
f035d41b XL |
31 | /// [`log`]: https://crates.io/log |
32 | fn set_default(self) -> dispatcher::DefaultGuard { | |
33 | #[cfg(feature = "tracing-log")] | |
34 | let _ = tracing_log::LogTracer::init(); | |
35 | ||
36 | dispatcher::set_default(&self.into()) | |
37 | } | |
38 | ||
39 | /// Attempts to set `self` as the [global default subscriber] in the current | |
40 | /// scope, returning an error if one is already set. | |
41 | /// | |
42 | /// If the "tracing-log" feature flag is enabled, this will also attempt to | |
43 | /// initialize a [`log`] compatibility layer. This allows the subscriber to | |
44 | /// consume `log::Record`s as though they were `tracing` `Event`s. | |
45 | /// | |
46 | /// This method returns an error if a global default subscriber has already | |
47 | /// been set, or if a `log` logger has already been set (when the | |
48 | /// "tracing-log" feature is enabled). | |
49 | /// | |
29967ef6 | 50 | /// [global default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber |
f035d41b XL |
51 | /// [`log`]: https://crates.io/log |
52 | fn try_init(self) -> Result<(), TryInitError> { | |
53 | #[cfg(feature = "tracing-log")] | |
54 | tracing_log::LogTracer::init().map_err(TryInitError::new)?; | |
55 | ||
56 | dispatcher::set_global_default(self.into()).map_err(TryInitError::new)?; | |
57 | ||
58 | Ok(()) | |
59 | } | |
60 | ||
61 | /// Attempts to set `self` as the [global default subscriber] in the current | |
62 | /// scope, panicking if this fails. | |
63 | /// | |
64 | /// If the "tracing-log" feature flag is enabled, this will also attempt to | |
65 | /// initialize a [`log`] compatibility layer. This allows the subscriber to | |
66 | /// consume `log::Record`s as though they were `tracing` `Event`s. | |
67 | /// | |
68 | /// This method panics if a global default subscriber has already been set, | |
69 | /// or if a `log` logger has already been set (when the "tracing-log" | |
70 | /// feature is enabled). | |
71 | /// | |
29967ef6 | 72 | /// [global default subscriber]: https://docs.rs/tracing/0.1.21/tracing/dispatcher/index.html#setting-the-default-subscriber |
f035d41b XL |
73 | /// [`log`]: https://crates.io/log |
74 | fn init(self) { | |
75 | self.try_init() | |
76 | .expect("failed to set global default subscriber") | |
77 | } | |
78 | } | |
79 | ||
80 | impl<T> SubscriberInitExt for T where T: Into<Dispatch> {} | |
81 | ||
29967ef6 | 82 | /// Error returned by [`try_init`](SubscriberInitExt::try_init) if a global default subscriber could not be initialized. |
f035d41b XL |
83 | pub struct TryInitError { |
84 | inner: Box<dyn Error + Send + Sync + 'static>, | |
85 | } | |
86 | ||
87 | // ==== impl TryInitError ==== | |
88 | ||
89 | impl TryInitError { | |
90 | fn new(e: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self { | |
91 | Self { inner: e.into() } | |
92 | } | |
93 | } | |
94 | ||
95 | impl fmt::Debug for TryInitError { | |
96 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
97 | fmt::Debug::fmt(&self.inner, f) | |
98 | } | |
99 | } | |
100 | ||
101 | impl fmt::Display for TryInitError { | |
102 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
103 | fmt::Display::fmt(&self.inner, f) | |
104 | } | |
105 | } | |
106 | ||
107 | impl Error for TryInitError { | |
108 | fn source(&self) -> Option<&(dyn Error + 'static)> { | |
109 | self.inner.source() | |
110 | } | |
111 | } |