shotover/
tracing_panic_handler.rs1use backtrace::{Backtrace, BacktraceFmt, BytesOrWideString, PrintFmt};
2use std::fmt;
3
4pub fn setup() {
5 std::panic::set_hook(Box::new(|panic| {
6 let backtrace = BacktraceFormatter(Backtrace::new());
7 if let Some(location) = panic.location() {
9 tracing::error!(
10 message = %panic,
11 panic.file = location.file(),
12 panic.line = location.line(),
13 panic.column = location.column(),
14 panic.backtrace = format!("{backtrace}"),
15 );
16 } else {
17 tracing::error!(
18 message = %panic,
19 panic.backtrace = format!("{backtrace}"),
20 );
21 }
22 }));
23}
24
25struct BacktraceFormatter(Backtrace);
31
32impl fmt::Display for BacktraceFormatter {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 let cwd = std::env::current_dir();
40 let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| {
41 let path = path.into_path_buf();
42 if let Ok(cwd) = &cwd {
43 if let Ok(suffix) = path.strip_prefix(cwd) {
44 return fmt::Display::fmt(&suffix.display(), fmt);
45 }
46 }
47 fmt::Display::fmt(&path.display(), fmt)
48 };
49
50 let mut f = BacktraceFmt::new(f, PrintFmt::Short, &mut print_path);
51 f.add_context()?;
52 for (frame, _) in backtrace_ext::short_frames_strict(&self.0) {
53 f.frame().backtrace_frame(frame)?;
54 }
55 f.finish()
56 }
57}