Skip to content

Commit 15ea126

Browse files
guswynnhawkw
authored andcommitted
subscriber: add Targets::would_enable (#1903
## Motivation As discussed on discord, this API + `Targets` being `: Clone` makes it easier to solve the original problem I had tried to solve in #1889. My plan on how to use this is in https://github.com/MaterializeInc/materialize/issues/10441 if you are interested! ## Solution I considered doing some macro magic to create a `Metadata` with a callsite and empty fields and everything, to be able to called `DirectiveSet::enabled`, but it felt cleaner and easier to reason about the special-case-ness (`Targets` never having field filters) using a new set of methods that do a similar thing. For testing I opted for just a doc-test, let me know if thats fine!
1 parent 0a48a8f commit 15ea126

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

tracing-subscriber/src/filter/directive.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use alloc::{
44
vec::{self, Vec},
55
};
66
use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr};
7-
use tracing_core::Metadata;
7+
use tracing_core::{Level, Metadata};
88
/// Indicates that a string could not be parsed as a filtering directive.
99
#[derive(Debug)]
1010
pub struct ParseError {
@@ -141,6 +141,22 @@ impl DirectiveSet<StaticDirective> {
141141
None => false,
142142
}
143143
}
144+
145+
/// Same as `enabled` above, but skips `Directive`'s with fields.
146+
pub(crate) fn target_enabled(&self, target: &str, level: &Level) -> bool {
147+
match self.directives_for_target(target).next() {
148+
Some(d) => d.level >= *level,
149+
None => false,
150+
}
151+
}
152+
153+
pub(crate) fn directives_for_target<'a>(
154+
&'a self,
155+
target: &'a str,
156+
) -> impl Iterator<Item = &'a StaticDirective> + 'a {
157+
self.directives()
158+
.filter(move |d| d.cares_about_target(target))
159+
}
144160
}
145161

146162
// === impl StaticDirective ===
@@ -157,6 +173,22 @@ impl StaticDirective {
157173
level,
158174
}
159175
}
176+
177+
pub(in crate::filter) fn cares_about_target(&self, to_check: &str) -> bool {
178+
// Does this directive have a target filter, and does it match the
179+
// metadata's target?
180+
if let Some(ref target) = self.target {
181+
if !to_check.starts_with(&target[..]) {
182+
return false;
183+
}
184+
}
185+
186+
if !self.field_names.is_empty() {
187+
return false;
188+
}
189+
190+
true
191+
}
160192
}
161193

162194
impl Ord for StaticDirective {

tracing-subscriber/src/filter/targets.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use core::{
2020
slice,
2121
str::FromStr,
2222
};
23-
use tracing_core::{Collect, Interest, Metadata};
23+
use tracing_core::{Collect, Interest, Level, Metadata};
2424

2525
/// A filter that enables or disables spans and events based on their [target]
2626
/// and [level].
@@ -313,6 +313,35 @@ impl Targets {
313313
Interest::never()
314314
}
315315
}
316+
317+
/// Returns whether a [target]-[`Level`] pair would be enabled
318+
/// by this `Targets`.
319+
///
320+
/// This method can be used with [`module_path!`] from `std` as the target
321+
/// in order to emulate the behavior of the [`tracing::event!`] and [`tracing::span!`]
322+
/// macros.
323+
///
324+
/// # Examples
325+
///
326+
/// ```
327+
/// use tracing_subscriber::filter::{Targets, LevelFilter};
328+
/// use tracing_core::Level;
329+
///
330+
/// let filter = Targets::new()
331+
/// .with_target("my_crate", Level::INFO)
332+
/// .with_target("my_crate::interesting_module", Level::DEBUG);
333+
///
334+
/// assert!(filter.would_enable("my_crate", &Level::INFO));
335+
/// assert!(!filter.would_enable("my_crate::interesting_module", &Level::TRACE));
336+
/// ```
337+
///
338+
/// [target]: tracing_core::Metadata::target
339+
/// [`module_path!`]: std::module_path!
340+
pub fn would_enable(&self, target: &str, level: &Level) -> bool {
341+
// "Correct" to call because `Targets` only produces `StaticDirective`'s with NO
342+
// fields
343+
self.0.target_enabled(target, level)
344+
}
316345
}
317346

318347
impl<T, L> Extend<(T, L)> for Targets

0 commit comments

Comments
 (0)