Skip to content

Commit 8bc008c

Browse files
bantonssonhds
andauthored
fix(subscriber): make Layered propagate on_register_dispatch (#3379)
## Motivation The `Layered` implementation of `Subscriber` does not implement and propagate the `on_register_dispatch` callback. This means that combined layers will never have their `on_register_dispatch` methods called. ## Solution Implement the missing `on_register_dispatch` method. --------- Co-authored-by: Hayden Stainsby <[email protected]>
1 parent adbd8a4 commit 8bc008c

File tree

6 files changed

+182
-0
lines changed

6 files changed

+182
-0
lines changed

tracing-mock/src/expect.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub(crate) enum Expect {
4242
DropSpan(ExpectedSpan),
4343
Visit(ExpectedSpan, ExpectedFields),
4444
NewSpan(NewSpan),
45+
OnRegisterDispatch,
4546
Nothing,
4647
}
4748

@@ -324,6 +325,10 @@ impl Expect {
324325
"\n[{}] expected {}\n[{}] but instead {}",
325326
name, e, name, what
326327
),
328+
Expect::OnRegisterDispatch => panic!(
329+
"\n[{}] expected on_register_dispatch to be called\n[{}] but instead {}",
330+
name, name, what
331+
),
327332
Expect::Nothing => panic!(
328333
"\n[{}] expected nothing else to happen\n[{}] but {} instead",
329334
name, name, what,

tracing-mock/src/layer.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,41 @@ impl MockLayerBuilder {
642642
self
643643
}
644644

645+
/// Adds an expectation that [`Layer::on_register_dispatch`] will
646+
/// be called next.
647+
///
648+
/// **Note**: This expectation is usually fulfilled automatically when
649+
/// a layer (wrapped in a subscriber) is set as the default via
650+
/// [`tracing::subscriber::with_default`] or
651+
/// [`tracing::subscriber::set_global_default`], so explicitly expecting
652+
/// this is not usually necessary. However, it may be useful when testing
653+
/// custom layer implementations that manually call `on_register_dispatch`.
654+
///
655+
/// # Examples
656+
///
657+
/// ```
658+
/// use tracing_mock::{expect, layer};
659+
/// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
660+
///
661+
/// let (layer, handle) = layer::mock()
662+
/// .on_register_dispatch()
663+
/// .run_with_handle();
664+
///
665+
/// let _subscriber = tracing_subscriber::registry()
666+
/// .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
667+
/// .set_default();
668+
///
669+
/// // The layer's on_register_dispatch was called when the subscriber was set as default
670+
///
671+
/// handle.assert_finished();
672+
/// ```
673+
///
674+
/// [`Layer::on_register_dispatch`]: tracing_subscriber::layer::Layer::on_register_dispatch
675+
pub fn on_register_dispatch(mut self) -> Self {
676+
self.expected.push_back(Expect::OnRegisterDispatch);
677+
self
678+
}
679+
645680
/// Expects that no further traces are received.
646681
///
647682
/// The call to `only` should appear immediately before the final
@@ -835,6 +870,14 @@ impl<C> Layer<C> for MockLayer
835870
where
836871
C: Subscriber + for<'a> LookupSpan<'a>,
837872
{
873+
fn on_register_dispatch(&self, _subscriber: &tracing::Dispatch) {
874+
println!("[{}] on_register_dispatch", self.name);
875+
let mut expected = self.expected.lock().unwrap();
876+
if let Some(Expect::OnRegisterDispatch) = expected.front() {
877+
expected.pop_front();
878+
}
879+
}
880+
838881
fn register_callsite(
839882
&self,
840883
metadata: &'static tracing::Metadata<'static>,

tracing-mock/src/subscriber.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,37 @@ where
802802
self
803803
}
804804

805+
/// Adds an expectation that [`Subscriber::on_register_dispatch`] will
806+
/// be called next.
807+
///
808+
/// **Note**: This expectation is usually fulfilled automatically when
809+
/// a subscriber is set as the default via [`tracing::subscriber::with_default`]
810+
/// or [`tracing::subscriber::set_global_default`], so explicitly expecting
811+
/// this is not usually necessary. However, it may be useful when testing
812+
/// custom subscriber implementations that manually call `on_register_dispatch`.
813+
///
814+
/// # Examples
815+
///
816+
/// ```
817+
/// use tracing_mock::{expect, subscriber};
818+
///
819+
/// let (subscriber, handle) = subscriber::mock()
820+
/// .on_register_dispatch()
821+
/// .run_with_handle();
822+
///
823+
/// tracing::subscriber::with_default(subscriber, || {
824+
/// // The subscriber's on_register_dispatch was called when it was set as default
825+
/// });
826+
///
827+
/// handle.assert_finished();
828+
/// ```
829+
///
830+
/// [`Subscriber::on_register_dispatch`]: tracing::Subscriber::on_register_dispatch
831+
pub fn on_register_dispatch(mut self) -> Self {
832+
self.expected.push_back(Expect::OnRegisterDispatch);
833+
self
834+
}
835+
805836
/// Filter the traces evaluated by the `MockSubscriber`.
806837
///
807838
/// The filter will be applied to all traces received before
@@ -1001,6 +1032,14 @@ impl<F> Subscriber for Running<F>
10011032
where
10021033
F: Fn(&Metadata<'_>) -> bool + 'static,
10031034
{
1035+
fn on_register_dispatch(&self, _subscriber: &tracing::Dispatch) {
1036+
println!("[{}] on_register_dispatch", self.name);
1037+
let mut expected = self.expected.lock().unwrap();
1038+
if let Some(Expect::OnRegisterDispatch) = expected.front() {
1039+
expected.pop_front();
1040+
}
1041+
}
1042+
10041043
fn enabled(&self, meta: &Metadata<'_>) -> bool {
10051044
println!("[{}] enabled: {:#?}", self.name, meta);
10061045
let enabled = (self.filter)(meta);
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//! Tests for `on_register_dispatch` expectations in MockSubscriber and MockLayer.
2+
3+
use tracing_mock::subscriber;
4+
5+
#[test]
6+
fn subscriber_on_register_dispatch() {
7+
let (subscriber, handle) = subscriber::mock().on_register_dispatch().run_with_handle();
8+
9+
tracing::subscriber::with_default(subscriber, || {
10+
// The subscriber's on_register_dispatch is called when set as default
11+
});
12+
13+
handle.assert_finished();
14+
}
15+
16+
#[cfg(feature = "tracing-subscriber")]
17+
#[test]
18+
fn layer_on_register_dispatch() {
19+
use tracing_mock::layer;
20+
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
21+
22+
let (layer, handle) = layer::mock().on_register_dispatch().run_with_handle();
23+
24+
let _subscriber = tracing_subscriber::registry().with(layer).set_default();
25+
26+
// The layer's on_register_dispatch is called when the subscriber is set as default
27+
drop(_subscriber);
28+
29+
handle.assert_finished();
30+
}
31+
32+
#[test]
33+
fn subscriber_multiple_expectations() {
34+
let (subscriber, handle) = subscriber::mock()
35+
.on_register_dispatch()
36+
.event(tracing_mock::expect::event())
37+
.run_with_handle();
38+
39+
tracing::subscriber::with_default(subscriber, || {
40+
tracing::info!("test event");
41+
});
42+
43+
handle.assert_finished();
44+
}
45+
46+
#[cfg(feature = "tracing-subscriber")]
47+
#[test]
48+
fn layer_multiple_expectations() {
49+
use tracing_mock::layer;
50+
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
51+
52+
let (layer, handle) = layer::mock()
53+
.on_register_dispatch()
54+
.event(tracing_mock::expect::event())
55+
.run_with_handle();
56+
57+
let _subscriber = tracing_subscriber::registry().with(layer).set_default();
58+
59+
tracing::info!("test event");
60+
61+
drop(_subscriber);
62+
handle.assert_finished();
63+
}

tracing-subscriber/src/layer/layered.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ where
9191
L: Layer<S>,
9292
S: Subscriber,
9393
{
94+
fn on_register_dispatch(&self, subscriber: &Dispatch) {
95+
self.inner.on_register_dispatch(subscriber);
96+
self.layer.on_register_dispatch(subscriber);
97+
}
98+
9499
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
95100
self.pick_interest(self.layer.register_callsite(metadata), || {
96101
self.inner.register_callsite(metadata)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![cfg(all(feature = "registry", feature = "std"))]
2+
//! Test that `on_register_dispatch` is called on both layers when a layered
3+
//! subscriber is set as the default.
4+
5+
use tracing_mock::layer;
6+
use tracing_subscriber::layer::SubscriberExt;
7+
8+
#[test]
9+
fn on_register_dispatch_is_called() {
10+
let (inner_layer, inner_handle) = layer::named("inner")
11+
.on_register_dispatch()
12+
.run_with_handle();
13+
14+
let (outer_layer, outer_handle) = layer::named("outer")
15+
.on_register_dispatch()
16+
.run_with_handle();
17+
18+
let subscriber = tracing_subscriber::registry()
19+
.with(inner_layer)
20+
.with(outer_layer);
21+
22+
tracing::subscriber::with_default(subscriber, || {});
23+
24+
// Verify that on_register_dispatch was called on both layers
25+
inner_handle.assert_finished();
26+
outer_handle.assert_finished();
27+
}

0 commit comments

Comments
 (0)