sjl - Simple JSON Logger
📦 crates.io | 📚 docs.rs
What
It's a Simple JSON Logger. It logs JSON to stderr.
Why?
The most popular logging crate, tracing, has problems with nested JSON unless you use the valuable crate with it which is unstable and behind a feature flag for 3 years... but that still has issues with enums and doesn't feel natural to use with .as_value() everywhere. The slog crate has similar issues—I've written about both here.
If you just want a Simple JSON Logger, you might find this useful.
Installation
cargo add sjl
Usage
use sjl::Logger;
fn main() {
let logger = Logger::new();
logger.info("Saul Goodman", ()); }
Outputs
{"timestamp":"2026-05-21T02:45:03.456Z","level":"info","message":"Saul Goodman"}
Extended Usage / Raison d'être
use serde::Serialize;
use sjl::LoggerOptions;
#[derive(Serialize)] struct User {
name: String,
cars: Vec<Car>,
}
#[derive(Serialize)]
struct Car {
make: String,
model: String,
transmission: Transmission,
}
#[derive(Serialize)]
enum Transmission {
Automatic,
Manual,
}
fn main() {
let logger = LoggerOptions::default().pretty(true).init();
let user = User {
name: "Jose".into(),
cars: vec![
Car {
make: "Toyota".into(),
model: "Rav4".into(),
transmission: Transmission::Manual,
},
Car {
make: "Tesla".into(),
model: "Cybertruck".into(),
transmission: Transmission::Automatic,
},
],
};
logger.info("Saul Goodman!", &user);
}
Outputs
{
"timestamp": "2026-05-21T03:39:36.780Z",
"level": "info",
"message": "Saul Goodman!",
"data": {
"name": "Jose",
"cars": [
{
"make": "Toyota",
"model": "Rav4",
"transmission": "Manual" },
{
"make": "Tesla",
"model": "Cybertruck",
"transmission": "Automatic"
}
]
}
}
All Options
use std::time::Duration;
use sjl::{LoggerOptions, LogLevel};
fn main() {
let logger = LoggerOptions::default()
.context("service", "payments")
.context("environment", "production")
.min_level(LogLevel::Warn)
.flush_at_bytes(1_000)
.flush_at_messages(100)
.flush_interval(Duration::from_millis(250))
.buffer_pool_size(20)
.buffer_pool_initial_capacity(4_000)
.buffer_pool_max_capacity(100_000)
.timestamp_key("time")
.timestamp_format("%FT%I:%M:%S%p")
.pretty(true)
.init();
logger.error("Saul Goodman!", ());
}
Outputs
{
"time": "2026-05-21T03:35:04AM",
"level": "error",
"message": "Saul Goodman!",
"environment": "production",
"service": "payments"
}
Running Tests
cargo llvm-cov --html