witcher
Track and put down errors
I intend to either investigate and document the error handling solution I'll use for Rust or implement my own depending on my findings.
Table of Contents
Background
Rust has had a rough start with proper error handling. Failure
was the first attempt to fix the
error handling issues in Rust. Since that time the std::error::Error
trait has improved and now the
recommendation is to use anyhow and thiserror
both created by the same author. I still find the options lacking.
Requirements
From my perspective errors should capture enough meta data around a problem to give a developer a good chance of finding the error's origin without having to try and reproduce the problem. They should be convenient enough to work with that developers will actually use them. Finally they should add minimal overhead that will impact performance or developers won't use them.
This means errors:
- shouldn't require complicated configuration
- error handling should be as concise and terse as possible
- should to able to interact with and wrap other errors for aggregation
- provide a chaining of errors to provide context and detail
- should provide enough detail that the source of the error is evident
- provide optional tracing in certain modes to allow for source line discovery
Error Packages
anyhow
anyhow does a good job providing convenience and chaining of errors. You can combine anyhow and tracing together to make a decent solution.
Running the code in this section will give you a nicely formatted output:
Although anyhow
provides a chaining of contexts which is great and the simplicity of wrapping
errors to a common type which is two of the three areas for my minimal requirements it still failed
when it comes to tracing detail.
Fails to meet requirements:
- error detail is missing
- the simplified error tracing you'd find in something like the Golang errors package is missing
- the underlying error types are not printed out
- no good way to integrate the detailed error output with tracing json messaging formats
use Context;
use ;
use error;
tracing-error
tracing-error provides a way to
instrument errors with additional tracing information and is part of the venerable tracing
ecosystem from the tokio
project. This is one of the few projects that provides tracing information
in their error infrastructure and is really close to what I was looking for. The implementation
actually uses thiserror
Backtracing example:
- Clone the repo
- Runt the example
Fails to meet requirements:
- too much configuration overhead
- each function that participates in the error tracing needs to have tracing annotations
- instrumenting the error uses an extremely verbose function name
.in_current_span()?
- tracing information calls out the attribute location in the code not the actual code lines
- the project is still unreleased and in beta so hopefully that improves
thiserror
thiserror allows you to quickly create wrapper errors with an
enumeration of error variants which according to the documentation are interchangable with
std::error::Error
implementations written by hand. The crate makes is super simple to write error
boiler plate code. However there is a non-trivial amount of compilation overhead that comes with
this method that makes it a no go see the reddit discussion
Fails to meet requirements:
- too much overhead introduced during compilation to be worth while
- has no mechanism for getting tracing information