1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
//! Panic handler support.
//!
//! **Feature:** `with_panic` (enabled by default)
//!
//! A panic handler can be installed that will automatically dispatch all errors
//! to Sentry that are caused by a panic.
//!
//! # Configuration
//!
//! ```no_run
//! use sentry::integrations::panic::register_panic_handler;
//! register_panic_handler();
//! ```
//!
//! Additionally panics are forwarded to the previously registered panic hook.
use std::panic;
use api::protocol::{Event, Exception, Level};
use backtrace_support::current_stacktrace;
use hub::Hub;
/// Extract the message of a panic.
pub fn message_from_panic_info<'a>(info: &'a panic::PanicInfo) -> &'a str {
match info.payload().downcast_ref::<&'static str>() {
Some(s) => *s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => &s[..],
None => "Box<Any>",
},
}
}
/// Creates an event from the given panic info.
///
/// The stacktrace is calculated from the current frame.
pub fn event_from_panic_info(info: &panic::PanicInfo) -> Event<'static> {
let msg = message_from_panic_info(info);
Event {
exception: vec![Exception {
ty: "panic".into(),
value: Some(msg.to_string()),
stacktrace: current_stacktrace(),
..Default::default()
}].into(),
level: Level::Fatal,
..Default::default()
}
}
/// A panic handler that sends to Sentry.
///
/// This panic handler report panics to Sentry. It also attempts to prevent
/// double faults in some cases where it's known to be unsafe to invoke the
/// Sentry panic handler.
pub fn panic_handler(info: &panic::PanicInfo) {
Hub::with_active(|hub| {
hub.capture_event(event_from_panic_info(info));
});
}
/// Registes the panic handler.
///
/// This registers the panic handler (`panic_handler`) as panic hook and
/// dispatches automatically to the one that was there before.
///
/// ```
/// use sentry::integrations::panic::register_panic_handler;
/// register_panic_handler();
/// ```
pub fn register_panic_handler() {
let next = panic::take_hook();
panic::set_hook(Box::new(move |info| {
panic_handler(info);
next(info);
}));
}