diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/tracing-subscriber/src/fmt/fmt_layer.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs) | 321 |
1 files changed, 294 insertions, 27 deletions
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs index 0e0d5e0eb..6e4e2ac0b 100644 --- a/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs +++ b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs @@ -56,7 +56,7 @@ use tracing_core::{ /// # tracing::subscriber::set_global_default(subscriber).unwrap(); /// ``` /// -/// [`Layer`]: ../layer/trait.Layer.html +/// [`Layer`]: super::layer::Layer #[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))] #[derive(Debug)] pub struct Layer< @@ -70,11 +70,12 @@ pub struct Layer< fmt_event: E, fmt_span: format::FmtSpanConfig, is_ansi: bool, - _inner: PhantomData<S>, + log_internal_errors: bool, + _inner: PhantomData<fn(S)>, } impl<S> Layer<S> { - /// Returns a new [`Layer`](struct.Layer.html) with the default configuration. + /// Returns a new [`Layer`][self::Layer] with the default configuration. pub fn new() -> Self { Self::default() } @@ -87,8 +88,8 @@ where N: for<'writer> FormatFields<'writer> + 'static, W: for<'writer> MakeWriter<'writer> + 'static, { - /// Sets the [event formatter][`FormatEvent`] that the layer will use to - /// format events. + /// Sets the [event formatter][`FormatEvent`] that the layer being built will + /// use to format events. /// /// The event formatter may be any type implementing the [`FormatEvent`] /// trait, which is implemented for all functions taking a [`FmtContext`], a @@ -108,7 +109,7 @@ where /// ``` /// [`FormatEvent`]: format::FormatEvent /// [`Event`]: tracing::Event - /// [`Writer`]: crate::format::Writer + /// [`Writer`]: format::Writer pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W> where E2: FormatEvent<S, N> + 'static, @@ -119,6 +120,37 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, + _inner: self._inner, + } + } + + /// Updates the event formatter by applying a function to the existing event formatter. + /// + /// This sets the event formatter that the layer being built will use to record fields. + /// + /// # Examples + /// + /// Updating an event formatter: + /// + /// ```rust + /// let layer = tracing_subscriber::fmt::layer() + /// .map_event_format(|e| e.compact()); + /// # // this is necessary for type inference. + /// # use tracing_subscriber::Layer as _; + /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); + /// ``` + pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> Layer<S, N, E2, W> + where + E2: FormatEvent<S, N> + 'static, + { + Layer { + fmt_fields: self.fmt_fields, + fmt_event: f(self.fmt_event), + fmt_span: self.fmt_span, + make_writer: self.make_writer, + is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -126,7 +158,7 @@ where // This needs to be a seperate impl block because they place different bounds on the type parameters. impl<S, N, E, W> Layer<S, N, E, W> { - /// Sets the [`MakeWriter`] that the [`Layer`] being built will use to write events. + /// Sets the [`MakeWriter`] that the layer being built will use to write events. /// /// # Examples /// @@ -142,9 +174,6 @@ impl<S, N, E, W> Layer<S, N, E, W> { /// # use tracing_subscriber::Layer as _; /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); /// ``` - /// - /// [`MakeWriter`]: ../fmt/trait.MakeWriter.html - /// [`Layer`]: ../layer/trait.Layer.html pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, N, E, W2> where W2: for<'writer> MakeWriter<'writer> + 'static, @@ -154,12 +183,63 @@ impl<S, N, E, W> Layer<S, N, E, W> { fmt_event: self.fmt_event, fmt_span: self.fmt_span, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, make_writer, _inner: self._inner, } } - /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in + /// Borrows the [writer] for this [`Layer`]. + /// + /// [writer]: MakeWriter + pub fn writer(&self) -> &W { + &self.make_writer + } + + /// Mutably borrows the [writer] for this [`Layer`]. + /// + /// This method is primarily expected to be used with the + /// [`reload::Handle::modify`](crate::reload::Handle::modify) method. + /// + /// # Examples + /// + /// ``` + /// # use tracing::info; + /// # use tracing_subscriber::{fmt,reload,Registry,prelude::*}; + /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) { + /// # std::io::stdout + /// # } + /// # fn main() { + /// let layer = fmt::layer().with_writer(non_blocking(std::io::stderr())); + /// let (layer, reload_handle) = reload::Layer::new(layer); + /// # + /// # // specifying the Registry type is required + /// # let _: &reload::Handle<fmt::Layer<Registry, _, _, _>, Registry> = &reload_handle; + /// # + /// info!("This will be logged to stderr"); + /// reload_handle.modify(|layer| *layer.writer_mut() = non_blocking(std::io::stdout())); + /// info!("This will be logged to stdout"); + /// # } + /// ``` + /// + /// [writer]: MakeWriter + pub fn writer_mut(&mut self) -> &mut W { + &mut self.make_writer + } + + /// Sets whether this layer should use ANSI terminal formatting + /// escape codes (such as colors). + /// + /// This method is primarily expected to be used with the + /// [`reload::Handle::modify`](crate::reload::Handle::modify) method when changing + /// the writer. + #[cfg(feature = "ansi")] + #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))] + pub fn set_ansi(&mut self, ansi: bool) { + self.is_ansi = ansi; + } + + /// Configures the layer to support [`libtest`'s output capturing][capturing] when used in /// unit tests. /// /// See [`TestWriter`] for additional details. @@ -180,13 +260,14 @@ impl<S, N, E, W> Layer<S, N, E, W> { /// ``` /// [capturing]: /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output - /// [`TestWriter`]: writer/struct.TestWriter.html + /// [`TestWriter`]: super::writer::TestWriter pub fn with_test_writer(self) -> Layer<S, N, E, TestWriter> { Layer { fmt_fields: self.fmt_fields, fmt_event: self.fmt_event, fmt_span: self.fmt_span, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, make_writer: TestWriter::default(), _inner: self._inner, } @@ -201,6 +282,58 @@ impl<S, N, E, W> Layer<S, N, E, W> { ..self } } + + /// Sets whether to write errors from [`FormatEvent`] to the writer. + /// Defaults to true. + /// + /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to + /// the writer. These errors are unlikely and will only occur if there is a + /// bug in the `FormatEvent` implementation or its dependencies. + /// + /// If writing to the writer fails, the error message is printed to stderr + /// as a fallback. + /// + /// [`FormatEvent`]: crate::fmt::FormatEvent + pub fn log_internal_errors(self, log_internal_errors: bool) -> Self { + Self { + log_internal_errors, + ..self + } + } + + /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`]. + /// + /// This sets the [`MakeWriter`] that the layer being built will use to write events. + /// + /// # Examples + /// + /// Redirect output to stderr if level is <= WARN: + /// + /// ```rust + /// use tracing::Level; + /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt}; + /// + /// let stderr = std::io::stderr.with_max_level(Level::WARN); + /// let layer = fmt::layer() + /// .map_writer(move |w| stderr.or_else(w)); + /// # // this is necessary for type inference. + /// # use tracing_subscriber::Layer as _; + /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); + /// ``` + pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> Layer<S, N, E, W2> + where + W2: for<'writer> MakeWriter<'writer> + 'static, + { + Layer { + fmt_fields: self.fmt_fields, + fmt_event: self.fmt_event, + fmt_span: self.fmt_span, + is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, + make_writer: f(self.make_writer), + _inner: self._inner, + } + } } impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W> @@ -228,6 +361,7 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -240,6 +374,7 @@ where fmt_span: self.fmt_span.without_time(), make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -284,7 +419,7 @@ where /// `Layer`s added to this subscriber. /// /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle - /// [time]: #method.without_time + /// [time]: Layer::without_time() pub fn with_span_events(self, kind: FmtSpan) -> Self { Layer { fmt_span: self.fmt_span.with_kind(kind), @@ -299,6 +434,30 @@ where ..self } } + /// Sets whether or not an event's [source code file path][file] is + /// displayed. + /// + /// [file]: tracing_core::Metadata::file + pub fn with_file(self, display_filename: bool) -> Layer<S, N, format::Format<L, T>, W> { + Layer { + fmt_event: self.fmt_event.with_file(display_filename), + ..self + } + } + + /// Sets whether or not an event's [source code line number][line] is + /// displayed. + /// + /// [line]: tracing_core::Metadata::line + pub fn with_line_number( + self, + display_line_number: bool, + ) -> Layer<S, N, format::Format<L, T>, W> { + Layer { + fmt_event: self.fmt_event.with_line_number(display_line_number), + ..self + } + } /// Sets whether or not an event's level is displayed. pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> { @@ -309,9 +468,9 @@ where } /// Sets whether or not the [thread ID] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html + /// [thread ID]: std::thread::ThreadId pub fn with_thread_ids(self, display_thread_ids: bool) -> Layer<S, N, format::Format<L, T>, W> { Layer { fmt_event: self.fmt_event.with_thread_ids(display_thread_ids), @@ -320,9 +479,9 @@ where } /// Sets whether or not the [name] of the current thread is displayed - /// when formatting events + /// when formatting events. /// - /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads + /// [name]: std::thread#naming-threads pub fn with_thread_names( self, display_thread_names: bool, @@ -333,7 +492,7 @@ where } } - /// Sets the layer being built to use a [less verbose formatter](../fmt/format/struct.Compact.html). + /// Sets the layer being built to use a [less verbose formatter][super::format::Compact]. pub fn compact(self) -> Layer<S, N, format::Format<format::Compact, T>, W> where N: for<'writer> FormatFields<'writer> + 'static, @@ -344,6 +503,7 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -358,11 +518,12 @@ where fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } - /// Sets the layer being built to use a [JSON formatter](../fmt/format/struct.Json.html). + /// Sets the layer being built to use a [JSON formatter][super::format::Json]. /// /// The full format includes fields from all entered spans. /// @@ -377,7 +538,7 @@ where /// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root /// object. /// - /// [`Layer::flatten_event`]: #method.flatten_event + /// [`Layer::flatten_event`]: Layer::flatten_event() #[cfg(feature = "json")] #[cfg_attr(docsrs, doc(cfg(feature = "json")))] pub fn json(self) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { @@ -388,6 +549,7 @@ where make_writer: self.make_writer, // always disable ANSI escapes in JSON mode! is_ansi: false, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -398,7 +560,7 @@ where impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { /// Sets the JSON layer being built to flatten event metadata. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::format::Json] pub fn flatten_event( self, flatten_event: bool, @@ -413,7 +575,7 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { /// Sets whether or not the formatter will include the current span in /// formatted events. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::format::Json] pub fn with_current_span( self, display_current_span: bool, @@ -428,7 +590,7 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { /// Sets whether or not the formatter will include a list (from root to leaf) /// of all currently entered spans in formatted events. /// - /// See [`format::Json`](../fmt/format/struct.Json.html) + /// See [`format::Json`][super::format::Json] pub fn with_span_list( self, display_span_list: bool, @@ -454,6 +616,38 @@ impl<S, N, E, W> Layer<S, N, E, W> { fmt_span: self.fmt_span, make_writer: self.make_writer, is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, + _inner: self._inner, + } + } + + /// Updates the field formatter by applying a function to the existing field formatter. + /// + /// This sets the field formatter that the layer being built will use to record fields. + /// + /// # Examples + /// + /// Updating a field formatter: + /// + /// ```rust + /// use tracing_subscriber::field::MakeExt; + /// let layer = tracing_subscriber::fmt::layer() + /// .map_fmt_fields(|f| f.debug_alt()); + /// # // this is necessary for type inference. + /// # use tracing_subscriber::Layer as _; + /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); + /// ``` + pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> Layer<S, N2, E, W> + where + N2: for<'writer> FormatFields<'writer> + 'static, + { + Layer { + fmt_event: self.fmt_event, + fmt_fields: f(self.fmt_fields), + fmt_span: self.fmt_span, + make_writer: self.make_writer, + is_ansi: self.is_ansi, + log_internal_errors: self.log_internal_errors, _inner: self._inner, } } @@ -467,6 +661,7 @@ impl<S> Default for Layer<S> { fmt_span: format::FmtSpanConfig::default(), make_writer: io::stdout, is_ansi: cfg!(feature = "ansi"), + log_internal_errors: false, _inner: PhantomData, } } @@ -497,7 +692,7 @@ where /// formatters are in use, each can store its own formatted representation /// without conflicting. /// -/// [extensions]: ../registry/struct.Extensions.html +/// [extensions]: crate::registry::Extensions #[derive(Default)] pub struct FormattedFields<E: ?Sized> { _format_fields: PhantomData<fn(E)>, @@ -586,6 +781,11 @@ where { fields.was_ansi = self.is_ansi; extensions.insert(fields); + } else { + eprintln!( + "[tracing-subscriber] Unable to format the following event, ignoring: {:?}", + attrs + ); } } @@ -732,7 +932,20 @@ where .is_ok() { let mut writer = self.make_writer.make_writer_for(event.metadata()); - let _ = io::Write::write_all(&mut writer, buf.as_bytes()); + let res = io::Write::write_all(&mut writer, buf.as_bytes()); + if self.log_internal_errors { + if let Err(e) = res { + eprintln!("[tracing-subscriber] Unable to write an event to the Writer for this Subscriber! Error: {}\n", e); + } + } + } else if self.log_internal_errors { + let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?}\n", + event.metadata().name(), event.fields()); + let mut writer = self.make_writer.make_writer_for(event.metadata()); + let res = io::Write::write_all(&mut writer, err_msg.as_bytes()); + if let Err(e) = res { + eprintln!("[tracing-subscriber] Unable to write an \"event formatting error\" to the Writer for this Subscriber! Error: {}\n", e); + } } buf.clear(); @@ -821,7 +1034,7 @@ where /// If this returns `None`, then no span exists for that ID (either it has /// closed or the ID is invalid). /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef #[inline] pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>> where @@ -844,7 +1057,7 @@ where /// /// If this returns `None`, then we are not currently within a span. /// - /// [stored data]: ../registry/struct.SpanRef.html + /// [stored data]: crate::registry::SpanRef #[inline] pub fn lookup_current(&self) -> Option<SpanRef<'_, S>> where @@ -1030,6 +1243,60 @@ mod test { } #[test] + fn format_error_print_to_stderr() { + struct AlwaysError; + + impl std::fmt::Debug for AlwaysError { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Err(std::fmt::Error) + } + } + + let make_writer = MockMakeWriter::default(); + let subscriber = crate::fmt::Subscriber::builder() + .with_writer(make_writer.clone()) + .with_level(false) + .with_ansi(false) + .with_timer(MockTime) + .finish(); + + with_default(subscriber, || { + tracing::info!(?AlwaysError); + }); + let actual = sanitize_timings(make_writer.get_string()); + + // Only assert the start because the line number and callsite may change. + let expected = concat!("Unable to format the following event. Name: event ", file!(), ":"); + assert!(actual.as_str().starts_with(expected), "\nactual = {}\nshould start with expected = {}\n", actual, expected); + } + + #[test] + fn format_error_ignore_if_log_internal_errors_is_false() { + struct AlwaysError; + + impl std::fmt::Debug for AlwaysError { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + Err(std::fmt::Error) + } + } + + let make_writer = MockMakeWriter::default(); + let subscriber = crate::fmt::Subscriber::builder() + .with_writer(make_writer.clone()) + .with_level(false) + .with_ansi(false) + .with_timer(MockTime) + .log_internal_errors(false) + .finish(); + + with_default(subscriber, || { + tracing::info!(?AlwaysError); + }); + let actual = sanitize_timings(make_writer.get_string()); + assert_eq!("", actual.as_str()); + } + + #[test] fn synthesize_span_none() { let make_writer = MockMakeWriter::default(); let subscriber = crate::fmt::Subscriber::builder() |