logerr 0.1.0

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

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!

There are various feature flags that control the behavior of logging. By
default, `LoggableError` uses a generic implementation over all error types
implementing `Debug` and uses a debug print statement (`{:#?}`) to perform the

If you want to make use of more advanced features, or add special
implementations for your own error types (including custom logging), refer to
the feature flags below.

## 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 | std\_errors |
| ----------: | :-: | :----: | :-----: | :---------: |
| log         |     | X      | X       | X           |
| anyhow      | X   |        |         | X           |
| generic     | X   |        |         |             |
| std\_errors | X   | 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 want any formatting for `std` errors and add my own errors, too!**

Use the `std_errors` feature flag and implement the `LoggableError` trait for
all other error types you need.

> **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!`.

### `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 like this:

ERROR: an error occured
because: something bad happened
because: file doesn't exist

The root error is the last one printed.

- Your application must use the `anyhow::Result` type for this to work
- **This is mutually exclusive with the following features:**
    - `generic`

### `generic`

Adds a generic implementation of the `LoggableError` trait for all error types
that implement the `Debug` trait.

- **This is mutually exclusive with the following features:**
    - `anyhow`
    - `std_errors`

### `std_errors`

Adds implementations of the `LoggableError` trait to all error types from the
`std` library.

[310]: https://crates.io/crates/log
[320]: https://crates.io/crates/anyhow