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

Fix pretty formatter thread id double space #1778

Merged
merged 2 commits into from
Dec 22, 2021

Conversation

rukai
Copy link
Contributor

@rukai rukai commented Dec 15, 2021

Before this PR there was one two many spaces between "on" and "ThreadId" when thread id formatting is enabled but thread name formatting is disabled.
There was no issue when both thread name and thread id were enabled.

Previous output:

  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on  ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"

new output:

  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"

I spent a lot of time working on unittests, I managed to add tests for a lot of related cases but couldnt test the actual case here :/
When I write a test like:

    #[test]
    fn pretty_threads_ids() {
        let make_writer = MockMakeWriter::default();
        let subscriber = crate::fmt::Collector::builder()
            .pretty()
            .with_thread_ids(true)
            .with_writer(make_writer.clone())
            .with_ansi(false)
            .with_timer(MockTime);
        assert_info_hello_ignore_numeric(
            subscriber,
            make_writer,
            r#"  fake time  INFO tracing_subscriber::fmt::format::test: hello
    at tracing-subscriber/src/fmt/format/mod.rs:

"#,
        )
    }

Inexplicably the thread id is not displayed.

Hopefully you can accept the tests I did write as a compromise, the actual fix here is really simple.

@rukai rukai requested review from davidbarsky, hawkw and a team as code owners December 15, 2021 03:19
@rukai rukai force-pushed the fix_thread_id_double_space branch 2 times, most recently from 6041fb6 to b9bea5b Compare December 21, 2021 00:17
@rukai
Copy link
Contributor Author

rukai commented Dec 21, 2021

I believe I have fixed the failure on windows but CI needs to be authorized again.

@@ -174,13 +174,12 @@ where
if let Some(name) = thread.name() {
write!(writer, "{}", name)?;
if self.display_thread_id {
write!(writer, " ({:?})", thread.id())?;
Copy link
Member

Choose a reason for hiding this comment

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

hmm, this changes the formatting slightly because we'll no longer have parentheses around thread IDs when thread names are also enabled. i'm not sure if this is particularly important, though.

Copy link
Contributor Author

@rukai rukai Dec 21, 2021

Choose a reason for hiding this comment

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

good point, I didnt notice those extra brackets.
However looking at it I think this is an improvement as the thread id is displayed with the debug display ThreadId(1) so having (ThreadId(1)) is a bit weird.

Copy link
Member

Choose a reason for hiding this comment

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

sure, i don't have a strong opinion on whether the parentheses are good or not, although they seemed more grammatically correct here. not a big deal either way though.

Copy link
Member

Choose a reason for hiding this comment

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

normally, i'd try to reserve formatting changes for a major version bump, but this seems reasonable to me.

assert_eq!(expected, result)
}

// When numeric characters are used they often form a non-deterministic value.
Copy link
Member

Choose a reason for hiding this comment

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

it would be nice if this comment explained why these values are nondeterministic...

Comment on lines 1595 to 1599
let result: String = buf
.get_string()
.chars()
.filter(|x| !x.is_numeric())
.collect();
Copy link
Member

Choose a reason for hiding this comment

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

i think this could probably be simplified a bit using str::replace from the standard library? not a hard blocker, though.

Copy link
Member

Choose a reason for hiding this comment

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

also, it could be nice if we replaced the numeric characters with a specific character, rather than just removing them? that way, we would be asserting that they were present at that position in the expected string. the current tests will pass even if, for example, no line number was actually printed.

on the other hand, there might be a variable number of numeric characters in the string --- if the code changes significantly, the line number might have another tens place, for example. we could probably work around that using a regex to replace any number of numeric characters with a single one, but i am not sure if this is really worth the effort...

Copy link
Contributor Author

@rukai rukai Dec 21, 2021

Choose a reason for hiding this comment

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

I avoided solutions using regex to avoid adding it as a dev-dep. As you've noted we could make this nicer with regex, so if your happy for me to add the regex dev-dep then I'll rewrite this using regex.

@rukai
Copy link
Contributor Author

rukai commented Dec 21, 2021

It seems PathBuf::from("tracing-subscriber/src/fmt/format/mod.rs").to_str().unwrap() does not output a path with \ so im retrying with replace('/', &std::path::MAIN_SEPARATOR.to_string())

For replacing the digits I just did .replace with an empty string, happy to change this again though.

Comment on lines 1563 to 1567
let expected = r#" fake time INFO tracing_subscriber::fmt::format::test: hello
at tracing-subscriber/src/fmt/format/mod.rs:

"#
.replace('/', &std::path::MAIN_SEPARATOR.to_string());
Copy link
Member

Choose a reason for hiding this comment

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

what if, instead of using replace to fix the path separator, we just used the file!() macro, like this:

Suggested change
let expected = r#" fake time INFO tracing_subscriber::fmt::format::test: hello
at tracing-subscriber/src/fmt/format/mod.rs:
"#
.replace('/', &std::path::MAIN_SEPARATOR.to_string());
let expected = concat!(
" fake time INFO tracing_subscriber::fmt::format::test: hello\n",
" at ",
file!(),
":\n"
);

this way, we will always get the actual path to the file as understood by Cargo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh thats nice! (hopefully it does what we expect on windows)

@@ -174,13 +174,12 @@ where
if let Some(name) = thread.name() {
write!(writer, "{}", name)?;
if self.display_thread_id {
write!(writer, " ({:?})", thread.id())?;
Copy link
Member

Choose a reason for hiding this comment

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

sure, i don't have a strong opinion on whether the parentheses are good or not, although they seemed more grammatically correct here. not a big deal either way though.

let _default = set_default(&subscriber.into());
tracing::info!("hello");

let result = buf.get_string().replace(char::is_numeric, "");
Copy link
Member

Choose a reason for hiding this comment

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

The reason I originally suggested using a regular expression here is that this approach does have the issue that the tests will still pass if the line numbers (and other numeric characters) are totally missing, which is not really ideal.

I don't actually think it's important to avoid adding the regex crate as a dev-dependency, because...tracing-subscriber already has a dev-dependency on regex:

regex = { version = "1", default-features = false, features = ["std"] }
:)

So, I think changing this to use a regular expression is probably the best solution.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ahaha I completely missed it was already a dep.
I changed it to use a regex.

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 good to me! thanks for adding the tests, they look great!

Comment on lines +1595 to +1597
let regex = Regex::new("[0-9]+").unwrap();
let result = buf.get_string();
let result_cleaned = regex.replace_all(&result, "NUMERIC");
Copy link
Member

Choose a reason for hiding this comment

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

nit, take it or leave it: we may want to put the regex in a lazy_static! to avoid recompiling the regex in every test:

Suggested change
let regex = Regex::new("[0-9]+").unwrap();
let result = buf.get_string();
let result_cleaned = regex.replace_all(&result, "NUMERIC");
lazy_static::lazy_static! {
static ref REGEX: Regex = Regex::new("[0-9]+").unwrap();
}
let result = buf.get_string();
let result_cleaned = regex.replace_all(&REGEX, "NUMERIC");

in theory, this might improve performance somewhat. in practice, I don't think the regex is compiled enough to have a significant impact on how long it takes to run these tests, so this may not really be worth the effort.

tracing-subscriber/src/fmt/format/pretty.rs Outdated Show resolved Hide resolved
@hawkw hawkw merged commit 76825ba into tokio-rs:master Dec 22, 2021
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.

bunch of non-blocking nits that don't need to be addressed.

@@ -174,13 +174,12 @@ where
if let Some(name) = thread.name() {
write!(writer, "{}", name)?;
if self.display_thread_id {
write!(writer, " ({:?})", thread.id())?;
Copy link
Member

Choose a reason for hiding this comment

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

normally, i'd try to reserve formatting changes for a major version bump, but this seems reasonable to me.

Comment on lines +1585 to +1591
// When numeric characters are used they often form a non-deterministic value as they usually represent things like a thread id or line number.
// This assert method should be used when non-deterministic numeric characters are present.
fn assert_info_hello_ignore_numeric(
subscriber: impl Into<Dispatch>,
buf: MockMakeWriter,
expected: &str,
) {
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 a non-blocking nit (eliza is extremely welcome to override with an "ignore david, this is fine"), but since this only used in two callsites, i'd rather have the contents of this method be inlined into each test.

assert_info_hello_ignore_numeric(subscriber, make_writer, &expected)
}

fn assert_info_hello(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) {
Copy link
Member

Choose a reason for hiding this comment

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

nit, take it or leave it: the "hello" doesn't really say too much about the test; i'd rather have the previous set of names here.

@davidbarsky
Copy link
Member

oh, Eliza merged this as I was commented on the PR. feel free to ignore them!

@hawkw
Copy link
Member

hawkw commented Dec 22, 2021

oh, Eliza merged this as I was commented on the PR. feel free to ignore them!

whoops, sorry about that! we can always apply additional test suggestions in a follow-up PR?

hawkw pushed a commit that referenced this pull request Dec 23, 2021
…1778)

Before this PR there was one two many spaces between "on" and "ThreadId"
when thread id formatting is enabled but thread name formatting is
disabled. There was no issue when both thread name and thread id were
enabled.

Previous output:
```
  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on  ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"
```

new output:
```
  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"
```

I spent a lot of time working on unittests, I managed to add tests for a
lot of related cases but couldnt test the actual case here :/ When I
write a test like:
```rust
    #[test]
    fn pretty_threads_ids() {
        let make_writer = MockMakeWriter::default();
        let subscriber = crate::fmt::Collector::builder()
            .pretty()
            .with_thread_ids(true)
            .with_writer(make_writer.clone())
            .with_ansi(false)
            .with_timer(MockTime);
        assert_info_hello_ignore_numeric(
            subscriber,
            make_writer,
            r#"  fake time  INFO tracing_subscriber::fmt::format::test: hello
    at tracing-subscriber/src/fmt/format/mod.rs:

"#,
        )
    }
```
Inexplicably the thread id is not displayed.

Hopefully you can accept the tests I did write as a compromise, the
actual fix here is really simple.
hawkw pushed a commit that referenced this pull request Dec 23, 2021
…1778)

Before this PR there was one two many spaces between "on" and "ThreadId"
when thread id formatting is enabled but thread name formatting is
disabled. There was no issue when both thread name and thread id were
enabled.

Previous output:
```
  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on  ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"
```

new output:
```
  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"
```

I spent a lot of time working on unittests, I managed to add tests for a
lot of related cases but couldnt test the actual case here :/ When I
write a test like:
```rust
    #[test]
    fn pretty_threads_ids() {
        let make_writer = MockMakeWriter::default();
        let subscriber = crate::fmt::Collector::builder()
            .pretty()
            .with_thread_ids(true)
            .with_writer(make_writer.clone())
            .with_ansi(false)
            .with_timer(MockTime);
        assert_info_hello_ignore_numeric(
            subscriber,
            make_writer,
            r#"  fake time  INFO tracing_subscriber::fmt::format::test: hello
    at tracing-subscriber/src/fmt/format/mod.rs:

"#,
        )
    }
```
Inexplicably the thread id is not displayed.

Hopefully you can accept the tests I did write as a compromise, the
actual fix here is really simple.
hawkw added a commit that referenced this pull request Dec 23, 2021
# 0.3.4 (Dec 23, 2021)

This release contains bugfixes for the `fmt` module, as well as documentation
improvements.

### Fixed

- **fmt**: Fixed `fmt` not emitting log lines when timestamp formatting fails
  ([#1689])
- **fmt**: Fixed double space before thread IDs with `Pretty` formatter
  ([#1778])
- Several documentation improvements ([#1608], [#1699], [#1701])

[#1689]: #1689
[#1778]: #1778
[#1608]: #1608
[#1699]: #1699
[#1701]: #1701

Thanks to new contributors @Swatinem and @rukai for contributing to this
release!
hawkw added a commit that referenced this pull request Dec 23, 2021
# 0.3.4 (Dec 23, 2021)

This release contains bugfixes for the `fmt` module, as well as documentation
improvements.

### Fixed

- **fmt**: Fixed `fmt` not emitting log lines when timestamp formatting fails
  ([#1689])
- **fmt**: Fixed double space before thread IDs with `Pretty` formatter
  ([#1778])
- Several documentation improvements ([#1608], [#1699], [#1701])

[#1689]: #1689
[#1778]: #1778
[#1608]: #1608
[#1699]: #1699
[#1701]: #1701

Thanks to new contributors @Swatinem and @rukai for contributing to this
release!
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
…okio-rs#1778)

Before this PR there was one two many spaces between "on" and "ThreadId"
when thread id formatting is enabled but thread name formatting is
disabled. There was no issue when both thread name and thread id were
enabled.

Previous output:
```
  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on  ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"
```

new output:
```
  2021-12-15T00:44:05.596510Z ERROR shotover_proxy::transforms::redis::cache: failed to fetch from cache: system.local not a caching table
    at shotover-proxy/src/transforms/redis/cache.rs:366 on ThreadId(5)
    in shotover_proxy::server::request with id=5 source="CassandraSource"
```

I spent a lot of time working on unittests, I managed to add tests for a
lot of related cases but couldnt test the actual case here :/ When I
write a test like:
```rust
    #[test]
    fn pretty_threads_ids() {
        let make_writer = MockMakeWriter::default();
        let subscriber = crate::fmt::Collector::builder()
            .pretty()
            .with_thread_ids(true)
            .with_writer(make_writer.clone())
            .with_ansi(false)
            .with_timer(MockTime);
        assert_info_hello_ignore_numeric(
            subscriber,
            make_writer,
            r#"  fake time  INFO tracing_subscriber::fmt::format::test: hello
    at tracing-subscriber/src/fmt/format/mod.rs:

"#,
        )
    }
```
Inexplicably the thread id is not displayed.

Hopefully you can accept the tests I did write as a compromise, the
actual fix here is really simple.
kaffarell pushed a commit to kaffarell/tracing that referenced this pull request May 22, 2024
# 0.3.4 (Dec 23, 2021)

This release contains bugfixes for the `fmt` module, as well as documentation
improvements.

### Fixed

- **fmt**: Fixed `fmt` not emitting log lines when timestamp formatting fails
  ([tokio-rs#1689])
- **fmt**: Fixed double space before thread IDs with `Pretty` formatter
  ([tokio-rs#1778])
- Several documentation improvements ([tokio-rs#1608], [tokio-rs#1699], [tokio-rs#1701])

[tokio-rs#1689]: tokio-rs#1689
[tokio-rs#1778]: tokio-rs#1778
[tokio-rs#1608]: tokio-rs#1608
[tokio-rs#1699]: tokio-rs#1699
[tokio-rs#1701]: tokio-rs#1701

Thanks to new contributors @Swatinem and @rukai for contributing to this
release!
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

3 participants