Perfect color-eyre
color-eyre provides advanced ways to obtain BACKTRACE and SPANTRACE and is hard to ignore.
Let’s extend the official example by adding hooq’s pseudo trace.
Create a new project and set the following in Cargo.toml (replace hooq with the latest version):
[features]
default = ["capture-spantrace"]
capture-spantrace = []
[dependencies]
color-eyre = "0.6.5"
hooq = { path = "../../hooq" } # Please rewrite `hooq = "*"`
tracing = "0.1.43"
tracing-error = "0.2.1"
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
We want color_eyre::eyre::WrapErr instead of ::eyre::WrapErr, so place hooq.toml next to Cargo.toml to override the import. Other settings inherit from the built‑in eyre flavor.
[eyre]
trait_uses = ["color_eyre::eyre::WrapErr"]
Write main.rs. use hooq::hooq; and annotate #[hooq(eyre)] above #[instrument] (we also add .without_time() to stabilize snapshots).
use color_eyre::Section;
use color_eyre::eyre::{Report, WrapErr};
use hooq::hooq;
use tracing::{info, instrument};
#[hooq(eyre)]
#[instrument]
fn main() -> Result<(), Report> {
#[cfg(feature = "capture-spantrace")]
install_tracing();
color_eyre::install()?;
read_config()
}
#[cfg(feature = "capture-spantrace")]
fn install_tracing() {
use tracing_error::ErrorLayer;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{EnvFilter, fmt};
let fmt_layer = fmt::layer().with_target(false).without_time();
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.with(ErrorLayer::default())
.init();
}
#[hooq(eyre)]
#[instrument]
fn read_file(path: &str) -> Result<(), Report> {
info!("Reading file");
std::fs::read_to_string(path).map(drop)
}
#[hooq(eyre)]
#[instrument]
fn read_config() -> Result<(), Report> {
read_file("fake_file")
.wrap_err("Unable to read config")
.suggestion("try using a file that exists next time")
}
Run with RUST_LIB_BACKTRACE=1 to also see the BACKTRACE:
Error:
0: [mdbook-source-code/recipe-color-eyre/src/main.rs:14:5]
14> read_config()
|
1: [mdbook-source-code/recipe-color-eyre/src/main.rs:45:5]
45> read_file("fake_file")
46| .wrap_err("Unab..nfig")
47| .suggestion("try ..time")
|
2: Unable to read config
3: [mdbook-source-code/recipe-color-eyre/src/main.rs:39:5]
39> std::fs::read_to_string(path).map(drop)
|
4: No such file or directory (os error 2)
Location:
mdbook-source-code/recipe-color-eyre/src/main.rs:39
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
0: recipe_color_eyre::read_file with path="fake_file"
at mdbook-source-code/recipe-color-eyre/src/main.rs:36
1: recipe_color_eyre::read_config
at mdbook-source-code/recipe-color-eyre/src/main.rs:43
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⋮ 4 frames hidden ⋮
5: <E as eyre::context::ext::StdError>::ext_report::h0e9fcf40b567f05e
at /home/USER/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/eyre-0.6.12/src/context.rs:26
⋮ 1 frame hidden ⋮
7: recipe_color_eyre::read_file::h74782b4bb409e5a9
at /home/USER/workspace/hooq/mdbook-source-code/recipe-color-eyre/src/main.rs:39
8: recipe_color_eyre::read_config::h8139da57eb93337e
at /home/USER/workspace/hooq/mdbook-source-code/recipe-color-eyre/src/main.rs:45
9: recipe_color_eyre::main::h9c27f45de169a3be
at /home/USER/workspace/hooq/mdbook-source-code/recipe-color-eyre/src/main.rs:14
10: core::ops::function::FnOnce::call_once::h724113526cc98cab
at /home/USER/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250
11: std::sys::backtrace::__rust_begin_short_backtrace::h9e20a34286867e4d
at /home/USER/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:158
⋮ 14 frames hidden ⋮
Suggestion: try using a file that exists next time
Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering.
Run with RUST_BACKTRACE=full to include source snippets.
This is likely the most detailed output.