-
Notifications
You must be signed in to change notification settings - Fork 798
Allow thread name and id to be displayed in traces #818
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
Conversation
This PR adds two new methods i.e `with_thread_ids` and `with_thread_names` to the fmt Layer which passed till the pre-configured Format type, where the check is performed and these the above values are formatted based on the flags. The formatting is done by creating to new Types that impl Display for Id and Name. For Thread Name, we keep track of the max length of the thread name that occured till now using a thread safe static type and pad accordingly. For Thread Id, we pad directly with 2 as in most cases we would see a double digit number of threads. Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
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 definitely looks like the right overall approach. I had some notes on the specifics of the implementation.
Also, I'm ccing @davidbarsky, since I imagine he has formatting opinions...
examples/examples/thread-info.rs
Outdated
/// This is a example showing how thread info can be enabled | ||
/// to be attached with events |
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.
How about:
/// This is a example showing how thread info can be enabled | |
/// to be attached with events | |
/// This is a example showing how thread info can be displayed when | |
/// formatting events with `tracing_subscriber::fmt`. |
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 believe that this may have been incorrectly resolved; I like @hawkw's proposed change.
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.
Ahhh, I had this locally but did not save it. Thank you! :)
// fall-back to thread id when name is absent and id's are not enabled | ||
if !self.display_thread_id { | ||
serializer.serialize_entry( | ||
"threadId", |
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 think that in this case, the key should maybe still be threadName
--- if you enable the thread name option, you might reasonably expect all the output JSON to have a field named threadName
, and might write parsing code that expects that...
What do you think?
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.
Yep, Makes sense!
if !self.display_thread_id { | ||
serializer.serialize_entry( | ||
"threadId", | ||
&format!("{:?}", std::thread::current().id()), |
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.
Using format!
here allocates, since format!
constructs a new String
. It would be nice if that was not necessary.
After looking at the serde
API docs, though, it seems like it might be --- there's no way to serialize something's Debug
implementation as a string value except by turning it into a String
and borrowing it. That seems like a deficiency in serde
(or, I'm missing something in the serde
API).
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.
Yeah, I did try searching a way for serde to directly use Debug
impl but could not find how. So, had to use format!
write!(writer, "{} ", FmtThreadId::new(std::thread::current().id()))?; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if self.display_thread_id { | ||
write!(writer, "{} ", FmtThreadId::new(std::thread::current().id()))?; |
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 don't think the FmtThreadId
newtype is really necessary just to add a couple characters of padding...we could just write
write!(writer, "{} ", FmtThreadId::new(std::thread::current().id()))?; | |
} | |
} | |
} | |
} | |
if self.display_thread_id { | |
write!(writer, "{} ", FmtThreadId::new(std::thread::current().id()))?; | |
write!(writer, "{:>2?} ", std::thread::current().id())?; | |
} | |
} | |
} | |
} | |
if self.display_thread_id { | |
write!(writer, "{:>2?} ", std::thread::current().id())?; |
instead, which is a bit simpler...
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.
Yep, That makes sense! Just thought it would be better to have a single place which knows how to format threadId's 👍
if self.display_thread_name { | ||
match std::thread::current().name() { | ||
Some(name) => { | ||
write!(writer, "{} ", FmtThreadName::new(name))?; | ||
} | ||
None => { | ||
// fall-back to thread id when name is absent and id's are not enabled | ||
if !self.display_thread_id { | ||
write!(writer, "{} ", FmtThreadId::new(std::thread::current().id()))?; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if self.display_thread_id { | ||
write!(writer, "{} ", FmtThreadId::new(std::thread::current().id()))?; | ||
} |
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.
same suggestions as the FullCtx
suggestions above.
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
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.
A couple additional suggestions, but overall, this looks great.
I'd still love to hear @davidbarsky's thoughts on the formatting.
examples/examples/thread-info.rs
Outdated
.with_thread_ids(true) | ||
.with_thread_names(true) |
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 be good to add comments on these lines explaining what they're doing, since it's the main thing the example is intended to demonstrate.
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.
Also, take it or leave it: might be nice if the example had CLI arguments to control thread IDs and thread names separately, so that users can demo all the possible combinations? But, adding argument-parsing would add a bunch of code not directly related to the things we're trying to show in this example, so I am not sure whether or not this is a good idea. What do you think?
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 does look very good, thank you! Just a few notes on documentation.
examples/examples/thread-info.rs
Outdated
/// This is a example showing how thread info can be enabled | ||
/// to be attached with events |
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 believe that this may have been incorrectly resolved; I like @hawkw's proposed change.
|
||
static MAX_LEN: AtomicUsize = AtomicUsize::new(0); |
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: can you add a comment explaining why this is necessary? If I'm following along correctly, this sets the maximum length a thread name can be, to ensure better formatted logs? If so, can you add a comment saying that?
Also, what is the scope of MAX_LEN
? It doesn't get dropped once this fmt
call ends, does it?
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.
Also, what is the scope of
MAX_LEN
? It doesn't get dropped once thisfmt
call ends, does it?
Statics don't get dropped. The only difference between a static inside a function and a static outside of a function is visibility; the function-local static is only visible to that function.
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.
re:
Nit: can you add a comment explaining why this is necessary?
@Pothulapati, IIRC, when I suggested we do this, I think I sent a version of this code with comments explaining what it was doing; if you like, please feel free to reuse that.
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.
done! :)
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
/// when formatting events | ||
/// | ||
/// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html | ||
pub fn with_thread_id(self, display_thread_id: bool) -> Format<F, T> { |
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.
Should these fn names also be plural here? My reason for keeping them singular is that they deal with a single event being part of Format
. WDYT?
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.
IMO, I think it's better for them to be consistent --- it's annoying to call a method on one type, and then try to call it on a different type, and get an error because the name is slightly different. Also, the formatter will almost certainly be used to format more than one event, too.
But, I could definitely be convinced otherwise!
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Signed-off-by: Tarun Pothulapati <[email protected]>
Okay, this looks great to me! I'm going to go ahead and merge it. Thanks again for working on this! |
Changed - **fmt**: When the `chrono` dependency is enabled, the `SystemTime` timestamp now emits human-readable timestamps rather than using `SystemTime`'s fmt::Debug`implementation (`chrono` is still required for customized timestamp formatting) (#807) - **ansi**: Updated `ansi_term` dependency to 0.12 (#816) Added - **json**: `with_span_list` method to configure the JSON formatter to include a list of all spans in the current trace in formatting events (similarly to the text formatter) (#741) - **json**: `with_current_span` method to configure the JSON formatter to include a field for the _current_ span (the leaf of the trace) in formatted events (#741) - **fmt**: `with_thread_names` and `with_thread_ids` methods to configure `fmt::Subscriber`s and `fmt::Layer`s to include the thread name and/or thread ID of the current thread when formatting events (#818) Thanks to new contributors @mockersf, @keetonian, and @Pothulapati for contributing to this release!
### Changed - **fmt**: When the `chrono` dependency is enabled, the `SystemTime` timestamp now emits human-readable timestamps rather than using `SystemTime`'s fmt::Debug`implementation (`chrono` is still required for customized timestamp formatting) (#807) - **ansi**: Updated `ansi_term` dependency to 0.12 (#816) ### Added - **json**: `with_span_list` method to configure the JSON formatter to include a list of all spans in the current trace in formatting events (similarly to the text formatter) (#741) - **json**: `with_current_span` method to configure the JSON formatter to include a field for the _current_ span (the leaf of the trace) in formatted events (#741) - **fmt**: `with_thread_names` and `with_thread_ids` methods to configure `fmt::Subscriber`s and `fmt::Layer`s to include the thread name and/or thread ID of the current thread when formatting events (#818) Thanks to new contributors @mockersf, @keetonian, and @Pothulapati for contributing to this release!
Motivation
Fixes #809
Solution
This PR adds two new methods i.e
with_thread_ids
andwith_thread_names
to the fmt Layer which passed tillthe pre-configured Format type, where the check is performed
and these the above values are formatted based on the flags.
The formatting is done by creating to new Types that impl Display
for Id and Name. For Thread Name, we keep track of the max length
of the thread name that occured till now using a thread safe static
type and pad accordingly. For Thread Id, we pad directly with 2
as in most cases we would see a double digit number of threads.
Signed-off-by: Tarun Pothulapati [email protected]