ticklog 0.1.0

A fast, minimal logging library for Rust, designed for performance-critical applications, e.g. high-frequency trading.
Documentation
//! End-to-end: the logging macros produce formatted lines at the sink.
//!
//! This is an integration test (its own binary), so the process-global
//! `REGISTRY` starts fresh and `build()` succeeds exactly once -- every
//! assertion runs under a single guard.

use std::sync::{Arc, Mutex};

use ticklog::{debug, error, info, trace, warn, Level, LogSink};

/// A sink that records every accepted line, for assertions after shutdown.
struct CaptureSink {
    lines: Arc<Mutex<Vec<String>>>,
}

impl LogSink for CaptureSink {
    fn accept(&mut self, line: &[u8], _level: Level) -> std::io::Result<()> {
        self.lines
            .lock()
            .unwrap()
            .push(String::from_utf8_lossy(line).into_owned());
        Ok(())
    }
}

#[test]
fn macros_produce_formatted_lines_in_order() {
    let lines = Arc::new(Mutex::new(Vec::new()));
    let sink = CaptureSink {
        lines: Arc::clone(&lines),
    };

    let guard = ticklog::builder()
        .sink(sink)
        .max_level(Level::Trace) // admit every level
        .build()
        .expect("first build in a fresh process must succeed");

    // One producer thread (this one) writes to a single ring, so the drain
    // emits these in the order they were logged.
    info!("plain message");
    warn!("value = {}", 42u64);
    error!("{} and {}", "a", "b");
    debug!("dbg {}", true);
    trace!("trc {}", 3.5f64);

    // Dropping the guard flushes and joins the drain, so every line is present.
    drop(guard);

    let captured = lines.lock().unwrap();
    assert_eq!(captured.len(), 5, "expected five lines, got {captured:?}");

    assert!(captured[0].contains(" INFO "));
    assert!(captured[0].ends_with("plain message"));
    assert!(captured[1].contains(" WARN "));
    assert!(captured[1].ends_with("value = 42"));
    assert!(captured[2].contains(" ERROR "));
    assert!(captured[2].ends_with("a and b"));
    assert!(captured[3].contains(" DEBUG "));
    assert!(captured[3].ends_with("dbg true"));
    assert!(captured[4].contains(" TRACE "));
    assert!(captured[4].ends_with("trc 3.5"));

    // Every line carries this test file's source location (default metadata).
    assert!(captured[0].contains("tests/logging.rs:"));
}