shepmaster / snafu

Easily assign underlying errors into domain-specific errors while adding context
https://docs.rs/snafu/
Apache License 2.0
1.45k stars 61 forks source link

Option<snafu::Backtrace> handling should be configurable #201

Closed cyphar closed 4 years ago

cyphar commented 4 years ago

Right now, the only way to have runtime-controlled optional backtraces for some library or application is to use Option<snafu::Backtrace> and then the user must set RUST_BACKTRACE or RUST_LIB_BACKTRACE in order to enable it. While this does mean that the same UX for "getting a backtrace" is present for all snafu-based Rust programs, it has the major downside of making the UX feel strange for programs which are not necessarily related to Rust. For instance, a user may find it odd for a shared library (written in Rust) used by a C program to require you to set RUST_LIB_BACKTRACE=1 in the environment.

In addition, the fact it's set once and cannot be changed means that for long-running processes it's necessary to restart them in order to enable debugging -- when ideally you should be able to enable debugging after the program has been started and handled more than one error.

shepmaster commented 4 years ago

The functionality is configurable, just not via Option. You need to implement GenerateBacktrace for your type and then you can rely on whatever logic you want. An untested sketch:

use snafu::{Backtrace, GenerateBacktrace};
use std::sync::atomic::{AtomicBool, Ordering};

struct GlobalBacktrace(Option<Backtrace>);

static ENABLED: AtomicBool = AtomicBool::new(false);

impl GenerateBacktrace for GlobalBacktrace {
    fn generate() -> Self {
        Self(if ENABLED.load(Ordering::SeqCst) {
            Some(GenerateBacktrace::generate())
        } else {
            None
        })
    }

    fn as_backtrace(&self) -> Option<&Backtrace> {
        self.0.as_ref()
    }
}
cyphar commented 4 years ago

I will admit, I didn't think to implement GenerateBacktrace on a custom struct -- that should solve my problem. Thanks, and sorry for the noise.