From 77aedec83fb4401b644e3627b0d3338d3147db0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Antonsson?= Date: Fri, 21 Nov 2025 15:57:47 +0100 Subject: [PATCH 1/3] fix(subscriber): make Layered propagate on_register_dispatch --- tracing-mock/src/expect.rs | 5 ++ tracing-mock/src/layer.rs | 43 +++++++++++++ tracing-mock/src/subscriber.rs | 39 ++++++++++++ tracing-mock/tests/on_register_dispatch.rs | 63 +++++++++++++++++++ tracing-subscriber/src/layer/layered.rs | 5 ++ .../tests/on_register_dispatch_is_called.rs | 27 ++++++++ 6 files changed, 182 insertions(+) create mode 100644 tracing-mock/tests/on_register_dispatch.rs create mode 100644 tracing-subscriber/tests/on_register_dispatch_is_called.rs diff --git a/tracing-mock/src/expect.rs b/tracing-mock/src/expect.rs index 39e95f73c4..4fc173fa0f 100644 --- a/tracing-mock/src/expect.rs +++ b/tracing-mock/src/expect.rs @@ -42,6 +42,7 @@ pub(crate) enum Expect { DropSpan(ExpectedSpan), Visit(ExpectedSpan, ExpectedFields), NewSpan(NewSpan), + OnRegisterDispatch, Nothing, } @@ -324,6 +325,10 @@ impl Expect { "\n[{}] expected {}\n[{}] but instead {}", name, e, name, what ), + Expect::OnRegisterDispatch => panic!( + "\n[{}] expected on_register_dispatch to be called\n[{}] but instead {}", + name, name, what + ), Expect::Nothing => panic!( "\n[{}] expected nothing else to happen\n[{}] but {} instead", name, name, what, diff --git a/tracing-mock/src/layer.rs b/tracing-mock/src/layer.rs index 011c161195..94c571ad42 100644 --- a/tracing-mock/src/layer.rs +++ b/tracing-mock/src/layer.rs @@ -642,6 +642,41 @@ impl MockLayerBuilder { self } + /// Adds an expectation that [`Layer::on_register_dispatch`] will + /// be called next. + /// + /// **Note**: This expectation is usually fulfilled automatically when + /// a layer (wrapped in a subscriber) is set as the default via + /// [`tracing::subscriber::with_default`] or + /// [`tracing::subscriber::set_global_default`], so explicitly expecting + /// this is not usually necessary. However, it may be useful when testing + /// custom layer implementations that manually call `on_register_dispatch`. + /// + /// # Examples + /// + /// ``` + /// use tracing_mock::{expect, layer}; + /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; + /// + /// let (layer, handle) = layer::mock() + /// .on_register_dispatch() + /// .run_with_handle(); + /// + /// let _subscriber = tracing_subscriber::registry() + /// .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true))) + /// .set_default(); + /// + /// // The layer's on_register_dispatch was called when the subscriber was set as default + /// + /// handle.assert_finished(); + /// ``` + /// + /// [`Layer::on_register_dispatch`]: tracing_subscriber::layer::Layer::on_register_dispatch + pub fn on_register_dispatch(mut self) -> Self { + self.expected.push_back(Expect::OnRegisterDispatch); + self + } + /// Expects that no further traces are received. /// /// The call to `only` should appear immediately before the final @@ -835,6 +870,14 @@ impl Layer for MockLayer where C: Subscriber + for<'a> LookupSpan<'a>, { + fn on_register_dispatch(&self, _subscriber: &tracing::Dispatch) { + println!("[{}] on_register_dispatch", self.name); + let mut expected = self.expected.lock().unwrap(); + if let Some(Expect::OnRegisterDispatch) = expected.front() { + expected.pop_front(); + } + } + fn register_callsite( &self, metadata: &'static tracing::Metadata<'static>, diff --git a/tracing-mock/src/subscriber.rs b/tracing-mock/src/subscriber.rs index 3e2f57b33b..e64c4ae36c 100644 --- a/tracing-mock/src/subscriber.rs +++ b/tracing-mock/src/subscriber.rs @@ -802,6 +802,37 @@ where self } + /// Adds an expectation that [`Subscriber::on_register_dispatch`] will + /// be called next. + /// + /// **Note**: This expectation is usually fulfilled automatically when + /// a subscriber is set as the default via [`tracing::subscriber::with_default`] + /// or [`tracing::subscriber::set_global_default`], so explicitly expecting + /// this is not usually necessary. However, it may be useful when testing + /// custom subscriber implementations that manually call `on_register_dispatch`. + /// + /// # Examples + /// + /// ``` + /// use tracing_mock::{expect, subscriber}; + /// + /// let (subscriber, handle) = subscriber::mock() + /// .on_register_dispatch() + /// .run_with_handle(); + /// + /// tracing::subscriber::with_default(subscriber, || { + /// // The subscriber's on_register_dispatch was called when it was set as default + /// }); + /// + /// handle.assert_finished(); + /// ``` + /// + /// [`Subscriber::on_register_dispatch`]: tracing::Subscriber::on_register_dispatch + pub fn on_register_dispatch(mut self) -> Self { + self.expected.push_back(Expect::OnRegisterDispatch); + self + } + /// Filter the traces evaluated by the `MockSubscriber`. /// /// The filter will be applied to all traces received before @@ -1001,6 +1032,14 @@ impl Subscriber for Running where F: Fn(&Metadata<'_>) -> bool + 'static, { + fn on_register_dispatch(&self, _subscriber: &tracing::Dispatch) { + println!("[{}] on_register_dispatch", self.name); + let mut expected = self.expected.lock().unwrap(); + if let Some(Expect::OnRegisterDispatch) = expected.front() { + expected.pop_front(); + } + } + fn enabled(&self, meta: &Metadata<'_>) -> bool { println!("[{}] enabled: {:#?}", self.name, meta); let enabled = (self.filter)(meta); diff --git a/tracing-mock/tests/on_register_dispatch.rs b/tracing-mock/tests/on_register_dispatch.rs new file mode 100644 index 0000000000..56624b9675 --- /dev/null +++ b/tracing-mock/tests/on_register_dispatch.rs @@ -0,0 +1,63 @@ +//! Tests for `on_register_dispatch` expectations in MockSubscriber and MockLayer. + +use tracing_mock::subscriber; + +#[test] +fn subscriber_on_register_dispatch() { + let (subscriber, handle) = subscriber::mock().on_register_dispatch().run_with_handle(); + + tracing::subscriber::with_default(subscriber, || { + // The subscriber's on_register_dispatch is called when set as default + }); + + handle.assert_finished(); +} + +#[cfg(feature = "tracing-subscriber")] +#[test] +fn layer_on_register_dispatch() { + use tracing_mock::layer; + use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + let (layer, handle) = layer::mock().on_register_dispatch().run_with_handle(); + + let _subscriber = tracing_subscriber::registry().with(layer).set_default(); + + // The layer's on_register_dispatch is called when the subscriber is set as default + drop(_subscriber); + + handle.assert_finished(); +} + +#[test] +fn subscriber_multiple_expectations() { + let (subscriber, handle) = subscriber::mock() + .on_register_dispatch() + .event(tracing_mock::expect::event()) + .run_with_handle(); + + tracing::subscriber::with_default(subscriber, || { + tracing::info!("test event"); + }); + + handle.assert_finished(); +} + +#[cfg(feature = "tracing-subscriber")] +#[test] +fn layer_multiple_expectations() { + use tracing_mock::layer; + use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; + + let (layer, handle) = layer::mock() + .on_register_dispatch() + .event(tracing_mock::expect::event()) + .run_with_handle(); + + let _subscriber = tracing_subscriber::registry().with(layer).set_default(); + + tracing::info!("test event"); + + drop(_subscriber); + handle.assert_finished(); +} diff --git a/tracing-subscriber/src/layer/layered.rs b/tracing-subscriber/src/layer/layered.rs index f606eba722..9306390794 100644 --- a/tracing-subscriber/src/layer/layered.rs +++ b/tracing-subscriber/src/layer/layered.rs @@ -91,6 +91,11 @@ where L: Layer, S: Subscriber, { + fn on_register_dispatch(&self, subscriber: &Dispatch) { + self.inner.on_register_dispatch(subscriber); + self.layer.on_register_dispatch(subscriber); + } + fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { self.pick_interest(self.layer.register_callsite(metadata), || { self.inner.register_callsite(metadata) diff --git a/tracing-subscriber/tests/on_register_dispatch_is_called.rs b/tracing-subscriber/tests/on_register_dispatch_is_called.rs new file mode 100644 index 0000000000..e331a464fa --- /dev/null +++ b/tracing-subscriber/tests/on_register_dispatch_is_called.rs @@ -0,0 +1,27 @@ +#![cfg(all(feature = "registry", feature = "std"))] +//! Test that `on_register_dispatch` is called on both layers when a layered +//! subscriber is set as the default. + +use tracing_mock::layer; +use tracing_subscriber::layer::SubscriberExt; + +#[test] +fn on_register_dispatch_is_called() { + let (inner_layer, inner_handle) = layer::named("inner") + .on_register_dispatch() + .run_with_handle(); + + let (outer_layer, outer_handle) = layer::named("outer") + .on_register_dispatch() + .run_with_handle(); + + let subscriber = tracing_subscriber::registry() + .with(inner_layer) + .with(outer_layer); + + tracing::subscriber::with_default(subscriber, || {}); + + // Verify that on_register_dispatch was called on both layers + inner_handle.assert_finished(); + outer_handle.assert_finished(); +} From 58e81d5cf44895e9b266365249cc94e53e0ebf20 Mon Sep 17 00:00:00 2001 From: Hayden Stainsby Date: Mon, 24 Nov 2025 12:41:43 +0100 Subject: [PATCH 2/3] Update tracing-mock/tests/on_register_dispatch.rs --- tracing-mock/tests/on_register_dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-mock/tests/on_register_dispatch.rs b/tracing-mock/tests/on_register_dispatch.rs index 56624b9675..564f97fdec 100644 --- a/tracing-mock/tests/on_register_dispatch.rs +++ b/tracing-mock/tests/on_register_dispatch.rs @@ -17,7 +17,7 @@ fn subscriber_on_register_dispatch() { #[test] fn layer_on_register_dispatch() { use tracing_mock::layer; - use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; + use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; let (layer, handle) = layer::mock().on_register_dispatch().run_with_handle(); From 2d701ed21c5a762568d0d0075b6a279b1b8159f6 Mon Sep 17 00:00:00 2001 From: Hayden Stainsby Date: Mon, 24 Nov 2025 12:41:49 +0100 Subject: [PATCH 3/3] Update tracing-mock/tests/on_register_dispatch.rs --- tracing-mock/tests/on_register_dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-mock/tests/on_register_dispatch.rs b/tracing-mock/tests/on_register_dispatch.rs index 564f97fdec..02b1c15cce 100644 --- a/tracing-mock/tests/on_register_dispatch.rs +++ b/tracing-mock/tests/on_register_dispatch.rs @@ -47,7 +47,7 @@ fn subscriber_multiple_expectations() { #[test] fn layer_multiple_expectations() { use tracing_mock::layer; - use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; + use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; let (layer, handle) = layer::mock() .on_register_dispatch()