# log-easy
[](https://crates.io/crates/log-easy)
[](https://docs.rs/log-easy)
[](./LICENSE.txt)
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`:
```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:
```text
[YYYY-MM-DD HH:MM:SS][LOG_LEVEL] Message
```
## Quick Start (Global Logger + Macros)
```rust
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)
```rust
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!`:
```rust
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:
```rust
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.
```rust
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`.
```rust
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:
```rust
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:
```rust
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.