From f71cebe41e4c12735b1d19ca804428d4ff7d905d Mon Sep 17 00:00:00 2001 From: Olivia Lee Date: Fri, 15 Aug 2025 02:39:17 -0700 Subject: [PATCH] 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 --- tracing-subscriber/src/filter/env/mod.rs | 18 ++++++++++++++++++ tracing-subscriber/src/sync.rs | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/tracing-subscriber/src/filter/env/mod.rs b/tracing-subscriber/src/filter/env/mod.rs index 005851d6..a9d93793 100644 --- a/tracing-subscriber/src/filter/env/mod.rs +++ b/tracing-subscriber/src/filter/env/mod.rs @@ -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 = HashMap; /// Indicates that an error occurred while parsing a `EnvFilter` from an diff --git a/tracing-subscriber/src/sync.rs b/tracing-subscriber/src/sync.rs index ec42b834..be41f1b9 100644 --- a/tracing-subscriber/src/sync.rs +++ b/tracing-subscriber/src/sync.rs @@ -54,4 +54,12 @@ mod parking_lot_impl { Ok(self.inner.write()) } } + + impl Default for RwLock { + fn default() -> Self { + RwLock { + inner: parking_lot::RwLock::default(), + } + } + } }