Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar-ui

crates/gunnar-ui-server/src/captured.rs

//! A `tracing` subscriber writing into a buffer this module can read.
//!
//! Installed **globally and once**, because the audit lines are written from
//! whatever task the handler happens to be on and a thread-local default would
//! miss them. Every test in this binary then writes into it, which only makes
//! the negative assertion below stronger: the token must appear in no line any
//! of them produced.
//!
//! `pub(crate)` because there is now a second secret in this crate that must
//! never reach a log — the invite minted for a paid signup — and
//! `auth::signup`'s own negative uses this harness rather than a second copy of
//! it. Two spellings of "capture the log" is how one of them goes stale.
//! (Moved out of `mirroring` so a build without `forges` keeps it; AIRGAP 2026-10-25.)
use std::sync::{Mutex, OnceLock};

static LOG: OnceLock<std::sync::Arc<Mutex<Vec<u8>>>> = OnceLock::new();
static INSTALLED: std::sync::Once = std::sync::Once::new();

#[derive(Clone)]
struct Writer(std::sync::Arc<Mutex<Vec<u8>>>);

impl std::io::Write for Writer {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.0
            .lock()
            .expect("the log buffer")
            .extend_from_slice(buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

impl<'a> tracing_subscriber::fmt::MakeWriter<'a> for Writer {
    type Writer = Writer;
    fn make_writer(&'a self) -> Writer {
        self.clone()
    }
}

/// Install the capturing subscriber, once for the whole test binary.
///
/// A failure to install is not a failure of the test: `cargo test` may have
/// been run with another subscriber already in place, and in that case the
/// buffer stays empty and [`written`] returns nothing — which the caller
/// checks for rather than passing vacuously.
pub fn install() {
    INSTALLED.call_once(|| {
        let buffer = std::sync::Arc::new(Mutex::new(Vec::new()));
        let _ = LOG.set(std::sync::Arc::clone(&buffer));
        let subscriber = tracing_subscriber::fmt()
            .with_writer(Writer(buffer))
            .with_ansi(false)
            .with_max_level(tracing::Level::TRACE)
            .finish();
        let _ = tracing::subscriber::set_global_default(subscriber);
    });
}

/// Everything logged so far.
pub fn written() -> String {
    LOG.get()
        .map(|b| String::from_utf8_lossy(&b.lock().expect("the log buffer")).into_owned())
        .unwrap_or_default()
}