Skip to content

Commit

Permalink
subscriber: add Filtered::filter_mut method (#1959)
Browse files Browse the repository at this point in the history
Partially fixes #1629 (I think making `reload::Handle::reload` work with
`Filtered` would be cleaner, but this approach seemed easier to me)

I assumed opening the PR against v0.1.x is correct as I couldn't find
the `Filtered` type in master.

I think it'd be sensible to note the fact that `reload::Handle::reload`
doesn't work with `Filtered` in the docs somewhere, should I add that?

## Motivation

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

While it would be desirable to just make that work, it would only be
possible via a breaking change (according to Eliza) so this seems like a
reasonable (and easy) workaround for now. (I can't judge whether this
method is only useful as a workaround for the bug or if it suits the
public API independently)

## Solution

Offer mutable access to the `Filtered::filter` field in the public API.
This can be used via the `reload::Handle::modify` method to change the
filter inside the existing `Filtered`.

Fixes #1629
  • Loading branch information
tfreiberg-fastly authored Mar 1, 2022
1 parent e1d3481 commit 4f714f0
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 4f714f0

Please sign in to comment.