1#![doc = include_str!("../README.md")]
2
3use std::{backtrace, panic, thread};
4
5pub struct Configuration {
6 pub force_capture: bool,
11
12 pub keep_original_hook: bool,
15}
16
17impl Default for Configuration {
18 fn default() -> Self {
19 Self {
20 force_capture: false,
21 keep_original_hook: true,
22 }
23 }
24}
25
26pub fn initialize_hook(config: Configuration) {
27 let original_hook = if config.keep_original_hook {
28 Some(panic::take_hook())
29 } else {
30 None
31 };
32 panic::set_hook(Box::new(move |info| {
33 let thread_name = thread::current()
34 .name()
35 .unwrap_or("<unnamed thread>")
36 .to_owned();
37
38 let location = if let Some(panic_location) = info.location() {
39 format!(
40 "{}:{}:{}",
41 panic_location.file(),
42 panic_location.line(),
43 panic_location.column()
44 )
45 } else {
46 "<unknown location>".to_owned()
47 };
48 let message = info.payload().downcast_ref::<&str>().unwrap_or(&"");
49
50 let backtrace = if config.force_capture {
51 backtrace::Backtrace::force_capture()
52 } else {
53 backtrace::Backtrace::capture()
54 };
55
56 log::error!("thread '{thread_name}' panicked at {location}:\n{message}\nstack bactrace:\n{backtrace}");
57
58 if let Some(original_hook) = &original_hook {
59 original_hook(info);
60 }
61 }));
62}