3232//! info!("This will be logged");
3333//! ```
3434//!
35- //! Reloading a [`Filtered`](crate::filter::Filtered) layer:
35+ //! Reloading the [`Filter`] of a [`Filtered`](crate::filter::Filtered) layer:
3636//!
3737//! ```rust
3838//! # use tracing::info;
5353//! info!("This will be logged");
5454//! ```
5555//!
56+ //! Reloading a [`Filtered`](crate::filter::Filtered) layer using [`Handle::reload_filtered`]:
57+ //!
58+ //! ```rust
59+ //! use tracing::info;
60+ //! use tracing_subscriber::{filter, fmt, reload, prelude::*};
61+ //! let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
62+ //! let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
63+ //! let dispatcher =
64+ //! tracing_core::Dispatch::new(tracing_subscriber::registry().with(filtered_layer));
65+ //!
66+ //! tracing_core::dispatcher::with_default(&dispatcher, || {
67+ //! info!("This will be ignored");
68+ //! let new_layer = fmt::Layer::default().with_filter(filter::LevelFilter::INFO);
69+ //! let subscriber = dispatcher
70+ //! .downcast_ref::<tracing_subscriber::Registry>()
71+ //! .unwrap();
72+ //! reload_handle
73+ //! .reload_filtered(new_layer, subscriber)
74+ //! .unwrap();
75+ //! info!("This will be logged");
76+ //! });
77+ //! ```
78+ //!
79+ //! Reloading a [`Filtered`](crate::filter::Filtered) layer using [`Handle::modify`]:
80+ //!
81+ //! ```rust
82+ //! use tracing::info;
83+ //! use tracing_subscriber::{filter, fmt, reload, prelude::*};
84+ //! let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
85+ //! let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
86+ //! let dispatcher =
87+ //! tracing_core::Dispatch::new(tracing_subscriber::registry().with(filtered_layer));
88+ //!
89+ //! tracing_core::dispatcher::with_default(&dispatcher, || {
90+ //! info!("This will be ignored");
91+ //! let new_layer = fmt::Layer::default().with_filter(filter::LevelFilter::INFO);
92+ //! let subscriber = dispatcher
93+ //! .downcast_ref::<tracing_subscriber::Registry>()
94+ //! .unwrap();
95+ //! reload_handle.modify(|layer| {
96+ //! *layer = new_layer;
97+ //! layer.on_reload_layer(subscriber);
98+ //! }).unwrap();
99+ //! info!("This will be logged");
100+ //! });
101+ //! ```
102+ //!
56103//! ## Note
57104//!
58105//! The [`Layer`] implementation is unable to implement downcasting functionality,
62109//! `Filter` on a layer, prefer wrapping that `Filter` in the `reload::Layer`.
63110//!
64111//! [`Filter` trait]: crate::layer::Filter
112+ //! [`Filter`]: crate::layer::Filter
65113//! [`Layer` type]: Layer
66114//! [`Layer` trait]: super::layer::Layer
67115use crate :: layer;
@@ -124,6 +172,10 @@ where
124172 try_lock ! ( self . inner. write( ) , else return ) . on_layer ( subscriber) ;
125173 }
126174
175+ fn on_reload_layer ( & mut self , subscriber : & S ) {
176+ try_lock ! ( self . inner. write( ) , else return ) . on_reload_layer ( subscriber) ;
177+ }
178+
127179 #[ inline]
128180 fn register_callsite ( & self , metadata : & ' static Metadata < ' static > ) -> Interest {
129181 try_lock ! ( self . inner. read( ) , else return Interest :: sometimes( ) ) . register_callsite ( metadata)
@@ -287,7 +339,9 @@ impl<L, S> Handle<L, S> {
287339 /// Replace the current [`Layer`] or [`Filter`] with the provided `new_value`.
288340 ///
289341 /// [`Handle::reload`] cannot be used with the [`Filtered`] layer; use
290- /// [`Handle::modify`] instead (see [this issue] for additional details).
342+ /// [`Handle::reload_filtered`] instead, or [`Handle::modify`] to replace
343+ /// the [`Filter`] of a [`Filtered`] layer (see [this issue] for additional
344+ /// details).
291345 ///
292346 /// However, if the _only_ the [`Filter`] needs to be modified, use
293347 /// `reload::Layer` to wrap the `Filter` directly.
@@ -303,6 +357,36 @@ impl<L, S> Handle<L, S> {
303357 } )
304358 }
305359
360+ /// Replaces the current [`Filtered`] layer with a new one and performs
361+ /// late initialization using [`Layer::on_reload_layer`].
362+ ///
363+ /// Unlike [`Handle::reload`], this method is specifically designed to
364+ /// support [per-layer filtering] by ensuring that the [`Filter`] within
365+ /// a [`Filtered`] layer is correctly registered with the [`Subscriber`].
366+ /// It achieves this by invoking the [`Layer::on_reload_layer`] callback
367+ /// after replacing the layer, allowing the new filter to be initialized
368+ /// using only a shared reference to the `Subscriber`.
369+ ///
370+ /// This method should be used instead of [`reload`] when reloading a
371+ /// [`Filtered`] layer.
372+ ///
373+ /// [`Filter`]: crate::layer::Filter
374+ /// [`Filtered`]: crate::filter::Filtered
375+ /// [`reload`]: Self::reload
376+ /// [`Subscriber`]: tracing::Subscriber
377+ /// [`Layer::on_reload_layer`]: crate::layer::Layer::on_reload_layer
378+ /// [per-layer filtering]: crate::layer::Layer#per-layer-filtering
379+ pub fn reload_filtered ( & self , new_value : impl Into < L > , subscriber : & S ) -> Result < ( ) , Error >
380+ where
381+ L : crate :: layer:: Layer < S > + ' static ,
382+ S : Subscriber ,
383+ {
384+ self . modify ( |layer| {
385+ * layer = new_value. into ( ) ;
386+ layer. on_reload_layer ( subscriber) ;
387+ } )
388+ }
389+
306390 /// Invokes a closure with a mutable reference to the current layer or filter,
307391 /// allowing it to be modified in place.
308392 pub fn modify ( & self , f : impl FnOnce ( & mut L ) ) -> Result < ( ) , Error > {
0 commit comments