# logerr
Seamless error type logging.
## What does it do?
`logerr` aims to make logging errors as part of a `std::result::Result` easy
and obstruction-free. It provides a trait, `LoggableError`, that is implemented
on a rich variety of common `Result` variants. All the traits functions share
the special property that they **pass through the `Result` type unmodified**.
This way, regular error handling is not obstructed in any way, and logging can
happen while you're "on the go" handling errors.
## How to use it
Once you have a `Result` with a supported error type, you just do:
```rust
use anyhow::{anyhow, Context};
use logerr::LoggableError; // Must include to get access to trait functions
fn main() {
Err(anyhow!("an error occured"))
.context("this is just a demo")
.to_stderr() // <-- Magic!
.unwrap()
}
```
There are various feature flags that control the behavior of logging. By
default, `LoggableError` uses a generic implementation over all error types
implementing [`Error`][std_error] and prints errors using their `Display` impl,
printing an error chain if `Error::source()` is implemented.
If you want to make use of more advanced features, or add special
implementations for your own error types (including custom logging), disable
the default features and implement the trait yourself.
## Feature flags
### Feature compatibility matrix
Below you see a matrix representation of the features that can safely be
combined with each other. An `X` means that the features can be combined.
| log | | X | X |
| anyhow | X | | |
| generic | X | | |
### Choosing which features to use
> **I only want to log errors!**
In this case the default features (`log`, `generic`) are very likely sufficient
for you
> **I want to bring my own error formatting, completely!**
This is currently only possible for error types that you or your code owns (Due
to the orphan rule). In this case, forego all default features and implement
the `LoggableError` trait yourself. You can have a look at the source code if
you need inspiration.
> **I'm using anyhow for all my error handling!**
Use the `anyhow` feature flag, and you're good to go.
### `log`
Pulls in [the log crate][310] and adds a default implementation for `to_log`
that prints the error to `log::error!`.
*Note*: The logged message will not contain module information about the module
where it was invoked. This is a shortcoming of the Rust language and will be
fixed once [#87417](https://github.com/rust-lang/rust/issues/87417) is merged.
### `anyhow`
Pulls in [the anyhow crate][320] and adds an implementation specifically for
`anyhow::Result` (i.e. `Result<_, anyhow::Error`) that prints the whole error
chain with the default `anyhow` Debug formatting. Your application must use the
`anyhow::Result` type for this to work
### `generic`
Adds a generic implementation of the `LoggableError` trait for all error types
that implement the [`Error`][std_error] trait. The result looks like this:
```
ERROR: an error occured
because: something bad happened
because: file doesn't exist
```
The root cause is the last error printed.
[310]: https://crates.io/crates/log
[320]: https://crates.io/crates/anyhow
[std_error]: https://doc.rust-lang.org/stable/std/error/trait.Error.html