nonblocking-logger 0.3.0

A high-performance library with format string support
Documentation
use nonblocking_logger::{LogLevel, Logger, log_str_to_multiple};
use std::io;
use std::path::Path;

/// Get the test directory path for temporary files
fn get_test_dir() -> io::Result<String> {
    let test_dir = "target/tests";

    if !Path::new(test_dir).exists() {
        std::fs::create_dir_all(test_dir)?;
    }

    Ok(test_dir.to_string())
}

/// Get a test file path in the test directory
fn get_test_file_path(filename: &str) -> io::Result<String> {
    let test_dir = get_test_dir()?;
    let timestamp = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_nanos();

    let safe_filename = filename.replace('/', "_").replace('\\', "_");
    Ok(format!("{}/test_{}_{}", test_dir, timestamp, safe_filename))
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Basic Usage ===");
    let logger = Logger::new().stdout();
    logger.info("Hello, world!")?;
    logger.warning("This is a warning")?;
    logger.error("This is an error")?;

    println!("\n=== Custom Time Format ===");
    let logger = Logger::new().time_format("%H:%M:%S").stdout();
    logger.info("With timestamp")?;

    println!("\n=== Multiple Targets ===");
    let test_file = get_test_file_path("example.log")?;
    let loggers = vec![Logger::new().stdout(), Logger::new().file(&test_file)?];
    log_str_to_multiple(&loggers, LogLevel::Info, "Logs to both stdout and file")?;

    println!("\n=== Custom Format ===");
    let logger = Logger::new()
        .format_for_level(LogLevel::Error, "🚨 ERROR: {message}".to_string())
        .format_for_level(LogLevel::Warning, "⚠️  WARN: {message}".to_string())
        .stdout();
    logger.error("Something went wrong")?;
    logger.warning("This is a warning")?;

    println!("\n=== Multiple Loggers ===");
    let loggers = vec![
        Logger::new().stdout().time_format("%H:%M:%S"),
        Logger::new().stderr().no_time_prefix(),
    ];

    log_str_to_multiple(
        &loggers,
        LogLevel::Info,
        "This goes to both stdout and stderr",
    )?;

    println!("\n=== Log Level Filtering ===");
    let logger = Logger::with_level(LogLevel::Warning)
        .stdout()
        .no_time_prefix();

    logger.debug("This debug message won't appear")?;
    logger.info("This info message won't appear")?;
    logger.warning("This warning will appear")?;
    logger.error("This error will appear")?;

    println!("\n=== Utility Functions ===");
    let loggers = vec![Logger::new().stdout(), Logger::new().stderr()];
    log_str_to_multiple(
        &loggers,
        LogLevel::Info,
        "This goes to both stdout and stderr using utility function",
    )?;

    Ok(())
}