Skip to content

Commit 5f5f24c

Browse files
tfreiberg-fastlyhawkw
authored andcommitted
subscriber: add Filter::on_{new_span, enter, exit, close} (#1973)
Closes #1955 Call those methods in the `Subscribe` methods for `Filtered` and delegate them in the filter combinators ## Motivation Currently, if a `Filter` is going to implement dynamic filtering, it must do this by querying the wrapped Subscriber for the current span context. Since `Filter` only has callsite_enabled and enabled methods, a `Filter` implementation cannot track the span context internally, the way a subscriber can. Unfortunately, this means that the current implementation of `EnvFilter` can only implement `Subscribe` (and provide global filtering). It cannot currently implement `Filter`, because it stores span context data internally. See #1868 for details. ## Proposal We should add `on_new_span`, `on_enter`, `on_exit`, and `on_close` methods to `Filter`. This would allow implementing `Filter`s (such as `EnvFilter`) that internally track span states.
1 parent 8e6f0ed commit 5f5f24c

File tree

3 files changed

+116
-6
lines changed

3 files changed

+116
-6
lines changed

tracing-subscriber/src/filter/subscriber_filters/combinator.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
//! Filter combinators
22
use crate::subscribe::{Context, Filter};
33
use std::{cmp, fmt, marker::PhantomData};
4-
use tracing_core::{collect::Interest, LevelFilter, Metadata};
4+
use tracing_core::{
5+
collect::Interest,
6+
span::{Attributes, Id},
7+
LevelFilter, Metadata,
8+
};
59

610
/// Combines two [`Filter`]s so that spans and events are enabled if and only if
711
/// *both* filters return `true`.
@@ -132,6 +136,30 @@ where
132136
// If either hint is `None`, return `None`. Otherwise, return the most restrictive.
133137
cmp::min(self.a.max_level_hint(), self.b.max_level_hint())
134138
}
139+
140+
#[inline]
141+
fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
142+
self.a.on_new_span(attrs, id, ctx.clone());
143+
self.b.on_new_span(attrs, id, ctx)
144+
}
145+
146+
#[inline]
147+
fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
148+
self.a.on_enter(id, ctx.clone());
149+
self.b.on_enter(id, ctx);
150+
}
151+
152+
#[inline]
153+
fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
154+
self.a.on_exit(id, ctx.clone());
155+
self.b.on_exit(id, ctx);
156+
}
157+
158+
#[inline]
159+
fn on_close(&self, id: Id, ctx: Context<'_, S>) {
160+
self.a.on_close(id.clone(), ctx.clone());
161+
self.b.on_close(id, ctx);
162+
}
135163
}
136164

137165
impl<A, B, S> Clone for And<A, B, S>
@@ -289,6 +317,30 @@ where
289317
// If either hint is `None`, return `None`. Otherwise, return the less restrictive.
290318
Some(cmp::max(self.a.max_level_hint()?, self.b.max_level_hint()?))
291319
}
320+
321+
#[inline]
322+
fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
323+
self.a.on_new_span(attrs, id, ctx.clone());
324+
self.b.on_new_span(attrs, id, ctx)
325+
}
326+
327+
#[inline]
328+
fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
329+
self.a.on_enter(id, ctx.clone());
330+
self.b.on_enter(id, ctx);
331+
}
332+
333+
#[inline]
334+
fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
335+
self.a.on_exit(id, ctx.clone());
336+
self.b.on_exit(id, ctx);
337+
}
338+
339+
#[inline]
340+
fn on_close(&self, id: Id, ctx: Context<'_, S>) {
341+
self.a.on_close(id.clone(), ctx.clone());
342+
self.b.on_close(id, ctx);
343+
}
292344
}
293345

294346
impl<A, B, S> Clone for Or<A, B, S>
@@ -356,6 +408,26 @@ where
356408
// TODO(eliza): figure this out???
357409
None
358410
}
411+
412+
#[inline]
413+
fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
414+
self.a.on_new_span(attrs, id, ctx);
415+
}
416+
417+
#[inline]
418+
fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
419+
self.a.on_enter(id, ctx);
420+
}
421+
422+
#[inline]
423+
fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
424+
self.a.on_exit(id, ctx);
425+
}
426+
427+
#[inline]
428+
fn on_close(&self, id: Id, ctx: Context<'_, S>) {
429+
self.a.on_close(id, ctx);
430+
}
359431
}
360432

361433
impl<A, S> Clone for Not<A, S>

tracing-subscriber/src/filter/subscriber_filters/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,9 @@ where
612612

613613
fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, C>) {
614614
self.did_enable(|| {
615-
self.subscriber
616-
.on_new_span(attrs, id, cx.with_filter(self.id()));
615+
let cx = cx.with_filter(self.id());
616+
self.filter.on_new_span(attrs, id, cx.clone());
617+
self.subscriber.on_new_span(attrs, id, cx);
617618
})
618619
}
619620

@@ -644,19 +645,22 @@ where
644645

645646
fn on_enter(&self, id: &span::Id, cx: Context<'_, C>) {
646647
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
647-
self.subscriber.on_enter(id, cx)
648+
self.filter.on_enter(id, cx.clone());
649+
self.subscriber.on_enter(id, cx);
648650
}
649651
}
650652

651653
fn on_exit(&self, id: &span::Id, cx: Context<'_, C>) {
652654
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
653-
self.subscriber.on_exit(id, cx)
655+
self.filter.on_enter(id, cx.clone());
656+
self.subscriber.on_exit(id, cx);
654657
}
655658
}
656659

657660
fn on_close(&self, id: span::Id, cx: Context<'_, C>) {
658661
if let Some(cx) = cx.if_enabled_for(&id, self.id()) {
659-
self.subscriber.on_close(id, cx)
662+
self.filter.on_close(id.clone(), cx.clone());
663+
self.subscriber.on_close(id, cx);
660664
}
661665
}
662666

tracing-subscriber/src/subscribe/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,40 @@ pub trait Filter<S> {
965965
fn max_level_hint(&self) -> Option<LevelFilter> {
966966
None
967967
}
968+
969+
/// Notifies this filter that a new span was constructed with the given
970+
/// `Attributes` and `Id`.
971+
///
972+
/// By default, this method does nothing. `Filter` implementations that
973+
/// need to be notified when new spans are created can override this
974+
/// method.
975+
fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
976+
let _ = (attrs, id, ctx);
977+
}
978+
979+
/// Notifies this filter that a span with the given ID was entered.
980+
///
981+
/// By default, this method does nothing. `Filter` implementations that
982+
/// need to be notified when a span is entered can override this method.
983+
fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
984+
let _ = (id, ctx);
985+
}
986+
987+
/// Notifies this filter that a span with the given ID was exited.
988+
///
989+
/// By default, this method does nothing. `Filter` implementations that
990+
/// need to be notified when a span is exited can override this method.
991+
fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
992+
let _ = (id, ctx);
993+
}
994+
995+
/// Notifies this filter that a span with the given ID has been closed.
996+
///
997+
/// By default, this method does nothing. `Filter` implementations that
998+
/// need to be notified when a span is closed can override this method.
999+
fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
1000+
let _ = (id, ctx);
1001+
}
9681002
}
9691003

9701004
/// Extension trait adding a `with(Subscribe)` combinator to types implementing

0 commit comments

Comments
 (0)