use backtrace::Backtrace; use eyre::EyreHandler; use std::error::Error; use std::{fmt, iter}; fn main() -> eyre::Result<()> { // Install our custom eyre report hook for constructing our custom Handlers install().unwrap(); // construct a report with, hopefully, our custom handler! let mut report = eyre::eyre!("hello from custom error town!"); // manually set the custom msg for this report after it has been constructed if let Some(handler) = report.handler_mut().downcast_mut::() { handler.custom_msg = Some("you're the best users, you know that right???"); } // print that shit!! Err(report) } // define a handler that captures backtraces unless told not to fn install() -> Result<(), impl Error> { let capture_backtrace = std::env::var("RUST_BACKWARDS_TRACE") .map(|val| val != "0") .unwrap_or(true); let hook = Hook { capture_backtrace }; eyre::set_hook(Box::new(move |e| Box::new(hook.make_handler(e)))) } struct Hook { capture_backtrace: bool, } impl Hook { fn make_handler(&self, _error: &(dyn Error + 'static)) -> Handler { let backtrace = if self.capture_backtrace { Some(Backtrace::new()) } else { None }; Handler { backtrace, custom_msg: None, } } } struct Handler { // custom configured backtrace capture backtrace: Option, // customizable message payload associated with reports custom_msg: Option<&'static str>, } impl EyreHandler for Handler { fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { return fmt::Debug::fmt(error, f); } let errors = iter::successors(Some(error), |error| (*error).source()); for (ind, error) in errors.enumerate() { write!(f, "\n{:>4}: {}", ind, error)?; } if let Some(backtrace) = self.backtrace.as_ref() { writeln!(f, "\n\nBacktrace:\n{:?}", backtrace)?; } if let Some(msg) = self.custom_msg.as_ref() { writeln!(f, "\n\n{}", msg)?; } Ok(()) } }