Skip to content

Commit b411a5c

Browse files
authored
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 4b2903f commit b411a5c

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
@@ -5,7 +5,7 @@ use alloc::vec;
55
use alloc::{string::String, vec::Vec};
66

77
use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr};
8-
use tracing_core::Metadata;
8+
use tracing_core::{Level, Metadata};
99
/// Indicates that a string could not be parsed as a filtering directive.
1010
#[derive(Debug)]
1111
pub struct ParseError {
@@ -142,6 +142,22 @@ impl DirectiveSet<StaticDirective> {
142142
None => false,
143143
}
144144
}
145+
146+
/// Same as `enabled` above, but skips `Directive`'s with fields.
147+
pub(crate) fn target_enabled(&self, target: &str, level: &Level) -> bool {
148+
match self.directives_for_target(target).next() {
149+
Some(d) => d.level >= *level,
150+
None => false,
151+
}
152+
}
153+
154+
pub(crate) fn directives_for_target<'a>(
155+
&'a self,
156+
target: &'a str,
157+
) -> impl Iterator<Item = &'a StaticDirective> + 'a {
158+
self.directives()
159+
.filter(move |d| d.cares_about_target(target))
160+
}
145161
}
146162

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

163195
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::{Interest, Metadata, Subscriber};
23+
use tracing_core::{Interest, Level, Metadata, Subscriber};
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)