nonblocking-logger 0.3.0

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

/// 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))
}

/// Example demonstrating direct logging system
///
/// This example shows how the direct logging system works with multiple threads
/// and demonstrates its performance characteristics.
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Direct Logging System Demo ===");

    let stdout_logger = Logger::new().stdout();
    let stderr_logger = Logger::new().stderr();
    let test_file = get_test_file_path("direct_demo.log")?;
    let file_logger = Logger::new().file(&test_file)?;

    println!("\n1. Basic logging with different targets:");
    stdout_logger.info("This goes to stdout")?;
    stderr_logger.warning("This goes to stderr")?;
    file_logger.info("This goes to file")?;

    println!("\n2. Multi-threaded logging demonstration:");

    let handles: Vec<_> = (0..5)
        .map(|i| {
            let logger = Logger::new().stdout();
            thread::spawn(move || {
                for j in 0..3 {
                    logger.info(&format!("Thread {} - Message {}", i, j))?;
                    thread::sleep(Duration::from_millis(10));
                }
                Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
            })
        })
        .collect();

    for handle in handles {
        handle
            .join()
            .unwrap()
            .map_err(|e| format!("Thread error: {:?}", e))?;
    }

    println!("\n3. Performance test (direct logging):");

    let start = std::time::Instant::now();
    for i in 0..1000 {
        stdout_logger.info(&format!("Performance test message {}", i))?;
    }
    let direct_time = start.elapsed();

    println!(
        "  Direct logging time for 1000 messages: {:?}",
        direct_time
    );

    println!("\n4. Lazy logging with expensive computation:");

    let expensive_logger = Logger::with_level(LogLevel::Info).stdout();

    expensive_logger.info_lazy(|| {
        println!("  🔥 Computing expensive result...");
        thread::sleep(Duration::from_millis(50));
        "Expensive computation completed".to_string()
    })?;

    expensive_logger.debug_lazy(|| {
        println!("  This should not appear!");
        "This debug message should not be computed".to_string()
    })?;

    println!("\n5. Custom formats and time formats:");

    let custom_logger = Logger::new()
        .time_format("%H:%M:%S%.3f")
        .format_for_level(LogLevel::Error, "🚨 ERROR: {message}".to_string())
        .format_for_level(LogLevel::Warning, "⚠️  WARN: {message}".to_string())
        .format_for_level(LogLevel::Info, "ℹ️  INFO: {message}".to_string())
        .stdout();

    custom_logger.info("Custom formatted info message")?;
    custom_logger.warning("Custom formatted warning message")?;
    custom_logger.error("Custom formatted error message")?;

    println!("\n6. Demonstrating concurrent logging:");

    let concurrent_logger = Logger::new().stdout();

    let log_handle = thread::spawn(move || {
        for i in 0..10 {
            concurrent_logger.info(&format!("Background logging {}", i))?;
            thread::sleep(Duration::from_millis(100));
        }
        Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
    });

    println!("  Main thread doing other work...");
    for i in 0..5 {
        println!("  Main thread work item {}", i);
        thread::sleep(Duration::from_millis(50));
    }

    log_handle
        .join()
        .unwrap()
        .map_err(|e| format!("Logging thread error: {:?}", e))?;

    println!("\n7. Final messages demonstration:");

    stdout_logger.info("Application is shutting down...")?;
    stderr_logger.warning("Final warning message")?;
    file_logger.info("Final log entry")?;

    thread::sleep(Duration::from_millis(100));

    println!("\nLogging complete. Check '{}' for file output.", test_file);
    println!("Note: Direct logging provides fast, synchronous output without background threads.");

    Ok(())
}