fstdout-logger 0.2.0

An implementation of the log crate that logs to stdout and to an optional log file with configurable options.
Documentation

FStdout Logger

A simple and flexible dual-destination logger for Rust applications that implements the log crate's API.

Latest Version Documentation

Features

  • Log messages to both stdout and a file simultaneously
  • Configurable log levels (Trace, Debug, Info, Warn, Error)
  • Module-level log filtering with RUST_LOG support
  • Colored output for stdout (with different colors for each log level)
  • Plain text output for log files (no color codes)
  • Compact timestamps in stdout (only time, HH:MM:SS)
  • Complete timestamps in log files (includes date)
  • Optional file and line number information
  • Highly configurable via simple builder API
  • Compatible with the standard log crate macros

Installation

Add this to your Cargo.toml:

[dependencies]

fstdout-logger = "0.1.0"

log = "0.4"

The crate uses the following dependencies internally:

  • colored for terminal coloring
  • chrono for timestamp formatting
  • thiserror for error handling

Usage

Simple Usage

use fstdout_logger::init_logger;
use log::{debug, error, info, warn};

fn main() {
    // Initialize logger with defaults (colored output, Info level)
    if let Err(e) = init_logger(Some("application.log")) {
        eprintln!("Failed to initialize logger: {}", e);
        return;
    }

    // Now use the standard log macros
    info!("Application started");         // Blue
    debug!("This won't show by default"); // Suppressed (below Info level)
    warn!("Warning: resource usage high"); // Yellow
    error!("Failed to process item: {}", "invalid format"); // Red
}

Using Presets

For common use cases, presets are available:

use fstdout_logger::{init_development_logger, init_production_logger};
use log::{debug, error, info};

fn main() {
    // For development: Debug level with file info and colors
    init_development_logger(Some("dev.log")).expect("Failed to initialize logger");

    // Or for production: Info level without file info, concise timestamps
    // init_production_logger(Some("app.log")).expect("Failed to initialize logger");

    debug!("Debug info shows in development mode"); // Shows in development, hidden in production
    info!("Application running");
    error!("Something went wrong!");
}

Custom Configuration

For full control, use the configuration builder:

use fstdout_logger::{init_logger_with_config, LoggerConfig, LoggerConfigBuilder};
use log::{info, LevelFilter};

fn main() {
    // Create a custom configuration
    let config = LoggerConfig::builder()
        .level(LevelFilter::Info)
        .show_file_info(false)      // Hide file and line info for cleaner output
        .show_date_in_stdout(false) // Show only time in stdout (HH:MM:SS)
        .use_colors(true)           // Enable colored output
        .build();

    // Initialize with the custom config
    init_logger_with_config(Some("application.log"), config)
        .expect("Failed to initialize logger");

    info!("Customized logging experience!");
}

Using RUST_LOG Environment Variable

The logger supports the standard RUST_LOG environment variable for fine-grained control over log levels per module:

use fstdout_logger::init_logger_from_env;
use log::{debug, info, trace};

fn main() {
    // Initialize logger from RUST_LOG environment variable
    init_logger_from_env(Some("app.log"))
        .expect("Failed to initialize logger");

    // Logs will be filtered according to RUST_LOG
    trace!("This is a trace message");
    debug!("This is a debug message");
    info!("This is an info message");
}

Set RUST_LOG when running your application:

# Set global log level to debug

RUST_LOG=debug cargo run


# Set specific module to trace, others to warn

RUST_LOG=my_crate::network=trace,warn cargo run


# Multiple module filters

RUST_LOG=my_crate::module_a=debug,my_crate::module_b=trace,info cargo run


# On Windows (PowerShell)

$env:RUST_LOG="debug" ; cargo run

$env:RUST_LOG="my_crate::network=trace,warn" ; cargo run

Supported RUST_LOG formats:

  • debug - Set default level to debug
  • my_crate=debug - Set specific crate to debug
  • my_crate::module=trace - Set specific module to trace
  • my_crate=debug,other_crate::module=trace - Multiple module filters
  • my_crate::module=trace,warn - Module-specific level with global default

Note: init_logger() automatically reads RUST_LOG and LOG_LEVEL if they are set!

Using LOG_LEVEL Numeric Format

For simpler configuration, you can use LOG_LEVEL with numeric values:

use fstdout_logger::{init_logger_with_config, LoggerConfig};
use log::LevelFilter;
use std::env;

fn main() {
    // Parse LOG_LEVEL environment variable
    let log_level = match env::var("LOG_LEVEL") {
        Ok(level) => match level.parse::<u8>() {
            Ok(level) => match level {
                0 => LevelFilter::Off,
                1 => LevelFilter::Error,
                2 => LevelFilter::Warn,
                3 => LevelFilter::Info,
                4 => LevelFilter::Debug,
                _ => LevelFilter::Trace,
            },
            Err(_) => LevelFilter::Warn,
        },
        Err(_) => LevelFilter::Warn,
    };

    // Configure logger with module filters
    if let Err(e) = init_logger_with_config(
        Some("app.log"),
        LoggerConfig::builder()
            .show_file_info(cfg!(debug_assertions))
            .level(log_level)
            .filter_module("rustls", LevelFilter::Error)
            .filter_module("tokio_rustls", LevelFilter::Error)
            .build(),
    ) {
        eprintln!("Failed to initialize logger: {}", e);
        std::process::exit(1);
    }
}

LOG_LEVEL values:

  • 0 = Off
  • 1 = Error
  • 2 = Warn
  • 3 = Info (default)
  • 4 = Debug
  • 5+ = Trace

Set LOG_LEVEL when running:

LOG_LEVEL=4 cargo run  # Debug level


# On Windows (PowerShell)

$env:LOG_LEVEL="4" ; cargo run

Output Format

Terminal Output (Default)

By default, terminal output shows a concise format with colors:

[HH:MM:SS LEVEL file:line] Message

For example:

[14:23:45 INFO main.rs:25] Application started

Log messages are colored according to log level:

  • ERROR: Bold Red
  • WARN: Bold Yellow
  • INFO: Bold Blue
  • DEBUG: Green
  • TRACE: Default terminal color

The timestamp and file information are displayed in a dimmed color to make the log level and message stand out.

File Output (Always Plain Text)

Log messages in files always include the date and file information:

[YYYY-MM-DD HH:MM:SS LEVEL file:line] Message

For example:

[2023-05-15 14:23:45 INFO main.rs:25] Application started

Configuration Options

You can configure the output format through the LoggerConfig:

  • show_file_info - Toggle display of file and line information
  • show_date_in_stdout - Toggle inclusion of date in terminal output
  • use_colors - Enable or disable colored output in terminal
  • level - Set the minimum log level to display

Run Examples

The crate includes examples that demonstrate its usage:

# Simple logging with custom configuration

cargo run --example basic_usage


# Stdout-only logging with minimal format

cargo run --example stdout_only


# Comparing different color and format options

cargo run --example color_options


# Demonstrating production vs development presets

cargo run --example production


# Module-level filtering with RUST_LOG

RUST_LOG=debug cargo run --example module_filters

RUST_LOG=module_filters::network=trace,warn cargo run --example module_filters


# Numeric log levels with LOG_LEVEL

LOG_LEVEL=4 cargo run --example log_level_numeric

Full API

The logger provides several initialization functions for different use cases:

  • init_logger(path) - Simple initialization with defaults
  • init_logger_with_level(path, level) - Set a specific log level
  • init_logger_with_config(path, config) - Use a custom configuration
  • init_logger_from_env(path) - Initialize from RUST_LOG environment variable
  • init_production_logger(path) - Use production-optimized settings
  • init_development_logger(path) - Use development-optimized settings
  • init_stdout_logger(config) - Initialize a stdout-only logger
  • init_simple_stdout_logger(level) - Initialize a minimal stdout-only logger

License

This project is licensed under the MIT License - see the LICENSE file for details.