common_telemetry/
panic_hook.rs1use std::panic;
16#[cfg(feature = "deadlock_detection")]
17use std::time::Duration;
18
19use backtrace::Backtrace;
20use lazy_static::lazy_static;
21use prometheus::*;
22
23lazy_static! {
24 pub static ref PANIC_COUNTER: IntCounter =
25 register_int_counter!("greptime_panic_counter", "panic_counter").unwrap();
26}
27
28pub fn set_panic_hook() {
29 let default_hook = panic::take_hook();
36 panic::set_hook(Box::new(move |panic| {
37 let backtrace = Backtrace::new();
38 let backtrace = format!("{backtrace:?}");
39 if let Some(location) = panic.location() {
40 tracing::error!(
41 message = %panic,
42 backtrace = %backtrace,
43 panic.file = location.file(),
44 panic.line = location.line(),
45 panic.column = location.column(),
46 );
47 } else {
48 tracing::error!(message = %panic, backtrace = %backtrace);
49 }
50 PANIC_COUNTER.inc();
51 default_hook(panic);
52 }));
53
54 #[cfg(feature = "deadlock_detection")]
55 let _ = std::thread::spawn(move || loop {
56 std::thread::sleep(Duration::from_secs(5));
57 let deadlocks = parking_lot::deadlock::check_deadlock();
58 if deadlocks.is_empty() {
59 continue;
60 }
61
62 tracing::info!("{} deadlocks detected", deadlocks.len());
63 for (i, threads) in deadlocks.iter().enumerate() {
64 tracing::info!("Deadlock #{}", i);
65 for t in threads {
66 tracing::info!("Thread Id {:#?}", t.thread_id());
67 tracing::info!("{:#?}", t.backtrace());
68 }
69 }
70 });
71}