logerr 0.2.0

Seamless error type logging
Documentation
# 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 | anyhow | generic |
| ----------: | :-: | :----: | :-----: |
| 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