subscriber: impl Clone for EnvFilter (#3360)

This is useful when using `EnvFilter` for multiple identical per-layer
filters, as well as with clap and similar libraries that have `Clone`
bounds.

We generally expect users to be cloning an `EnvFilter` before attaching it
to a subscriber, rather than cloning `EnvFilters` that are already
attached. Because of this, we reset all the accumulated dynamic state
when cloning. This means that some spans and callsites might be missed
when an already-attached `EnvFilter` is cloned, but the presence of the
dynamic state mean that detaching and attaching `EnvFilter`s to existing
subscribers (e.g. with `reload`) already doesn't work very well. This
isn't a new class of problem.

There was a previous implementation of this in #2398, that shared the
dynamic state between all cloned filters behind an `Arc`. I chose
not do go for that approach because it causes inconsistencies if the
cloned filters are attached to different subscribers.

Fixes: #2360
This commit is contained in:
Olivia Lee 2025-08-15 02:39:17 -07:00 committed by GitHub
parent 3a1f571102
commit f71cebe41e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 0 deletions

View File

@ -204,6 +204,24 @@ pub struct EnvFilter {
regex: bool,
}
/// Creates an [`EnvFilter`] with the same directives as `self`.
///
/// This does *not* clone any of the dynamic state that [`EnvFilter`] acquires while attached to a
/// subscriber.
impl Clone for EnvFilter {
fn clone(&self) -> EnvFilter {
EnvFilter {
statics: self.statics.clone(),
dynamics: self.dynamics.clone(),
has_dynamics: self.has_dynamics,
by_id: RwLock::default(),
by_cs: RwLock::default(),
scope: ThreadLocal::new(),
regex: self.regex,
}
}
}
type FieldMap<T> = HashMap<Field, T>;
/// Indicates that an error occurred while parsing a `EnvFilter` from an

View File

@ -54,4 +54,12 @@ mod parking_lot_impl {
Ok(self.inner.write())
}
}
impl<T: Default> Default for RwLock<T> {
fn default() -> Self {
RwLock {
inner: parking_lot::RwLock::default(),
}
}
}
}