santh-tracing 0.2.0

Consistent tracing setup for CLI tools - stderr/JSON/file sinks, a secret-redacting writer, and operation spans
Documentation
//! Invariant: spans can be created and logged from multiple threads safely.

use santh_tracing::{init, with_op, LogLevel};
use std::thread;

#[test]
fn span_thread_safety() {
    let _lock = crate::support::INIT_LOCK.lock();
    let _guard = init("concurrent_tool", LogLevel::Info);

    let handles: Vec<_> = (0..10)
        .map(|i| {
            thread::spawn(move || {
                let op = format!("op_{i}");
                let op: &'static str = Box::leak(op.into_boxed_str());
                crate::support::capture_output(|| {
                    with_op(op, || {
                        santh_tracing::tracing::info!("thread {i}");
                    });
                })
            })
        })
        .collect();

    for (i, h) in handles.into_iter().enumerate() {
        let out = h.join().expect("Fix: thread panicked");
        assert!(
            out.contains(&format!("op=\"op_{i}\"")),
            "Fix: missing op for thread {i}"
        );
        assert!(
            out.contains(&format!("thread {i}")),
            "Fix: missing event for thread {i}"
        );
    }
}