log: Logging std::error::Errors
It would be really nice to have a specialized way of logging errors that implement std::error::Error.
This would allow automatically capturing detailed information about an error, including the Display and Debug representations, and especially backtraces via the new Error::backtrace, which has an open PR.
The main purpose is to give the backend implementation the option to extract all desired information about an error and use it as appropriate for the output.
Not sure how this could fit into the current design, but I’d imagine an additional method on Log and a macro.
trait Log {
...
// The record serves the purpose of providing the location, and optionally an additional error message / metadata.
// Question: Should the record be optional or required?
fn error(&self, error: &dyn std::error::Error, record: Option<&Record>);
}
Plus a macro.
Naming for that macro would of course be somewhat awkward, considering error! exists. Maybe with_error!(). Also there could be a variant of error! that allows specifying an error value.
One could of course ask if this is really necessary, since you could already write a custom macro or method that captures the required information as a Record. But I’d like to see a standardized way of doing this that gives the logger implementation the power to do what it wants, without forcing the user to make a decision here up-front.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 3
- Comments: 15 (7 by maintainers)
We’re on board with adding specific support for
std::error::Errortolog. There’s a PR open at #378 with some initial support that allows you to attach an error to aRecord.For
Send, sincelogalready makes no direct concessions to allowingRecords to be passed across thread boundaries it isn’t going to be required here. You can, however, downcast astd::error::Error, so if your application needed to capture a sendable structured representation of the record then you could downcast it to the kind of error you expect to see at that point.There is some space to explore about macro support though. I think all log levels should support accepting an error, because not every error you encounter is necessarily an error-worthy log. You might want to log them as warnings or debug if they’re non-critical. We could follow the same approach as
target, by allowing another kind of optional special field before the format arguments:@softprops That would be much nicer, but we’ve had trouble in the past attempting to wrangle new syntax into the macros, especially after the message string, because currently that whole lot is shelled straight off to
format_argsas a bag of tokens. Things break in strange ways.Until we can come up with entirely new macros (I’ve been prototyping some stuff in this repo) I think we’ll have to attach the error at the front, before the message.
Personally, I think treating errors as first-class concepts in logs is a worthwhile thing to do. It looks like we might not have given this too much thought in the past, but now that the
std::error::Errortype is more useful and backtrace support is in the works it could be a good time to consider it.We could add something like a
fn source(&self) -> Option<&(dyn Error + 'static)>method toRecordalong with macro support similar to howtargetwas added:Alternatively we could design support into the key-values API and leave it up to convention to capture an error with a common key name. That would probably be my preferred approach, because it would avoid creating too many parallel syntaxes in the
log!macros.