From d864366978d73982995073435f0ced4b9e1e622f Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Thu, 30 Jun 2022 17:15:07 -0700 Subject: [PATCH] subscriber: fix `max_level_hint` for empty `Option`/`Vec` `Layer` impls (#2195) ## Motivation These are incorrect: currently, when you have a `None` layer, the `None` hint it returns causes the default `TRACE` to win, which is inaccurate. Similarly, `Vec` should default to `OFF` if it has no `Layer`s in it ## Solution Change the default hints to `Some(OFF)` Co-authored-by: Eliza Weisman --- tracing-subscriber/src/layer/mod.rs | 9 +++- tracing-subscriber/tests/layer_filters/vec.rs | 7 ++++ tracing-subscriber/tests/option.rs | 41 +++++++++++++++++++ tracing-subscriber/tests/vec.rs | 19 +++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 tracing-subscriber/tests/option.rs create mode 100644 tracing-subscriber/tests/vec.rs diff --git a/tracing-subscriber/src/layer/mod.rs b/tracing-subscriber/src/layer/mod.rs index 808d890f3c..24b8533234 100644 --- a/tracing-subscriber/src/layer/mod.rs +++ b/tracing-subscriber/src/layer/mod.rs @@ -1490,7 +1490,11 @@ where fn max_level_hint(&self) -> Option { match self { Some(ref inner) => inner.max_level_hint(), - None => None, + None => { + // There is no inner layer, so this layer will + // never enable anything. + Some(LevelFilter::OFF) + } } } @@ -1701,7 +1705,8 @@ feature! { } fn max_level_hint(&self) -> Option { - let mut max_level = LevelFilter::ERROR; + // Default to `OFF` if there are no inner layers. + let mut max_level = LevelFilter::OFF; for l in self { // NOTE(eliza): this is slightly subtle: if *any* layer // returns `None`, we have to return `None`, assuming there is diff --git a/tracing-subscriber/tests/layer_filters/vec.rs b/tracing-subscriber/tests/layer_filters/vec.rs index 77675a5f94..87244e4ab5 100644 --- a/tracing-subscriber/tests/layer_filters/vec.rs +++ b/tracing-subscriber/tests/layer_filters/vec.rs @@ -111,3 +111,10 @@ fn all_filtered_max_level_hint() { assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG)); } + +#[test] +fn empty_vec() { + // Just a None means everything is off + let subscriber = tracing_subscriber::registry().with(Vec::::new()); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); +} diff --git a/tracing-subscriber/tests/option.rs b/tracing-subscriber/tests/option.rs new file mode 100644 index 0000000000..738cc0a6c5 --- /dev/null +++ b/tracing-subscriber/tests/option.rs @@ -0,0 +1,41 @@ +#![cfg(feature = "registry")] +use tracing::level_filters::LevelFilter; +use tracing::Subscriber; +use tracing_subscriber::prelude::*; + +// This test is just used to compare to the tests below +#[test] +fn just_layer() { + let subscriber = tracing_subscriber::registry().with(LevelFilter::INFO); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO)); +} + +#[test] +fn subscriber_and_option_some_layer() { + let subscriber = tracing_subscriber::registry() + .with(LevelFilter::INFO) + .with(Some(LevelFilter::DEBUG)); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG)); +} + +#[test] +fn subscriber_and_option_none_layer() { + // None means the other layer takes control + let subscriber = tracing_subscriber::registry() + .with(LevelFilter::ERROR) + .with(None::); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR)); +} + +#[test] +fn just_option_some_layer() { + // Just a None means everything is off + let subscriber = tracing_subscriber::registry().with(None::); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); +} + +#[test] +fn just_option_none_layer() { + let subscriber = tracing_subscriber::registry().with(Some(LevelFilter::ERROR)); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR)); +} diff --git a/tracing-subscriber/tests/vec.rs b/tracing-subscriber/tests/vec.rs new file mode 100644 index 0000000000..92abf0bff9 --- /dev/null +++ b/tracing-subscriber/tests/vec.rs @@ -0,0 +1,19 @@ +#![cfg(feature = "registry")] +use tracing::level_filters::LevelFilter; +use tracing::Subscriber; +use tracing_subscriber::prelude::*; + +#[test] +fn just_empty_vec() { + // Just a None means everything is off + let subscriber = tracing_subscriber::registry().with(Vec::::new()); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF)); +} + +#[test] +fn layer_and_empty_vec() { + let subscriber = tracing_subscriber::registry() + .with(LevelFilter::INFO) + .with(Vec::::new()); + assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO)); +}