minimal_logger
A minimal-resource, multi-platform logger for Rust with optional file output, automatic flushing, platform-native log rotation, and change-aware runtime reconfiguration via a builder API.
Features
- Thread-local buffered logging with
BufWriter - Platform-specific log rotation
- Linux / macOS:
SIGHUP - Windows:
Global\\RustLogger_LogRotatenamed event
- Linux / macOS:
- Periodic background flush thread with configurable interval
- Builder-based configuration for log level, output file, buffer size, and format
- Environment-variable bootstrap via
config_from_env() - Falls back to
stderrwhen file output is unavailable - Change-aware runtime reconfiguration — only updated subsystems are re-initialised
Installation
Add to your Cargo.toml:
[]
= "0.2"
= "0.4"
Getting started
Construct a MinimalLoggerConfig and pass it to init() once at startup:
use ;
Or seed configuration from the standard RUST_LOG* environment variables:
Runtime reconfiguration
Call reinit() with a new MinimalLoggerConfig to update a running logger.
reinit() is change-aware and only updates components whose effective
configuration changed:
- log filters and max level (
.level()/.filter()) - output destination (
.file()/.stderr()) - periodic flush worker interval (
.flush_ms()) - rendering format (
.format()) - per-thread buffer capacity for newly recreated writers (
.buf_capacity())
Unset fields keep their current value — you can change a single subsystem
without repeating the full configuration. If nothing changed, reinit() returns
immediately.
use info;
Configuration
| Builder method | Default at init |
Description |
|---|---|---|
.level(l) |
Info |
Global log level |
.filter(t, l) |
(none) | Per-target level override; may be called many times |
.file(path) |
(stderr) | Append log records to a file (O_APPEND) |
.stderr() |
(default) | Explicitly route output back to stderr |
.buf_capacity(n) |
4096 |
Per-thread BufWriter capacity in bytes |
.flush_ms(ms) |
1000 |
Periodic flush interval in milliseconds |
.format(tmpl) |
see below | Log-line template with {field} placeholders |
Level and filter syntax
// All targets at DEBUG
new.level
// Global WARN; myapp at DEBUG
new
.level
.filter
// Layered per-module overrides
new
.level
.filter
.filter
Recognised levels: Off, Error, Warn, Info, Debug, Trace.
When multiple filters match a target the most specific (longest prefix) wins.
Format fields
| Placeholder | Example output |
|---|---|
{timestamp} |
2026-04-18T12:34:56.789012Z |
{level} |
INFO |
{thread_name} |
main |
{target} |
myapp::server |
{module_path} |
myapp::server |
{file} |
src/server.rs |
{line} |
42 |
{args} |
listening on :8080 |
Width and alignment: {level:<5} left-aligns in a field of width 5;
{line:>4} right-aligns. Use {{ and }} for literal brace characters.
Default format string:
{timestamp} [{level:<5}] T[{thread_name}] [{file}:{line}] {args}
Log rotation
The logger reopens its log file on a platform-native signal or event, with no gap in output and no lost bytes.
| Platform | Trigger |
|---|---|
| Linux / macOS | SIGHUP |
| Other Unix | SIGHUP |
| Windows | Global\RustLogger_LogRotate named event |
When the signal fires, each thread detects the new file on its next log call
via an Arc pointer comparison: it flushes its buffered bytes to the old file
descriptor, then creates a new BufWriter pointing to the freshly opened file.
The old file descriptor is closed once no thread holds a reference to it.
Example logrotate configuration (Linux):
/var/log/myapp.log {
daily
rotate 7
postrotate
kill -HUP $(cat /var/run/myapp.pid)
endscript
}
API summary
| Function | Description |
|---|---|
init(MinimalLoggerConfig) |
Register the logger and start the flush worker. Call once at startup. |
reinit(MinimalLoggerConfig) |
Apply a new config; update only changed subsystems. |
config_from_env() |
Build a MinimalLoggerConfig from RUST_LOG* environment variables. |
shutdown() |
Flush the calling thread's buffered writer before process exit. |
Cargo metadata
This crate exposes docs on docs.rs.