pub fn set_hook(
hook: Box<dyn Fn(&(dyn StdError + 'static)) -> Box<dyn EyreHandler> + Sync + Send + 'static>,
) -> Result<(), InstallError>
Expand description
Install the provided error hook for constructing EyreHandlers when converting Errors to Reports
§Details
To customize the format and content of error reports from eyre
you must
first define a new EyreHandler
type to capture and store the extra context
and to define the format of how to display the chain of errors and this
stored context. Once this type has been defined you must also define a global
hook used to construct these handlers whenever Report
s are constructed.
§Examples
ⓘ
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>() {
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<Backtrace>,
// 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(())
}
}