Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensure the None-layer doesn't override the max-level erroneously #2321

Merged
merged 12 commits into from Sep 27, 2022

Conversation

guswynn
Copy link
Contributor

@guswynn guswynn commented Sep 23, 2022

Motivation

Fixes #2265

Solution

Make a special downcast that marks when the layer is a None, which allows us to do the short-circuit we want. The tests I added should be pretty thorough!

Additionally, make sure this downcast works through the reload subscriber

@guswynn guswynn marked this pull request as ready for review September 23, 2022 18:09
@guswynn guswynn requested review from hawkw, davidbarsky and a team as code owners September 23, 2022 18:09
Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall, this looks good --- i had some tiny nitpicks about the comments.

tracing-subscriber/tests/option.rs Outdated Show resolved Hide resolved
tracing-subscriber/tests/option.rs Outdated Show resolved Hide resolved
tracing-subscriber/src/subscribe/mod.rs Outdated Show resolved Hide resolved
tracing-subscriber/src/reload.rs Outdated Show resolved Hide resolved
Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, this basically looks good to me --- i had a few very small nitpicks but they're not particularly important.

tracing-subscriber/src/subscribe/mod.rs Outdated Show resolved Hide resolved
tracing-subscriber/src/reload.rs Outdated Show resolved Hide resolved
tracing-subscriber/src/subscribe/mod.rs Outdated Show resolved Hide resolved
Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left suggestions for potential docs changes, as i'd like to get this one merged soon.

tracing-subscriber/src/reload.rs Outdated Show resolved Hide resolved
tracing-subscriber/src/subscribe/mod.rs Outdated Show resolved Hide resolved
tracing-subscriber/tests/option.rs Show resolved Hide resolved
tracing-subscriber/src/subscribe/mod.rs Outdated Show resolved Hide resolved
tracing-subscriber/tests/option.rs Show resolved Hide resolved
Comment on lines 58 to 108
/// Test that the `None` max level hint only applies if its the only layer
#[test]
fn doesnt_override_none() {
// None means the other layer takes control
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(None))
.with(None::<LevelFilter>);
assert_eq!(subscriber.max_level_hint(), None);

// The `None`-returning layer still wins
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(None))
.with(Some(LevelFilter::ERROR));
assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR));

// Check that we aren't doing anything truly wrong
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(Some(LevelFilter::DEBUG)))
.with(None::<LevelFilter>);
assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));

// Test that per-subscriber filters aren't affected

// One layer is None so it "wins"
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(None))
.with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG));
assert_eq!(subscriber.max_level_hint(), None);

// The max-levels wins
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(Some(LevelFilter::INFO)))
.with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG));
assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));

// Test filter on the other layer
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG))
.with(None::<LevelFilter>);
assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(None).with_filter(LevelFilter::DEBUG))
.with(None::<LevelFilter>);
assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));

// The `OFF` from `None` over overridden.
let subscriber = tracing_subscriber::registry()
.with(BasicLayer(Some(LevelFilter::INFO)))
.with(None::<LevelFilter>);
assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i notice all these tests order the layers so that we have another layer, and then a None. we should probably also have tests that the same cases work when the None layer is on the inside (e.g., Registry, None, BasicLayer instead of Registry, BasicLayer, None)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added tests for this in abd1030 and it turns out we weren't handling that case nicely, so i fixed it in 870ba11. i'm not super happy with the code, but it does at least do the right thing now...

@hawkw hawkw merged commit cf2b06f into tokio-rs:master Sep 27, 2022
@guswynn guswynn deleted the option-part-2 branch September 27, 2022 18:12
hawkw added a commit that referenced this pull request Sep 30, 2022
## Motivation

Currently, when using the `Layer` impl for `Option<S: Layer<...>>`, the
`Layer::max_level_hint` returns  `Some(LevelFilter::OFF)`. This was
intended to allow totally disabling output in the case where a
`Subscriber` is composed entirely of `None` `Layer`s. However, when
other `Layer`s *do* exist but return `None` from their `max_level_hint`
implementations to indicate that they don't care what the max level is,
the presence of a single `None` layer will globally disable everything,
which is not the wanted behavior.

Fixes #2265

## Solution

This branch introduces a special downcast marker that can be used to
detect when a `Layer` in a `Layered` is `None`. This allows the
`pick_level_hint` method to short-circuit when a `Layer` implementation
which is `None` returns `Some(LevelFilter::OFF)` from its
`max_level_hint` if the other half of the `Layered` is not `None`. The
tests I added should be pretty thorough!

Additionally, the downcast marker is special-cased in the `reload`
`Layer`. Normally, this `Layer` doesn't support downcasting, but it can
in the case of the special marker value.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Sep 30, 2022
## Motivation

Currently, when using the `Layer` impl for `Option<S: Layer<...>>`, the
`Layer::max_level_hint` returns  `Some(LevelFilter::OFF)`. This was
intended to allow totally disabling output in the case where a
`Subscriber` is composed entirely of `None` `Layer`s. However, when
other `Layer`s *do* exist but return `None` from their `max_level_hint`
implementations to indicate that they don't care what the max level is,
the presence of a single `None` layer will globally disable everything,
which is not the wanted behavior.

Fixes #2265

## Solution

This branch introduces a special downcast marker that can be used to
detect when a `Layer` in a `Layered` is `None`. This allows the
`pick_level_hint` method to short-circuit when a `Layer` implementation
which is `None` returns `Some(LevelFilter::OFF)` from its
`max_level_hint` if the other half of the `Layered` is not `None`. The
tests I added should be pretty thorough!

Additionally, the downcast marker is special-cased in the `reload`
`Layer`. Normally, this `Layer` doesn't support downcasting, but it can
in the case of the special marker value.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Oct 6, 2022
# 0.3.16 (October 6, 2022)

This release of `tracing-subscriber` fixes a regression introduced in
[v0.3.15][subscriber-0.3.15] where `Option::None`'s `Layer`
implementation would set the max level hint to `OFF`. In addition, it
adds several new APIs, including the `Filter::event_enabled` method for
filtering events based on fields values, and the ability to log internal
errors that occur when writing a log line.

This release also replaces the dependency on the unmaintained
[`ansi-term`] crate with the [`nu-ansi-term`] crate, resolving an
*informational* security advisory ([RUSTSEC-2021-0139] for
[`ansi-term`]'s maintainance status. This increases the minimum
supported Rust version (MSRV) to Rust 1.50+, although the crate should
still compile for the previous MSRV of Rust 1.49+ when the `ansi`
feature is not enabled.

### Fixed

- **layer**: `Option::None`'s `Layer` impl always setting the
  `max_level_hint` to `LevelFilter::OFF` (#2321)
- Compilation with `-Z minimal versions` (#2246)
- **env-filter**: Clarify that disabled level warnings are emitted by
  `tracing-subscriber` (#2285)

### Added

- **fmt**: Log internal errors to `stderr` if writing a log line fails
  (#2102)
- **fmt**: `FmtLayer::log_internal_errors` and
  `FmtSubscriber::log_internal_errors` methods for configuring whether
  internal writer errors are printed to `stderr` (#2102)
- **fmt**: `#[must_use]` attributes on builders to warn if a
  `Subscriber` is configured but not set as the default subscriber
  (#2239)
- **filter**: `Filter::event_enabled` method for filtering an event
  based on its fields (#2245, #2251)
- **filter**: `Targets::default_level` accessor (#2242)

### Changed

- **ansi**: Replaced dependency on unmaintained `ansi-term` crate with
  `nu-ansi-term` ((#2287, fixes informational advisory
  [RUSTSEC-2021-0139])
- `tracing-core`: updated to [0.1.30][core-0.1.30]
- Minimum Supported Rust Version (MSRV) increased to Rust 1.50+ (when
  the `ansi`) feature flag is enabled (#2287)

### Documented

- **fmt**: Correct inaccuracies in `fmt::init` documentation (#2224)
- **filter**: Fix incorrect doc link in `filter::Not` combinator
  (#2249)

Thanks to new contributors @cgbur, @DesmondWillowbrook, @RalfJung, and
@poliorcetics, as well as returning contributors @CAD97, @connec,
@jswrenn, @guswynn, and @bryangarza, for contributing to this release!

[nu-ansi-term]: https://github.com/nushell/nu-ansi-term
[ansi_term]: https://github.com/ogham/rust-ansi-term
[RUSTSEC-2021-0139]: https://rustsec.org/advisories/RUSTSEC-2021-0139.html
[core-0.1.30]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.30
[subscriber-0.3.15]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.15
hawkw added a commit that referenced this pull request Oct 6, 2022
# 0.3.16 (October 6, 2022)

This release of `tracing-subscriber` fixes a regression introduced in
[v0.3.15][subscriber-0.3.15] where `Option::None`'s `Layer`
implementation would set the max level hint to `OFF`. In addition, it
adds several new APIs, including the `Filter::event_enabled` method for
filtering events based on fields values, and the ability to log internal
errors that occur when writing a log line.

This release also replaces the dependency on the unmaintained
[`ansi-term`] crate with the [`nu-ansi-term`] crate, resolving an
*informational* security advisory ([RUSTSEC-2021-0139] for
[`ansi-term`]'s maintainance status. This increases the minimum
supported Rust version (MSRV) to Rust 1.50+, although the crate should
still compile for the previous MSRV of Rust 1.49+ when the `ansi`
feature is not enabled.

### Fixed

- **layer**: `Option::None`'s `Layer` impl always setting the
  `max_level_hint` to `LevelFilter::OFF` (#2321)
- Compilation with `-Z minimal versions` (#2246)
- **env-filter**: Clarify that disabled level warnings are emitted by
  `tracing-subscriber` (#2285)

### Added

- **fmt**: Log internal errors to `stderr` if writing a log line fails
  (#2102)
- **fmt**: `FmtLayer::log_internal_errors` and
  `FmtSubscriber::log_internal_errors` methods for configuring whether
  internal writer errors are printed to `stderr` (#2102)
- **fmt**: `#[must_use]` attributes on builders to warn if a
  `Subscriber` is configured but not set as the default subscriber
  (#2239)
- **filter**: `Filter::event_enabled` method for filtering an event
  based on its fields (#2245, #2251)
- **filter**: `Targets::default_level` accessor (#2242)

### Changed

- **ansi**: Replaced dependency on unmaintained `ansi-term` crate with
  `nu-ansi-term` ((#2287, fixes informational advisory
  [RUSTSEC-2021-0139])
- `tracing-core`: updated to [0.1.30][core-0.1.30]
- Minimum Supported Rust Version (MSRV) increased to Rust 1.50+ (when
  the `ansi`) feature flag is enabled (#2287)

### Documented

- **fmt**: Correct inaccuracies in `fmt::init` documentation (#2224)
- **filter**: Fix incorrect doc link in `filter::Not` combinator
  (#2249)

Thanks to new contributors @cgbur, @DesmondWillowbrook, @RalfJung, and
@poliorcetics, as well as returning contributors @CAD97, @connec,
@jswrenn, @guswynn, and @bryangarza, for contributing to this release!

[nu-ansi-term]: https://github.com/nushell/nu-ansi-term
[ansi_term]: https://github.com/ogham/rust-ansi-term
[RUSTSEC-2021-0139]: https://rustsec.org/advisories/RUSTSEC-2021-0139.html
[core-0.1.30]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.30
[subscriber-0.3.15]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.15
hawkw added a commit that referenced this pull request Oct 6, 2022
# 0.3.16 (October 6, 2022)

This release of `tracing-subscriber` fixes a regression introduced in
[v0.3.15][subscriber-0.3.15] where `Option::None`'s `Layer`
implementation would set the max level hint to `OFF`. In addition, it
adds several new APIs, including the `Filter::event_enabled` method for
filtering events based on fields values, and the ability to log internal
errors that occur when writing a log line.

This release also replaces the dependency on the unmaintained
[`ansi-term`] crate with the [`nu-ansi-term`] crate, resolving an
*informational* security advisory ([RUSTSEC-2021-0139] for
[`ansi-term`]'s maintainance status. This increases the minimum
supported Rust version (MSRV) to Rust 1.50+, although the crate should
still compile for the previous MSRV of Rust 1.49+ when the `ansi`
feature is not enabled.

### Fixed

- **layer**: `Option::None`'s `Layer` impl always setting the
  `max_level_hint` to `LevelFilter::OFF` (#2321)
- Compilation with `-Z minimal versions` (#2246)
- **env-filter**: Clarify that disabled level warnings are emitted by
  `tracing-subscriber` (#2285)

### Added

- **fmt**: Log internal errors to `stderr` if writing a log line fails
  (#2102)
- **fmt**: `FmtLayer::log_internal_errors` and
  `FmtSubscriber::log_internal_errors` methods for configuring whether
  internal writer errors are printed to `stderr` (#2102)
- **fmt**: `#[must_use]` attributes on builders to warn if a
  `Subscriber` is configured but not set as the default subscriber
  (#2239)
- **filter**: `Filter::event_enabled` method for filtering an event
  based on its fields (#2245, #2251)
- **filter**: `Targets::default_level` accessor (#2242)

### Changed

- **ansi**: Replaced dependency on unmaintained `ansi-term` crate with
  `nu-ansi-term` ((#2287, fixes informational advisory
  [RUSTSEC-2021-0139])
- `tracing-core`: updated to [0.1.30][core-0.1.30]
- Minimum Supported Rust Version (MSRV) increased to Rust 1.50+ (when
  the `ansi`) feature flag is enabled (#2287)

### Documented

- **fmt**: Correct inaccuracies in `fmt::init` documentation (#2224)
- **filter**: Fix incorrect doc link in `filter::Not` combinator
  (#2249)

Thanks to new contributors @cgbur, @DesmondWillowbrook, @RalfJung, and
@poliorcetics, as well as returning contributors @CAD97, @connec,
@jswrenn, @guswynn, and @bryangarza, for contributing to this release!

[nu-ansi-term]: https://github.com/nushell/nu-ansi-term
[ansi_term]: https://github.com/ogham/rust-ansi-term
[RUSTSEC-2021-0139]: https://rustsec.org/advisories/RUSTSEC-2021-0139.html
[core-0.1.30]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.30
[subscriber-0.3.15]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None-layers resets loglevel
2 participants