From 449cefd5c99462373d927e08d1ebdc9541889caa Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Wed, 14 Mar 2018 18:22:18 +0000 Subject: [PATCH] hook to send panics and stacktraces to logs as well as stdout (#775) --- util/Cargo.toml | 1 + util/src/lib.rs | 1 + util/src/logger.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/util/Cargo.toml b/util/Cargo.toml index d81e6974..34538c58 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -10,6 +10,7 @@ slog = { version = "^2.0.12", features = ["max_level_trace", "release_max_level_ slog-term = "^2.2.0" slog-async = "^2.1.0" lazy_static = "~0.2.8" +backtrace = "^0.3.5" byteorder = "^1.0" rand = "^0.3" serde = "~1.0.8" diff --git a/util/src/lib.rs b/util/src/lib.rs index 9104d020..5a5006fe 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -21,6 +21,7 @@ #![deny(unused_mut)] #![warn(missing_docs)] +extern crate backtrace; extern crate byteorder; extern crate rand; #[macro_use] diff --git a/util/src/logger.rs b/util/src/logger.rs index 0bb0c342..28989ffd 100644 --- a/util/src/logger.rs +++ b/util/src/logger.rs @@ -19,6 +19,9 @@ use slog::{Discard, Drain, Duplicate, Level, LevelFilter, Logger}; use slog_term; use slog_async; +use backtrace::Backtrace; +use std::{panic, thread}; + use types::{LogLevel, LoggingConfig}; fn convert_log_level(in_level: &LogLevel) -> Level { @@ -89,6 +92,7 @@ pub fn init_logger(config: Option) { *was_init_ref = true; // .. allow logging, having ensured that paths etc are immutable } + send_panic_to_log(); } /// Initializes the logger for unit and integration tests @@ -100,4 +104,46 @@ pub fn init_test_logger() { let mut config_ref = LOGGING_CONFIG.lock().unwrap(); *config_ref = LoggingConfig::default(); *was_init_ref = true; + send_panic_to_log(); +} + +/// hook to send panics to logs as well as stderr +fn send_panic_to_log() { + panic::set_hook(Box::new(|info| { + let backtrace = Backtrace::new(); + + let thread = thread::current(); + let thread = thread.name().unwrap_or("unnamed"); + + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(s) => *s, + None => match info.payload().downcast_ref::() { + Some(s) => &**s, + None => "Box", + }, + }; + + match info.location() { + Some(location) => { + error!( + LOGGER, + "thread '{}' panicked at '{}': {}:{}{:?}", + thread, + msg, + location.file(), + location.line(), + backtrace + ); + } + None => error!( + LOGGER, + "thread '{}' panicked at '{}'{:?}", thread, msg, backtrace + ), + } + //also print to stderr + eprintln!( + "Thread '{}' panicked with message:\n\"{}\"\nSee grin.log for further details.", + thread, msg + ); + })); }