use backtrace::{Backtrace, BacktraceFmt, BytesOrWideString, PrintFmt};
use std::fmt;
pub fn setup() {
std::panic::set_hook(Box::new(|panic| {
let backtrace = BacktraceFormatter(Backtrace::new());
if let Some(location) = panic.location() {
tracing::error!(
message = %panic,
panic.file = location.file(),
panic.line = location.line(),
panic.column = location.column(),
panic.backtrace = format!("{backtrace}"),
);
} else {
tracing::error!(
message = %panic,
panic.backtrace = format!("{backtrace}"),
);
}
}));
}
struct BacktraceFormatter(Backtrace);
impl fmt::Display for BacktraceFormatter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let cwd = std::env::current_dir();
let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| {
let path = path.into_path_buf();
if let Ok(cwd) = &cwd {
if let Ok(suffix) = path.strip_prefix(cwd) {
return fmt::Display::fmt(&suffix.display(), fmt);
}
}
fmt::Display::fmt(&path.display(), fmt)
};
let mut f = BacktraceFmt::new(f, PrintFmt::Short, &mut print_path);
f.add_context()?;
for (frame, _) in backtrace_ext::short_frames_strict(&self.0) {
f.frame().backtrace_frame(frame)?;
}
f.finish()
}
}