-
-
Notifications
You must be signed in to change notification settings - Fork 147
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
RFC: Add support for customizable error handlers based on eyre
#96
Comments
One possible solution for the fn Backtrace stuff would be to wrap the inner error in a newtype that transparently forwards |
elasticdog
added a commit
to EarthmanMuons/rustops-blueprint
that referenced
this issue
May 13, 2023
Good for CLI applications, it provides some nicer ergonomics, features to inject context if needed, as well as non-trivial optimizations compared to using `Box<dyn Error>`. For the xtasks use case, I'm going with the simpler `anyhow` over something like `color-eyre`, which supports more complicated output formatting (but has other trade-offs). See: - dtolnay/anyhow#96
elasticdog
added a commit
to EarthmanMuons/rustops-blueprint
that referenced
this issue
May 13, 2023
Good for CLI applications, it provides some nicer ergonomics, features to inject context if needed, as well as non-trivial optimizations compared to using `Box<dyn Error>`. For the xtasks use case, I'm going with the simpler `anyhow` over something like `color-eyre`, which supports more complicated output formatting (but has other trade-offs). See: - dtolnay/anyhow#96
github-merge-queue bot
pushed a commit
to EarthmanMuons/rustops-blueprint
that referenced
this issue
May 13, 2023
Good for CLI applications, it provides some nicer ergonomics, features to inject context if needed, as well as non-trivial optimizations compared to using `Box<dyn Error>`. For the xtasks use case, I'm going with the simpler `anyhow` over something like `color-eyre`, which supports more complicated output formatting (but has other trade-offs). See: - dtolnay/anyhow#96
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Proposal TLDR
Add a dynamic dispatch based version of
eyre::Report
'sEyreHandler
trait and parameter, with a global hook for constructing the boxed trait object that stores additional context and handles rendering error reports.eyre::EyreHandler::default
is replaced with the hook fn, thedefault
fn is removed from theReportHandler
trait, and theeyre::EyreHandler::display
fn is renamed toreport
to better represent it's usage.The proof of concept is currently implemented in #97
Background
eyre
is a library based on anyhow that has experimented with adding customization support toanyhow::Error
to add support to forms of context in error reports that shouldn't be inserted into the chain of error messages, such as the output oftracing_error::SpanTrace
.eyre
has accomplished this by adding a newErrorHandler
parameter to the primary dyn Error handling type. This approach has some downsides:anyhow!
just works. [[1]]eyre::Report
in a library interface where theErrorHandler
type is still selected by the user requires invasive use of generic parameters and breaks type inference even worse. [[2]]New Design
Most of these problems can be solved by using a Boxed trait object instead of a generic parameter. Type inference is no longer an issue and behaves exactly the same as in
anyhow
. The hook is global for your application so any library that exports ananyhow::Error
will still capture the type of context specified in the global hook, removing the need for generics in interfaces or conversions between handler types throughout the application.The downside of this design is the addition of a
Box
to theErrorImpl
type behind the thin pointer, adding an extra allocation to error construction. However, in the default case this hook should create a boxed dyn object from a unit type, which wont actually allocate anything and so should be essentially free (I hope).handler construction hook
This function is used to create the handler to be stored alongside or instead of the
Backtrace
. This function is called when theanyhow::Error
is first constructed, letting it capture context sensitive information such asbacktrace::Backtrace
or atracing_error::SpanTrace
. This function takes a reference to the inner error as an argument to allow it to do conditional capture of context such as aBacktrace
upon inspection of the wrapped error type.Any
trait boundThe
ReportHandler
trait requires that types that implement it support downcasting. This makes it possible to write extension traits for mutating the inner context. This lets store information like status codes, custom error report sections for stderr/stdout, suggestions, etc. This is necessary to implement aReportHandler
based oncolor-eyre
.One potential downside of this approach compared to the generic parameter is that the internals of these extension traits must rely upon downcasting that can fail, and must choose a handling strategy for when the context created by the global hook is different from the context they're written to downcast too, such as panicking or logging an warning indicating that the context couldn't be modified.
fn report
This fn provides the
Debug
implementation foranyhow::Error
. It takes theReportHandler
as it's &self parameter letting it access and render any context stored within the handler and it takes a reference to thedyn Error
stored withinanyhow::Error
to let it control how the chain of errors is displayed and to access other context captured by source errors intended for the error report itself, such asBacktraces
.Problems
fn backtrace(&self) -> Backtrace
Right now
anyhow::Error
guarantees that it will capture astd::backtrace::Backtrace
when it is available. While this interface is unstable this causes some significant issues.anyhow::Error
cannot delegate capturing thisBacktrace
to the handler because the handler could choose to not capture one, which would require anunwrap
infn backtrace
to maintain the same exterior interface.Additionally, if
anyhow::Error
continues to handle capturing the backtrace the hook and report printing functions cannot include theBacktrace
as one of their args, because this arg would not be available onstable
or even older versions oncestd::backtrace::Backtrace
has been stabilized. This means thatanyhow::Error
would need to handle rendering theBacktrace
it captures, preventing the handler from customizing the backtrace rendering with crates likecolor-backtrace
. I haven't come up with a good solution for this other than making a breaking change and removing thefn backtrace(&self) -> Backtrace
or changing it to return anOption
and adding a second function totrait ReportHandler
for accessing the inner backtrace if it exists.The text was updated successfully, but these errors were encountered: