-
Notifications
You must be signed in to change notification settings - Fork 734
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
Implement subscribe::Filter for Option<Filter> #2407
Conversation
Pass all the Filter methods through to the underlying Box/Arc Filter rather than relying on default implementations.
Where None means "no filtering".
Make sure None lets everything through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
three tiny nits that can you can apply, but this change looks good to me overall.
//! trait may also be implemented for user-defined types. [`Option<Filter>`] | ||
//! also implements [`Filter`], to allow for a (surprise!) optional filter - | ||
//! [`None`](Option::None) filters nothing (that is, allows everything through). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! trait may also be implemented for user-defined types. [`Option<Filter>`] | |
//! also implements [`Filter`], to allow for a (surprise!) optional filter - | |
//! [`None`](Option::None) filters nothing (that is, allows everything through). | |
//! trait may also be implemented for user-defined types. [`Option<Filter>`] | |
//! also implements [`Filter`], which allows for an optional filter where | |
//! [`None`](Option::None) filters out _nothing_ (that is, allows everything through). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aww, i like the (surprise!)
:(
#[test] | ||
fn option_some() { | ||
let (subscribe, handle) = subscriber::mock().only().run_with_handle(); | ||
let subscribe = Box::new(subscribe.with_filter(Some(filter()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: i'm not sure if Box
is necessary, but if it is, then that's fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied boxed.rs
as a starting point. I can unbox.
use super::*; | ||
use tracing_subscriber::{filter, prelude::*, Subscribe}; | ||
|
||
fn filter<S>() -> filter::DynFilterFn<S> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small nit, since it took me a second to understand what was happening here:
fn filter<S>() -> filter::DynFilterFn<S> { | |
fn filter_out_everything<S>() -> filter::DynFilterFn<S> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto copied from boxed.rs
.
Updated with fixes for review comments. |
There was a problem hiding this 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 and it definitely makes sense to add, thanks!
Because the interactions between per-subscriber filters can be somewhat complex, especially when the max-level hints are involved, it would be nice to see tests that test Option
filters in combination with other subscribers with their own per-layer filters. The current tests are kind of only testing the happy path for the per-layer filtering system, where there aren't multiple sets of filters for separate subscribers, and it would be nice to test the more difficult cases, as well.
Thanks!
//! trait may also be implemented for user-defined types. [`Option<Filter>`] | ||
//! also implements [`Filter`], which allows for an optional filter where | ||
//! [`None`](Option::None) filters out _nothing_ (that is, allows everything | ||
//! through). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it could maybe be nice to have an example somewhere showing how and why we might want to use the Filter
impl for Option
?
#[test] | ||
fn option_some() { | ||
let (subscribe, handle) = subscriber::mock().only().run_with_handle(); | ||
let subscribe = subscribe.with_filter(Some(filter_out_everything())); | ||
|
||
let _guard = tracing_subscriber::registry().with(subscribe).set_default(); | ||
|
||
for i in 0..2 { | ||
tracing::info!(i); | ||
} | ||
|
||
handle.assert_finished(); | ||
} | ||
|
||
#[test] | ||
fn option_none() { | ||
let (subscribe, handle) = subscriber::mock() | ||
.event(expect::event()) | ||
.event(expect::event()) | ||
.only() | ||
.run_with_handle(); | ||
let subscribe = Box::new(subscribe.with_filter(None::<filter::DynFilterFn<_>>)); | ||
|
||
let _guard = tracing_subscriber::registry().with(subscribe).set_default(); | ||
|
||
for i in 0..2 { | ||
tracing::info!(i); | ||
} | ||
|
||
handle.assert_finished(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's also add some tests where a registry includes a subscriber that has an Option
filter, as well as a subscriber with a non-optional filter, to ensure that the Option
impl plays nicely with other per-layer filters?
Updated with @hawkw's suggestions. |
let (subscribe, handle) = subscriber::mock() | ||
.event(expect::event()) | ||
.only() | ||
.run_with_handle(); | ||
let subscribe = subscribe | ||
.with_filter(filter::dynamic_filter_fn(|meta, _ctx| { | ||
meta.target() == "interesting" | ||
})) | ||
.with_filter(None::<filter::DynFilterFn<_>>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is worth having, but the scenario i really wanted to test was not a single subscriber with two different filters, but two different subscribers with separate filters, where one subscriber's filter was a None
. in particular, we want to assert that the None
filter does not inadvertantly enable anything that the other subscriber's filter would enable.
we also really want to test that the correct max level hint is used, since that's something we've had bugs with in the past.
* Added tests for max level filtering and interest caching with multiple subscribers. * Changed the interest level for a `None` filter from `sometimes` to `always` so other filters can be cached more effectively.
Add tests and tweak `None` filter interest level
@hawkw @davidbarsky OK, I think this now, thanks to @ryanthomasjohnson, has the additional tests you wanted. I've merged in current master and all the tests pass locally. |
Cool, taking a look! |
Ping? Is there anything outstanding on my side for this? |
No, don't think so. the test that you wrote seems to exercise what Eliza wanted it to exercise. I'll rebase, but I'm perfectly fine with the changes. |
Any chance this can merge? |
//! function pointer. In addition, when more control is required, the [`Filter`] | ||
//! trait may also be implemented for user-defined types. | ||
//! | ||
//! [`Option<Filter>`] also implements [`Filter`], which allows for an optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, not a blocker: it could be nice to link to the implementation of Filter
for Option<Filter>
in the docs here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the rustdoc syntax to link to a trait implementation?
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
# 0.3.18 (November 13, 2023) This release of `tracing-subscriber` adds support for the [`NO_COLOR`] environment variable (an informal standard to disable emitting ANSI color escape codes) in `fmt::Layer`, reintroduces support for the [`chrono`] crate, and increases the minimum supported Rust version (MSRV) to Rust 1.63.0. It also introduces several minor API improvements. ### Added - **chrono**: Add [`chrono`] implementations of `FormatTime` ([#2690]) - **subscriber**: Add support for the [`NO_COLOR`] environment variable in `fmt::Layer` ([#2647]) - **fmt**: make `format::Writer::new()` public ([#2680]) - **filter**: Implement `layer::Filter` for `Option<Filter>` ([#2407]) ### Changed - **log**: bump version of `tracing-log` to 0.2 ([#2772]) - Increased minimum supported Rust version (MSRV) to 1.63.0+. [`chrono`]: https://github.com/chronotope/chrono [`NO_COLOR`]: https://no-color.org/ [#2690]: #2690 [#2647]: #2647 [#2680]: #2680 [#2407]: #2407 [#2772]: #2772 Thanks to @shayne-fletcher, @dmlary, @kaifastromai, and @jsgf for contributing!
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
Summary: Replaces the various `tracing` forks for [tokio-rs/tracing#2407] with crates-io releases containing those changes. [tokio-rs/tracing#2407]: tokio-rs/tracing#2407 Reviewed By: capickett, davidbarsky Differential Revision: D51266382 fbshipit-source-id: 5ad0b7b9477e5fa450e52c639357fe485e0e89ff
# 0.3.18 (November 13, 2023) This release of `tracing-subscriber` adds support for the [`NO_COLOR`] environment variable (an informal standard to disable emitting ANSI color escape codes) in `fmt::Layer`, reintroduces support for the [`chrono`] crate, and increases the minimum supported Rust version (MSRV) to Rust 1.63.0. It also introduces several minor API improvements. ### Added - **chrono**: Add [`chrono`] implementations of `FormatTime` ([tokio-rs#2690]) - **subscriber**: Add support for the [`NO_COLOR`] environment variable in `fmt::Layer` ([tokio-rs#2647]) - **fmt**: make `format::Writer::new()` public ([tokio-rs#2680]) - **filter**: Implement `layer::Filter` for `Option<Filter>` ([tokio-rs#2407]) ### Changed - **log**: bump version of `tracing-log` to 0.2 ([tokio-rs#2772]) - Increased minimum supported Rust version (MSRV) to 1.63.0+. [`chrono`]: https://github.com/chronotope/chrono [`NO_COLOR`]: https://no-color.org/ [tokio-rs#2690]: tokio-rs#2690 [tokio-rs#2647]: tokio-rs#2647 [tokio-rs#2680]: tokio-rs#2680 [tokio-rs#2407]: tokio-rs#2407 [tokio-rs#2772]: tokio-rs#2772 Thanks to @shayne-fletcher, @dmlary, @kaifastromai, and @jsgf for contributing!
It's currently awkward to have an optional per-layer filter. Implement `Filter<L>` for `Option<F> where F: Filter<L>`, following the example of `Layer`. A `None` filter passes everything through. Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the `filter_impl_body` macro to include them. This also adds a couple of tests and updates the docs. --------- Co-authored-by: David Barsky <[email protected]> Co-authored-by: Ryan Johnson <[email protected]> Co-authored-by: Eliza Weisman <[email protected]>
# 0.3.18 (November 13, 2023) This release of `tracing-subscriber` adds support for the [`NO_COLOR`] environment variable (an informal standard to disable emitting ANSI color escape codes) in `fmt::Layer`, reintroduces support for the [`chrono`] crate, and increases the minimum supported Rust version (MSRV) to Rust 1.63.0. It also introduces several minor API improvements. ### Added - **chrono**: Add [`chrono`] implementations of `FormatTime` ([tokio-rs#2690]) - **subscriber**: Add support for the [`NO_COLOR`] environment variable in `fmt::Layer` ([tokio-rs#2647]) - **fmt**: make `format::Writer::new()` public ([tokio-rs#2680]) - **filter**: Implement `layer::Filter` for `Option<Filter>` ([tokio-rs#2407]) ### Changed - **log**: bump version of `tracing-log` to 0.2 ([tokio-rs#2772]) - Increased minimum supported Rust version (MSRV) to 1.63.0+. [`chrono`]: https://github.com/chronotope/chrono [`NO_COLOR`]: https://no-color.org/ [tokio-rs#2690]: tokio-rs#2690 [tokio-rs#2647]: tokio-rs#2647 [tokio-rs#2680]: tokio-rs#2680 [tokio-rs#2407]: tokio-rs#2407 [tokio-rs#2772]: tokio-rs#2772 Thanks to @shayne-fletcher, @dmlary, @kaifastromai, and @jsgf for contributing!
Motivation
It's currently awkward to have an optional per-subscriber filter.
Solution
Implement
Filter<S>
forOption<F> where F: Filter<S>
, following the example ofSubscribe
. ANone
filter passes everything through.Also, it looks like Filter for Arc/Box doesn't pass through all the methods, so extend the
filter_impl_body
macro to include them.This also adds a couple of tests and updates the docs.