tokio-rs / tracing

Application level tracing for Rust.
https://tracing.rs
MIT License
5.51k stars 723 forks source link

Introduce a formatter sigil for "alternate" `Display` #1311

Open thomaseizinger opened 3 years ago

thomaseizinger commented 3 years ago

Feature Request

Motivation

anyhow provides a formatting of the whole error chain through the alternate selector {:#}: https://docs.rs/anyhow/1.0.38/anyhow/struct.Error.html#display-representations

It would be nice to make use of this within tracing events in a concise way.

Proposal

Add a formatter sigil (possibly #) to tracing that allows to print values using their alternate Display implementation.

For example:


let error = anyhow!("Oh noes!").context("Something went horribly wrong!");

tracing::error!(#error, "What a mess")

Would print as:

ERROR What a mess error=Something went horribly wrong!: Oh noes!

Alternative

One can convert an anyhow error into a std-error. If reporting std-errors were to be made more ergonomic AND tracing provides a way of printing all causes of std-errors, then this feature is not needed. That being said, triggering the alternative Display impl is not specific to anyhow and might be useful in general.

hawkw commented 3 years ago

I'm open to adding an alt-mode sigil to format specifiers. I imagine what we would want to do is add it as a modifier for both the Display and Debug sigils, so you can write ?# as well as %#.

Implementing alt mode as a sigil would add a lot of new complexity to the macros, though, which is not ideal. I think it might be worth trying to design a more general way to include any arbitrary format specifiers (such as, for example, format an integer in hexadecimal) without having to write field = format_args!("{:x}", hex_number) or similar, which is quite verbose. I'm not sure what a syntax for arbitrary format specifiers would look like, off the top of my head, but I'm open to suggestions!

thomaseizinger commented 3 years ago

I'm not sure what a syntax for arbitrary format specifiers would look like, off the top of my head, but I'm open to suggestions!

What comes to my mind is a similar syntax as here: https://docs.rs/thiserror/1.0.24/thiserror/#details

For example:

let id = Uuid::new_v4();

tracing::debug!({id}, "New ID generated"); // {} prints as Display
tracing::debug!({id:?}, "New ID generated"); // {:?} prints as Debug
tracing::debug!({id:#}, "New ID generated"); // {:?} prints as Display alternate
// etc

We could still retain a special case of:

tracing::debug!(id, "New ID generated");

For using the regular Display impl which I assume is going to be quite common.

let4be commented 3 years ago

Also need to support this in #instrument macro as it can be made to print errors as well...

lilyball commented 3 years ago

An arbitrary format syntax would be great, but I think "alternate mode" is the most important and it would be perfectly okay if we simply supported that and required format_args!() for anything more complicated.

The lack of support for # is something that I keep running into, especially when trying to port code from slog to tracing (as slog supports the # modifier).