#logging #logging-macro #file-logger #macro

log-easy

Easy to use file logger with log levels and global logging macros

2 releases

Uses new Rust 2024

0.1.1 Feb 6, 2026
0.1.0 Feb 5, 2026

#458 in Debugging

MIT/Apache

15KB
182 lines

log-easy

Crates.io Docs.rs License: MIT OR Apache-2.0

Easy-to-use file logger that writes messages in a simple, readable format. Built for straightforward file logging with minimal setup.

Installation

[!INFO] Minimum supported Rust version (MSRV): 1.85

Add this to your Cargo.toml:

[dependencies]
log-easy = "0.1"

Features

  • Log levels: Trace, Debug, Info, Warn, Error
  • Global macros for ergonomic logging (info!, warn!, etc.)
  • Instance-based API for explicit control
  • Minimal dependencies

Log Format

Each entry is written as:

[YYYY-MM-DD HH:MM:SS][LOG_LEVEL] Message

Quick Start (Global Logger + Macros)

use log_easy::{error, info, init_with, warn, LogLevel, Logger};

fn main() -> std::io::Result<()> {
    init_with(Logger::new("app.log").with_level(LogLevel::Info))?;

    info!("Application started");
    warn!("This is a warning");
    error!("Something went wrong");

    Ok(())
}

[!NOTE] Global macros require init or init_with to be called once before use.

Instance Logger (No Globals)

use log_easy::{LogLevel, Logger};

fn main() -> std::io::Result<()> {
    let logger = Logger::new("app-instance.log").with_level(LogLevel::Debug);

    logger.debug("Instance logger ready");
    logger.info("Application started");

    Ok(())
}

Formatting Messages

Macros accept formatting arguments like println!:

use log_easy::{info, init_with, LogLevel, Logger};

fn main() -> std::io::Result<()> {
    init_with(Logger::new("app.log").with_level(LogLevel::Info))?;

    let user = "alice";
    let id = 42;
    info!("user={} id={}", user, id);

    Ok(())
}

Instance methods accept a preformatted string:

use log_easy::{LogLevel, Logger};

fn main() -> std::io::Result<()> {
    let logger = Logger::new("app.log").with_level(LogLevel::Info);

    logger.info(&format!("user={} id={}", "alice", 42));

    Ok(())
}

Log Levels

Messages below the configured level are ignored.

use log_easy::{LogLevel, Logger};

let logger = Logger::new("app.log").with_level(LogLevel::Warn);
logger.info("This will not be logged");
logger.warn("This will be logged");

Initialization (init vs init_with)

  • init(path) initializes the global logger at the default level (Info).
  • init_with(logger) lets you provide a fully configured Logger.
use log_easy::{init, init_with, LogLevel, Logger};

init("app.log")?;
init_with(Logger::new("app.log").with_level(LogLevel::Trace))?;

Both return std::io::Result<()> and will error if the global logger is already initialized.

Error Handling

The convenience methods (info, warn, etc.) are non-intrusive and never return errors. If a write fails, the logger prints a message to stderr.

If you need to handle errors explicitly, use the try_* methods:

use log_easy::{LogLevel, Logger};

fn main() -> std::io::Result<()> {
    let logger = Logger::new("app.log").with_level(LogLevel::Info);

    logger.try_info("This can fail")?;
    Ok(())
}

The try_* macros return std::io::Result<()> as well:

use log_easy::{init_with, try_info, LogLevel, Logger};

fn main() -> std::io::Result<()> {
    init_with(Logger::new("app.log").with_level(LogLevel::Info))?;

    try_info!("This can fail")?;

    Ok(())
}

License

Licensed under either of:

  • Apache License, Version 2.0
  • MIT license

at your option.

Dependencies

~1MB
~18K SLoC