Skip to content

Commit

Permalink
subscriber: add Filtered::filter_mut method
Browse files Browse the repository at this point in the history
 ## Motivation

Changing the filter of a Filtered at runtime is currently only possible
by replacing it with a new Filtered via the reload::Handle's reload method.
This currently doesn't work (see
#1629).

While it would be desirable to just make that work, it would only be
possible via a breaking change (according to Eliza).
Making it possible to change the filter via the handle's modify method
and mutating the inner filter is an easy workaround.
  • Loading branch information
tfreiberg-fastly committed Mar 1, 2022
1 parent e1d3481 commit ddae0e9
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
34 changes: 34 additions & 0 deletions tracing-subscriber/src/filter/layer_filters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,40 @@ impl<L, F, S> Filtered<L, F, S> {
fn did_enable(&self, f: impl FnOnce()) {
FILTERING.with(|filtering| filtering.did_enable(self.id(), f))
}

/// Borrows the [`Filter`](crate::layer::Filter) used by this layer.
pub fn filter(&self) -> &F {
&self.filter
}

/// Mutably borrows the [`Filter`](crate::layer::Filter) used by this layer.
///
/// When this layer can be mutably borrowed, this may be used to mutate the filter.
/// Generally, this will primarily be used with the
/// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
///
/// # Examples
///
/// ```
/// # use tracing::info;
/// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*};
/// # fn main() {
/// let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
/// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
/// #
/// # // specifying the Registry type is required
/// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry>,
/// # filter::LevelFilter, Registry>,Registry>
/// # = &reload_handle;
/// #
/// info!("This will be ignored");
/// reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO);
/// info!("This will be logged");
/// # }
/// ```
pub fn filter_mut(&mut self) -> &mut F {
&mut self.filter
}
}

impl<S, L, F> Layer<S> for Filtered<L, F, S>
Expand Down
29 changes: 28 additions & 1 deletion tracing-subscriber/src/reload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@
//! change at runtime. Note that this layer introduces a (relatively small)
//! amount of overhead, and should thus only be used as needed.
//!
//! # Examples
//!
//! Reloading a [`Filtered`](crate::filter::Filtered) layer to change the filter at runtime.
//!
//! ```
//! # use tracing::info;
//! # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*};
//! # fn main() {
//! let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
//! let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
//! #
//! # // specifying the Registry type is required
//! # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry>,
//! # filter::LevelFilter, Registry>,Registry>
//! # = &reload_handle;
//! #
//! info!("This will be ignored");
//! reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO);
//! info!("This will be logged");
//! # }
//! ```
//!
//! [`Layer` type]: struct.Layer.html
//! [`Layer` trait]: ../layer/trait.Layer.html
use crate::layer;
Expand Down Expand Up @@ -36,7 +58,7 @@ pub struct Layer<L, S> {
_s: PhantomData<fn(S)>,
}

/// Allows reloading the state of an associated `Layer`.
/// Allows reloading the state of an associated [`Layer`](crate::layer::Layer).
#[derive(Debug)]
pub struct Handle<L, S> {
inner: Weak<RwLock<L>>,
Expand Down Expand Up @@ -150,6 +172,11 @@ where
S: Subscriber,
{
/// Replace the current layer with the provided `new_layer`.
///
/// **Warning:** The [`Filtered`](crate::filter::Filtered) type currently can't be changed
/// at runtime via the [`Handle::reload`] method.
/// Use the [`Handle::modify`] method to change the filter instead.
/// (see <https://github.com/tokio-rs/tracing/issues/1629>)
pub fn reload(&self, new_layer: impl Into<L>) -> Result<(), Error> {
self.modify(|layer| {
*layer = new_layer.into();
Expand Down

0 comments on commit ddae0e9

Please sign in to comment.