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

Implement subscribe::Filter for Option<Filter> #2407

Merged
merged 16 commits into from Sep 28, 2023

Conversation

jsgf
Copy link
Contributor

@jsgf jsgf commented Dec 8, 2022

Motivation

It's currently awkward to have an optional per-subscriber filter.

Solution

Implement Filter<S> for Option<F> where F: Filter<S>, following the example of Subscribe. 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.

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.
Copy link
Member

@davidbarsky davidbarsky left a 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.

Comment on lines 471 to 473
//! 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).
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
//! 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).

Copy link
Member

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())));
Copy link
Member

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.

Copy link
Contributor Author

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> {
Copy link
Member

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:

Suggested change
fn filter<S>() -> filter::DynFilterFn<S> {
fn filter_out_everything<S>() -> filter::DynFilterFn<S> {

Copy link
Contributor Author

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.

@jsgf
Copy link
Contributor Author

jsgf commented Dec 13, 2022

Updated with fixes for review comments.

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 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!

Comment on lines 471 to 474
//! 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).
Copy link
Member

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?

Comment on lines 10 to 39
#[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();
Copy link
Member

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?

@jsgf
Copy link
Contributor Author

jsgf commented Dec 14, 2022

Updated with @hawkw's suggestions.

Comment on lines +44 to +52
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<_>>);
Copy link
Member

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.

ryanthomasjohnson and others added 3 commits March 27, 2023 10:12
* 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
@jsgf
Copy link
Contributor Author

jsgf commented May 1, 2023

@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.

@jsgf jsgf requested a review from hawkw May 1, 2023 06:49
@hawkw
Copy link
Member

hawkw commented May 1, 2023

@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!

@jsgf
Copy link
Contributor Author

jsgf commented May 31, 2023

Ping? Is there anything outstanding on my side for this?

@davidbarsky
Copy link
Member

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.

@zertosh
Copy link

zertosh commented Jul 26, 2023

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
Copy link
Member

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?

Copy link
Contributor Author

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?

@davidbarsky davidbarsky enabled auto-merge (squash) September 28, 2023 23:47
@davidbarsky davidbarsky merged commit 62d57a6 into tokio-rs:master Sep 28, 2023
55 checks passed
davidbarsky added a commit that referenced this pull request Sep 29, 2023
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 <me@davidbarsky.com>
Co-authored-by: Ryan Johnson <ryantj@fb.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
davidbarsky added a commit that referenced this pull request Sep 29, 2023
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 <me@davidbarsky.com>
Co-authored-by: Ryan Johnson <ryantj@fb.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
davidbarsky added a commit that referenced this pull request Sep 29, 2023
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 <me@davidbarsky.com>
Co-authored-by: Ryan Johnson <ryantj@fb.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
davidbarsky added a commit that referenced this pull request Sep 29, 2023
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 <me@davidbarsky.com>
Co-authored-by: Ryan Johnson <ryantj@fb.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
davidbarsky added a commit that referenced this pull request Sep 29, 2023
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 <me@davidbarsky.com>
Co-authored-by: Ryan Johnson <ryantj@fb.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Oct 1, 2023
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 <me@davidbarsky.com>
Co-authored-by: Ryan Johnson <ryantj@fb.com>
Co-authored-by: Eliza Weisman <eliza@buoyant.io>
hawkw pushed a commit that referenced this pull request Nov 13, 2023
# 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!
facebook-github-bot pushed a commit to facebook/fb303 that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebook/fbthrift that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebookexperimental/rust-shed that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebookincubator/Glean that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebook/sapling that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebook/hhvm that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebookexperimental/reverie that referenced this pull request Nov 14, 2023
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
facebook-github-bot pushed a commit to facebookexperimental/hermit that referenced this pull request Nov 14, 2023
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
vkill pushed a commit to bk-rs/fbthrift-git-rs that referenced this pull request Dec 3, 2023
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
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request Feb 14, 2024
# 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!
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 yet

5 participants