diff --git a/tracing-subscriber/src/fmt/fmt_layer.rs b/tracing-subscriber/src/fmt/fmt_layer.rs index c2708e2859..ac0990b3fd 100644 --- a/tracing-subscriber/src/fmt/fmt_layer.rs +++ b/tracing-subscriber/src/fmt/fmt_layer.rs @@ -87,8 +87,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 @@ -122,11 +122,40 @@ where _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, + _inner: self._inner, + } + } } // 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 +171,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, @@ -201,6 +227,39 @@ impl<S, N, E, W> Layer<S, N, E, W> { ..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, + make_writer: f(self.make_writer), + _inner: self._inner, + } + } } impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W> @@ -481,6 +540,36 @@ impl<S, N, E, W> Layer<S, N, E, W> { _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, + _inner: self._inner, + } + } } impl<S> Default for Layer<S> { diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 09a67a0b4f..7eb73a97ff 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -923,7 +923,7 @@ where } impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { - /// Sets the Visitor that the subscriber being built will use to record + /// Sets the field formatter that the subscriber being built will use to record /// fields. /// /// For example: @@ -1021,7 +1021,7 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// subscriber. /// /// If the max level has already been set, or a [`EnvFilter`] was added by - /// [`with_filter`], this replaces that configuration with the new + /// [`with_env_filter`], this replaces that configuration with the new /// maximum level. /// /// # Examples @@ -1044,8 +1044,8 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// .finish(); /// ``` /// [verbosity level]: https://docs.rs/tracing-core/0.1.5/tracing_core/struct.Level.html - /// [`EnvFilter`]: ../filter/struct.EnvFilter.html - /// [`with_filter`]: #method.with_filter + /// [`EnvFilter`]: struct@crate::filter::EnvFilter + /// [`with_env_filter`]: fn@Self::with_env_filter pub fn with_max_level( self, filter: impl Into<LevelFilter>, @@ -1057,8 +1057,26 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { } } - /// Sets the function that the subscriber being built should use to format - /// events that occur. + /// Sets the [event formatter][`FormatEvent`] that the subscriber being built + /// will use to format events that occur. + /// + /// The event formatter may be any type implementing the [`FormatEvent`] + /// trait, which is implemented for all functions taking a [`FmtContext`], a + /// [`Writer`], and an [`Event`]. + /// + /// # Examples + /// + /// Setting a type implementing [`FormatEvent`] as the formatter: + /// + /// ```rust + /// use tracing_subscriber::fmt::format; + /// + /// let subscriber = tracing_subscriber::fmt() + /// .event_format(format().compact()) + /// .finish(); + /// ``` + /// + /// [`Writer`]: struct@self::format::Writer pub fn event_format<E2>(self, fmt_event: E2) -> SubscriberBuilder<N, E2, F, W> where E2: FormatEvent<Registry, N> + 'static, @@ -1085,8 +1103,6 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { /// .with_writer(io::stderr) /// .init(); /// ``` - /// - /// [`MakeWriter`]: trait.MakeWriter.html pub fn with_writer<W2>(self, make_writer: W2) -> SubscriberBuilder<N, E, F, W2> where W2: for<'writer> MakeWriter<'writer> + 'static, @@ -1127,6 +1143,82 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> { inner: self.inner.with_writer(TestWriter::default()), } } + + /// Updates the event formatter by applying a function to the existing event formatter. + /// + /// This sets the event formatter that the subscriber being built will use to record fields. + /// + /// # Examples + /// + /// Updating an event formatter: + /// + /// ```rust + /// let subscriber = tracing_subscriber::fmt() + /// .map_event_format(|e| e.compact()) + /// .finish(); + /// ``` + pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> SubscriberBuilder<N, E2, F, W> + where + E2: FormatEvent<Registry, N> + 'static, + N: for<'writer> FormatFields<'writer> + 'static, + W: for<'writer> MakeWriter<'writer> + 'static, + { + SubscriberBuilder { + filter: self.filter, + inner: self.inner.map_event_format(f), + } + } + + /// Updates the field formatter by applying a function to the existing field formatter. + /// + /// This sets the field formatter that the subscriber being built will use to record fields. + /// + /// # Examples + /// + /// Updating a field formatter: + /// + /// ```rust + /// use tracing_subscriber::field::MakeExt; + /// let subscriber = tracing_subscriber::fmt() + /// .map_fmt_fields(|f| f.debug_alt()) + /// .finish(); + /// ``` + pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> SubscriberBuilder<N2, E, F, W> + where + N2: for<'writer> FormatFields<'writer> + 'static, + { + SubscriberBuilder { + filter: self.filter, + inner: self.inner.map_fmt_fields(f), + } + } + + /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`]. + /// + /// This sets the [`MakeWriter`] that the subscriber 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 = tracing_subscriber::fmt() + /// .map_writer(move |w| stderr.or_else(w)) + /// .finish(); + /// ``` + pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> SubscriberBuilder<N, E, F, W2> + where + W2: for<'writer> MakeWriter<'writer> + 'static, + { + SubscriberBuilder { + filter: self.filter, + inner: self.inner.map_writer(f), + } + } } /// Install a global tracing subscriber that listens for events and diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index f3f994490f..d041d7f78c 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -857,7 +857,7 @@ where /// per-layer filtering. /// /// [`Filtered`]: crate::filter::Filtered - /// [plf]: #per-layer-filtering + /// [plf]: crate::layer#per-layer-filtering #[cfg(all(feature = "registry", feature = "std"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))] fn with_filter<F>(self, filter: F) -> filter::Filtered<Self, F, S>