Features
Pipeline
- Three formats - JSON Lines, logfmt, and an aligned human-readable line with optional terminal colour.
- Per-target filtering -
RUST_LOG-style directives where the most specific rule wins; read them from an environment variable withenv_filter. - Ambient fields - service-level default fields and thread-local context (
trace_id,request_id), de-duplicated with clear precedence. - Several sinks per logger - stdout/stderr, buffered files, size- and time-based rotation, any
io::Write, and a background writer with a bounded queue.
Ergonomics
- Macros with
format!messages -info!("user {id} logged in", http.status = 200, peer = %addr), with or without an explicit logger. - Global logger -
log_io::init(logger)returns a guard that flushes at the end ofmain. - Async-friendly context - capture context once and re-install it around every poll of a future, on any executor.
logandtracingbridges - route existing ecosystem logging into log-io sinks (featureslogandtracing).
Safety and reliability
- Injection-safe output - C0/C1 controls, DEL, U+2028/2029 and bidi controls are escaped in every format; metadata keys cannot be spoofed by fields.
- Redaction - replace
password,token,authorizationand other configured keys with[REDACTED]at the logging boundary. - Durable shutdown - flush-on-level (errors by default), flush guards,
fsyncon flush when you need it, and an opt-in panic hook. - Zero unsafe code -
#![forbid(unsafe_code)]; sinks recover from mutex poisoning; library code never unwraps.
Installation
[]
= "2"
# Optional integrations:
= { = "2", = [
"log", # route `log` macros into log-io (LogBridge)
"tracing", # use log-io as a tracing-subscriber layer (TracingLayer)
] }
Feature recommendations
- Applications: the defaults (
std,json,logfmt,human). - Libraries already using
logortracing: addlogortracingand keep your existing macros. - Embedded (
no_std):default-features = false, features = ["json"](orlogfmt/human) for the data model and formatters only.
Quick Start
One line installs a JSON logger on standard output (info, or the
filter in LOG_IO); init_logfmt and init_human pick the other
layouts:
let _guard = init_json?;
let port = 8080_u16;
info!;
# Ok::
To configure it, build the logger:
use ;
let logger = builder
.level
.env_filter // e.g. LOG_IO="info,my_app::db=debug"
.with_default_field
.stdout_json
.build;
let _guard = init.expect;
let port = 8080_u16;
info!;
warn!;
Context across threads and async tasks
use ;
let logger = builder.stdout_logfmt.build;
let _request = with_request_id;
info!; // carries request_id=req-7
let snapshot = capture;
let worker = logger.clone;
spawn
.join
.unwrap;
// For futures: tokio::spawn(snapshot.wrap(async move { ... }))
Durable file output off the hot path
use JsonFormat;
use ;
use ;
let file = builder
.max_bytes
.rotation
.max_files
.open?;
let sink = new?;
let logger = builder
.level
.redact_common_secrets
.with_sink
.build;
let _guard = init?; // drains the queue when main returns
# Ok::
Plugging into log and tracing
use ;
use Logger;
use SubscriberExt;
let logger = builder.stdout_logfmt.build;
new.install.ok;
info!;
let subscriber = registry.with;
with_default;
Performance
Measured on an AMD Ryzen 9 9950X3D, Windows 11, rustc 1.95; see
BENCH.md for the method and the full tables.
| Workload | 2.0.0 | vs 1.0.0 |
|---|---|---|
| JSON format, 5 fields | ~123 ns | 8% faster |
| logfmt format, 5 fields | ~115 ns | 26% faster |
| Pipeline, JSON writer, 3 fields | ~64 ns | same |
| Pipeline, default config (timestamp + context) | ~114 ns | same |
| Record rejected by the filter | ~1 ns | 60% faster |
| 4 threads, one shared JSON sink | ~24 ns/record | 25% faster |
| 8 threads, one shared JSON sink | ~27 ns/record | 2.7x faster |
No heap allocation per record in steady state (enforced by
tests/alloc.rs).
Status: Stable
Current version: 2.1.0. The API follows Semantic Versioning;
Value, Error, Metadata, Record and the configuration enums are
#[non_exhaustive] so they can grow in minor releases. Upgrading from
1.x: see docs/MIGRATION.md.
Planned: sampling and rate limiting per call site, OpenTelemetry-shaped JSON layouts, compression of rotated files.
Documentation & Resources
Documentation
- Documentation Index - where everything is
- API Reference - every component with runnable examples
- Migration Guide - upgrading from 1.x
- Benchmarks - method, machine and numbers
- Specification - design contract and policies
- docs.rs/log-io - generated rustdoc
Examples
| Example | Shows |
|---|---|
01_quick_start |
the smallest useful setup |
02_macros |
format strings, dotted keys, % / ? values, targets |
03_context |
request context and snapshots across threads |
04_filter |
directives, most-specific matching, LOG_IO env var |
05_file_sink |
durable file output with a flush guard |
06_multi_sink |
human on stderr and JSON in a file |
07_default_fields_and_redaction |
service fields and secret redaction |
08_custom_format |
custom and runtime-selected formats |
09_custom_sink |
implementing Sink |
10_non_blocking |
background writer with rotation |
11_log_bridge |
the log facade (feature log) |
12_tracing_layer |
tracing with span fields (feature tracing) |
Run one with cargo run --example 02_macros (add --features log or
--features tracing for the last two).
Troubleshooting
Version Compatibility
- Rust: 1.85+ (edition 2024). Raising the MSRV is a major-version change.
- API stability: semantic versioning; see
REPS.mdsection 9. - Feature flags: additive;
logandtracingare independent of each other.
Development Setup