Skip to content

Commit

Permalink
Add rerun --strict: crash if any warning or error is logged
Browse files Browse the repository at this point in the history
Part of #1483
  • Loading branch information
emilk committed Apr 11, 2023
1 parent 49d5de8 commit 511d411
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 6 deletions.
5 changes: 5 additions & 0 deletions crates/re_log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ pub use {
setup::*,
};

/// Re-exports of other crates.
pub mod external {
pub use log;
}

/// Never log anything less serious than a `WARN` from these crates.
const CRATES_AT_WARN_LEVEL: [&str; 3] = [
// wgpu crates spam a lot on info level, which is really annoying
Expand Down
29 changes: 23 additions & 6 deletions crates/rerun/src/crash_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn install_panic_hook(_build_info: BuildInfo) {
let previous_panic_hook = std::panic::take_hook();

std::panic::set_hook(Box::new(move |panic_info: &std::panic::PanicInfo<'_>| {
let callstack = callstack_from("panicking::panic_fmt\n");
let callstack = callstack_from(&["panicking::panic_fmt\n"]);

let file_line = panic_info.location().map(|location| {
let file = anonymize_source_file_path(&std::path::PathBuf::from(location.file()));
Expand Down Expand Up @@ -210,21 +210,38 @@ fn install_signal_handler(build_info: BuildInfo) {
}

fn callstack() -> String {
callstack_from("install_signal_handler::signal_handler\n")
callstack_from(&["install_signal_handler::signal_handler\n"])
}
}

fn callstack_from(start_pattern: &str) -> String {
/// Get a nicely formatted callstack.
///
/// You can give this function a list of substrings to look for, e.g. names of functions.
/// If any of these substrings matches, anything before that is removed from the callstack.
/// For example:
///
/// ```
/// fn print_callstack() {
/// eprintln!("{}", callstack_from(&["print_callstack"]));
/// }
/// ```
pub fn callstack_from(start_patterns: &[&str]) -> String {
let backtrace = backtrace::Backtrace::new();
let stack = backtrace_to_string(&backtrace);

// Trim it a bit:
let mut stack = stack.as_str();

let start_patterns = start_patterns
.iter()
.chain(std::iter::once(&"callstack_from"));

// Trim the top (closest to the panic handler) to cut out some noise:
if let Some(offset) = stack.find(start_pattern) {
let prev_newline = stack[..offset].rfind('\n').map_or(0, |newline| newline + 1);
stack = &stack[prev_newline..];
for start_pattern in start_patterns {
if let Some(offset) = stack.find(start_pattern) {
let prev_newline = stack[..offset].rfind('\n').map_or(0, |newline| newline + 1);
stack = &stack[prev_newline..];
}
}

// Trim the bottom to cut out code that sets up the callstack:
Expand Down
41 changes: 41 additions & 0 deletions crates/rerun/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ struct Args {
#[clap(long)]
profile: bool,

/// Exit with a non-zero exit code if any warning or error is logged. Useful for tests.
#[clap(long)]
strict: bool,

/// An upper limit on how much memory the Rerun Viewer should use.
///
/// When this limit is used, Rerun will purge the oldest data.
Expand Down Expand Up @@ -187,6 +191,11 @@ where
return Ok(0);
}

if args.strict {
re_log::add_boxed_logger(Box::new(StrictLogger {})).expect("Failed to enter --strict mode");
re_log::info!("--strict mode: any warning or error will cause Rerun to panic.");
}

let res = if let Some(commands) = &args.commands {
match commands {
#[cfg(all(feature = "analytics"))]
Expand Down Expand Up @@ -539,3 +548,35 @@ pub fn setup_ctrl_c_handler() -> (tokio::sync::broadcast::Receiver<()>, Arc<Atom
.expect("Error setting Ctrl-C handler");
(receiver, shutdown_return)
}

// ----------------------------------------------------------------------------

use re_log::external::log;

struct StrictLogger {}

impl log::Log for StrictLogger {
fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
match metadata.level() {
log::Level::Error | log::Level::Warn => true,
log::Level::Info | log::Level::Debug | log::Level::Trace => false,
}
}

fn log(&self, record: &log::Record<'_>) {
let level = match record.level() {
log::Level::Error => "error",
log::Level::Warn => "warning",
log::Level::Info | log::Level::Debug | log::Level::Trace => return,
};

eprintln!("{level} logged in --strict mode: {}", record.args());
eprintln!(
"{}",
crate::crash_handler::callstack_from(&["log::__private_api_log"])
);
std::process::exit(1);
}

fn flush(&self) {}
}

0 comments on commit 511d411

Please sign in to comment.