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

subscriber: directives: accept legit log level names in mixed case (env_logger compat) #1126

Merged
merged 2 commits into from
Dec 10, 2020

Conversation

salewski
Copy link
Contributor

@salewski salewski commented Dec 6, 2020

Hi Folks,

This PR is about behavior compatibility with the env_logger and log crates. There are references in the tracing-subscriber docs noting some level of partial compatibility with env_logger, but it is not clear to me the extent to which that is a priority.

If the intention is to keep the projects close in behavior where there is overlap in the representations of logging directive strings, then this PR is a step toward better compatibility.

On the other hand, if such compatibility is more of a short-term nice-to-have than a long-term objective, then this PR might be a step in the wrong direction. If so, please feel free to reject it. I happened to notice the behavior difference (described below) while working on something else, and just thought I'd bring it up for discussion.

On the other other hand, it is clear that some significant effort has been expended to have compatibly parsed logging directive strings. Which leads me to read the regex code modified in the second commit of this PR as possibly introducing a level of compatibility that was deliberately omitted; the existing regex was clearly structured to accept only all uppercase OR only all lowercase log level names. So I'm getting mixed signals :-)

In the end, regardless of the specific outcome of this PR, understanding the degree to which env_logger compatibility is wanted would be useful to know in general.

For my own use, env_logger compatibility is not something I need.

Motivation

Logging directive strings parsed to create tracing_subscriber::filter::env::Directives are currently accepted as all-lower-case or all-upper-case representations of the log level names (like "info" and "INFO"), but mixed case representation (like "Info", "iNfo", and "infO") are rejected.

This behavior is divergent with that of the env_logger crate, which accepts the mixed case names. The env_logger crate gets the behavior of parsing mixed case log level names from the underlying log crate, so there may be an element of user expectations involved in that regard, too, with log users expecting that case-insensitive log level names will be accepted.

Accepting mixed case names would bring the behavior of the tracing_subscriber crate back into alignment those other crates in this regard.

Solution

Accept mixed case names for log levels in directive strings.

This PR includes two commits:

  1. The first adds unit tests that demonstrate the mixed case logging level names being rejected.

  2. The second introduces an adjustment to DIRECTIVE_RE that accepts mixed case logging level names. With this change, the tests again all pass.

@salewski salewski requested review from hawkw and a team as code owners December 6, 2020 00:26
@hawkw
Copy link
Member

hawkw commented Dec 6, 2020

Thanks for the PR! I definitely agree that if env_logger accepts mixed-case level names, then we ought to accept them as well.

I think the CI failure on Rust 1.42.0 is due to an upstream dependency breaking compatibility with our MSRV — that's not related to this PR at all. When that's fixed on master, you can update this branch, and the CI run should pass.

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.

looks good to me once we get a green CI build — I left a couple suggestions but they're not important, so feel free to take it or leave it!

Comment on lines 1032 to 1067
#[test]
fn parse_directives_global_bare_warn_lc() {
// test parse_directives with no crate, in isolation, all lowercase
let dirs = parse_directives("warn");
assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs);
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}

#[test]
fn parse_directives_global_bare_warn_uc() {
// test parse_directives with no crate, in isolation, all uppercase
let dirs = parse_directives("WARN");
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}

#[test]
fn parse_directives_global_bare_warn_mixed() {
// test parse_directives with no crate, in isolation, mixed case
let dirs = parse_directives("wArN");
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}
Copy link
Member

Choose a reason for hiding this comment

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

Since this PR adds so many new test cases that are all pretty equivalent, I wonder if it's worth trying to factor out some of the repeated code. For example, we could do something like:

Suggested change
#[test]
fn parse_directives_global_bare_warn_lc() {
// test parse_directives with no crate, in isolation, all lowercase
let dirs = parse_directives("warn");
assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs);
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}
#[test]
fn parse_directives_global_bare_warn_uc() {
// test parse_directives with no crate, in isolation, all uppercase
let dirs = parse_directives("WARN");
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}
#[test]
fn parse_directives_global_bare_warn_mixed() {
// test parse_directives with no crate, in isolation, mixed case
let dirs = parse_directives("wArN");
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}
fn test_parse_bare_level(directive: &str, level: LevelFilter) {
let dirs = parse_directives(directive);
assert_eq!(dirs.len(), 1, "\nparsed: {:#?}", dirs);
assert_eq!(dirs[0].target, None);
assert_eq!(dirs[0].level, LevelFilter::WARN);
assert_eq!(dirs[0].in_span, None);
}
#[test]
fn parse_directives_global_bare_warn_lc() {
// test parse_directives with no crate, in isolation, all lowercase
test_parse_bare_level("warn", LevelFilter::WARN);
}
#[test]
fn parse_directives_global_bare_warn_uc() {
// test parse_directives with no crate, in isolation, all uppercase
test_parse_bare_level("WARN", LevelFilter::WARN);
}
#[test]
fn parse_directives_global_bare_warn_mixed() {
// test parse_directives with no crate, in isolation, mixed case
test_parse_bare_level("wArN", LevelFilter::WARN);
}

If you don't think this is worth the effort, I'm happy to merge this PR either way — just a thought!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this PR adds so many new test cases that are all pretty equivalent, I wonder if it's worth trying to factor out some of the repeated code. For example, we could do something like:

If you don't think this is worth the effort, I'm happy to merge this PR either way — just a thought!

Thanks for the suggestion; that's clearly better. I'll incorporate it and rebase.

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 incorporated this idea into my push from earlier tonight.

@salewski salewski force-pushed the ads/parse-spec-raw-level-tests branch from 9f33370 to 4e7ba7a Compare December 7, 2020 01:25
@hawkw
Copy link
Member

hawkw commented Dec 8, 2020

If you don't mind rebasing the current master, #1128 should have fixed the CI failure. Thanks!

@salewski salewski force-pushed the ads/parse-spec-raw-level-tests branch from 4e7ba7a to 74cdfef Compare December 9, 2020 04:22
@salewski
Copy link
Contributor Author

salewski commented Dec 9, 2020

If you don't mind rebasing the current master, #1128 should have fixed the CI failure. Thanks!

I just pushed a rebase, but the rustfmt step in the "style" test isn't happy. Let me fix that up, too, and I'll push another rebase shortly. More soon...

@salewski salewski force-pushed the ads/parse-spec-raw-level-tests branch from 74cdfef to c40f926 Compare December 9, 2020 04:42
@salewski
Copy link
Contributor Author

salewski commented Dec 9, 2020

If you don't mind rebasing the current master, #1128 should have fixed the CI failure. Thanks!

I just pushed a rebase, but the rustfmt step in the "style" test isn't happy. Let me fix that up, too, and I'll push another rebase shortly. More soon...

I just pushed those changes.

@salewski
Copy link
Contributor Author

salewski commented Dec 9, 2020

If you don't mind rebasing the current master, #1128 should have fixed the CI failure. Thanks!

I just pushed a rebase, but the rustfmt step in the "style" test isn't happy. Let me fix that up, too, and I'll push another rebase shortly. More soon...

I just pushed those changes.

Those changes were not greeted with unanimous green checkmark applause by the CI checks :-)

(Other CI stuff unrelated to this PR)

These test parse_directives() against strings that contain only a
legit log level name. The variants that submit the mixed case forms
are currently failing:

    $ cargo test --lib 'filter::env::directive::test::parse_directives_'
    ...
    failures:
        filter::env::directive::test::parse_directives_global_bare_warn_mixed
        filter::env::directive::test::parse_directives_ralith_mixed

    test result: FAILED. 12 passed; 2 failed; 0 ignored; 0 measured; 61 filtered out

Fix to come in a follow-up commit.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
 Signed-off-by: Alan D. Salewski <ads@salewski.email>
Fix issue demonstrated by unit tests in commit f607b7f. With
this commit, the unit tests all pass.

The 'DIRECTIVE_RE' regex now uses a case-insensitive, non-capturing
subgroup when matching log level names in logging directive
strings. This allows correctly capturing not only, e.g., "info" and
"INFO" (both of which were also accepted previously), but also
"Info" and other combinations of mixed case variations for the legit
log level names.

This change makes the behavior of tracing-subscriber more consistent
with that of the `env_logger` crate, which also accepts mixed case
variations of the log level names.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
 Signed-off-by: Alan D. Salewski <ads@salewski.email>
@salewski salewski force-pushed the ads/parse-spec-raw-level-tests branch from c40f926 to 6342e09 Compare December 10, 2020 21:20
@salewski
Copy link
Contributor Author

These changes were rebased on top of the updates to master from issue #1131. The CI checks are all green now.

@salewski salewski requested a review from hawkw December 10, 2020 21:35
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 looks great, thank you!

@hawkw hawkw merged commit aa2bae0 into tokio-rs:master Dec 10, 2020
hawkw pushed a commit that referenced this pull request Dec 14, 2020
…nv_logger compat) (#1126)

Hi Folks,

This PR is about behavior compatibility with the `env_logger` and `log`
crates. There are references in the `tracing-subscriber` docs noting
some level of partial compatibility with `env_logger`, but it is not
clear to me the extent to which that is a priority.

If the intention is to keep the projects close in behavior where there
is overlap in the representations of logging directive strings, then
this PR is a step toward better compatibility.

On the other hand, if such compatibility is more of a short-term
nice-to-have than a long-term objective, then this PR might be a step in
the wrong direction. If so, please feel free to reject it. I happened to
notice the behavior difference (described below) while working on
something else, and just thought I'd bring it up for discussion.

On the *other* other hand, it is clear that some significant effort
*has* been expended to have compatibly parsed logging directive strings.
Which leads me to read the regex code modified in the second commit of
this PR as possibly introducing a level of compatibility that was
deliberately omitted; the existing regex was clearly structured to
accept *only* all uppercase OR *only* all lowercase log level names. So
I'm getting mixed signals :-)

In the end, regardless of the specific outcome of this PR, understanding
the degree to which `env_logger` compatibility is wanted would be useful
to know in general.

For my own use, `env_logger` compatibility is not something I need.


## Motivation

Logging directive strings parsed to create
`tracing_subscriber::filter::env::Directive`s are currently accepted as
all-lower-case or all-upper-case representations of the log level names
(like "info" and "INFO"), but mixed case representation (like "Info",
"iNfo", and "infO") are rejected.

This behavior is divergent with that of the `env_logger` crate, which
accepts the mixed case names. The `env_logger` crate gets the behavior
of parsing mixed case log level names from the underlying `log` crate,
so there may be an element of user expectations involved in that regard,
too, with `log` users expecting that case-insensitive log level names
will be accepted.

Accepting mixed case names would bring the behavior of the
`tracing_subscriber` crate back into alignment those other crates in
this regard.


## Solution

Accept mixed case names for log levels in directive strings.

This PR includes two commits:

   1. The first adds unit tests that demonstrate the mixed case logging
   level names being rejected.

   2. The second introduces an adjustment to `DIRECTIVE_RE` that accepts
   mixed case logging level names. With this change, the tests again all
   pass.

* [1 of 2]: subscriber: add more parse_directives* tests

These test parse_directives() against strings that contain only a
legit log level name. The variants that submit the mixed case forms
are currently failing:

    $ cargo test --lib 'filter::env::directive::test::parse_directives_'
    ...
    failures:
        filter::env::directive::test::parse_directives_global_bare_warn_mixed
        filter::env::directive::test::parse_directives_ralith_mixed

    test result: FAILED. 12 passed; 2 failed; 0 ignored; 0 measured; 61 filtered out

Fix to come in a follow-up commit.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
 Signed-off-by: Alan D. Salewski <ads@salewski.email>

* [2 of 2]: subscriber: directives: accept log levels in mixed case

Fix issue demonstrated by unit tests in commit f607b7f. With
this commit, the unit tests all pass.

The 'DIRECTIVE_RE' regex now uses a case-insensitive, non-capturing
subgroup when matching log level names in logging directive
strings. This allows correctly capturing not only, e.g., "info" and
"INFO" (both of which were also accepted previously), but also
"Info" and other combinations of mixed case variations for the legit
log level names.

This change makes the behavior of tracing-subscriber more consistent
with that of the `env_logger` crate, which also accepts mixed case
variations of the log level names.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
 Signed-off-by: Alan D. Salewski <ads@salewski.email>
hawkw pushed a commit that referenced this pull request Dec 14, 2020
…nv_logger compat) (#1126)

Hi Folks,

This PR is about behavior compatibility with the `env_logger` and `log`
crates. There are references in the `tracing-subscriber` docs noting
some level of partial compatibility with `env_logger`, but it is not
clear to me the extent to which that is a priority.

If the intention is to keep the projects close in behavior where there
is overlap in the representations of logging directive strings, then
this PR is a step toward better compatibility.

On the other hand, if such compatibility is more of a short-term
nice-to-have than a long-term objective, then this PR might be a step in
the wrong direction. If so, please feel free to reject it. I happened to
notice the behavior difference (described below) while working on
something else, and just thought I'd bring it up for discussion.

On the *other* other hand, it is clear that some significant effort
*has* been expended to have compatibly parsed logging directive strings.
Which leads me to read the regex code modified in the second commit of
this PR as possibly introducing a level of compatibility that was
deliberately omitted; the existing regex was clearly structured to
accept *only* all uppercase OR *only* all lowercase log level names. So
I'm getting mixed signals :-)

In the end, regardless of the specific outcome of this PR, understanding
the degree to which `env_logger` compatibility is wanted would be useful
to know in general.

For my own use, `env_logger` compatibility is not something I need.


## Motivation

Logging directive strings parsed to create
`tracing_subscriber::filter::env::Directive`s are currently accepted as
all-lower-case or all-upper-case representations of the log level names
(like "info" and "INFO"), but mixed case representation (like "Info",
"iNfo", and "infO") are rejected.

This behavior is divergent with that of the `env_logger` crate, which
accepts the mixed case names. The `env_logger` crate gets the behavior
of parsing mixed case log level names from the underlying `log` crate,
so there may be an element of user expectations involved in that regard,
too, with `log` users expecting that case-insensitive log level names
will be accepted.

Accepting mixed case names would bring the behavior of the
`tracing_subscriber` crate back into alignment those other crates in
this regard.


## Solution

Accept mixed case names for log levels in directive strings.

This PR includes two commits:

   1. The first adds unit tests that demonstrate the mixed case logging
   level names being rejected.

   2. The second introduces an adjustment to `DIRECTIVE_RE` that accepts
   mixed case logging level names. With this change, the tests again all
   pass.

* [1 of 2]: subscriber: add more parse_directives* tests

These test parse_directives() against strings that contain only a
legit log level name. The variants that submit the mixed case forms
are currently failing:

    $ cargo test --lib 'filter::env::directive::test::parse_directives_'
    ...
    failures:
        filter::env::directive::test::parse_directives_global_bare_warn_mixed
        filter::env::directive::test::parse_directives_ralith_mixed

    test result: FAILED. 12 passed; 2 failed; 0 ignored; 0 measured; 61 filtered out

Fix to come in a follow-up commit.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
 Signed-off-by: Alan D. Salewski <ads@salewski.email>

* [2 of 2]: subscriber: directives: accept log levels in mixed case

Fix issue demonstrated by unit tests in commit f607b7f. With
this commit, the unit tests all pass.

The 'DIRECTIVE_RE' regex now uses a case-insensitive, non-capturing
subgroup when matching log level names in logging directive
strings. This allows correctly capturing not only, e.g., "info" and
"INFO" (both of which were also accepted previously), but also
"Info" and other combinations of mixed case variations for the legit
log level names.

This change makes the behavior of tracing-subscriber more consistent
with that of the `env_logger` crate, which also accepts mixed case
variations of the log level names.

Co-authored-by: Eliza Weisman <eliza@buoyant.io>
 Signed-off-by: Alan D. Salewski <ads@salewski.email>
hawkw added a commit that referenced this pull request Feb 20, 2021
Fixed

- **env-filter**: Fixed directives where the level is in mixed case
  (such as `Info`) failing to parse ([#1126])
- **fmt**: Fixed `fmt::Subscriber` not providing a max-level hint
  ([#1251])
- `tracing-subscriber` no longer enables `tracing` and `tracing-core`'s
  default features ([#1144])

Changed

- **chrono**: Updated `chrono` dependency to 0.4.16 ([#1189])
- **log**: Updated `tracing-log` dependency to 0.1.2

Thanks to @salewski, @taiki-e, @davidpdrsn and @markdingram for
contributing to this release!

[#1126]: #1126
[#1251]: #1251
[#1144]: #1144
[#1189]: #1189

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Feb 20, 2021
### Fixed

- **env-filter**: Fixed directives where the level is in mixed case
  (such as `Info`) failing to parse ([#1126])
- **fmt**: Fixed `fmt::Subscriber` not providing a max-level hint
  ([#1251])
- `tracing-subscriber` no longer enables `tracing` and `tracing-core`'s
  default features ([#1144])

### Changed

- **chrono**: Updated `chrono` dependency to 0.4.16 ([#1189])
- **log**: Updated `tracing-log` dependency to 0.1.2

Thanks to @salewski, @taiki-e, @davidpdrsn and @markdingram for
contributing to this release!

[#1126]: #1126
[#1251]: #1251
[#1144]: #1144
[#1189]: #1189

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
### Fixed

- **env-filter**: Fixed directives where the level is in mixed case
  (such as `Info`) failing to parse ([tokio-rs#1126])
- **fmt**: Fixed `fmt::Subscriber` not providing a max-level hint
  ([tokio-rs#1251])
- `tracing-subscriber` no longer enables `tracing` and `tracing-core`'s
  default features ([tokio-rs#1144])

### Changed

- **chrono**: Updated `chrono` dependency to 0.4.16 ([tokio-rs#1189])
- **log**: Updated `tracing-log` dependency to 0.1.2

Thanks to @salewski, @taiki-e, @davidpdrsn and @markdingram for
contributing to this release!

[tokio-rs#1126]: tokio-rs#1126
[tokio-rs#1251]: tokio-rs#1251
[tokio-rs#1144]: tokio-rs#1144
[tokio-rs#1189]: tokio-rs#1189

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
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.

2 participants