slog-json

JSON drain for slog-rs that serializes Rust log records to structured, machine-readable JSON.

Library
Cargo
v2.6.1
15stars
MPL-2.0 OR MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
28/100Needs Attention
Development Activity0
Maintenance20
Community20
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
56/100Fair
Architecture65
Code Quality55
Innovation45
Learning Curve60

slog-json is a Drain implementation for the slog-rs structured logging framework that renders every log record as a single JSON object written to any io::Write target (stdout, stderr, a file, or a socket). It builds on slog’s key-value record model, walking a record’s default fields plus any logger-scoped and per-call key-value pairs and serializing them through serde_json, so JSON output composes naturally with the rest of the slog-rs drain ecosystem (async wrapping, level filtering, fan-out to multiple drains).

It ships with a sensible default key set (ts, level, msg) via Json::default(), or a builder (Json::new()/JsonBuilder) for full control over newline behavior, flushing, pretty-printing, and additional static key-value pairs — making it a common choice for shipping Rust application logs to log aggregators, container log collectors, or any pipeline that expects line-delimited JSON.

What You Get

  • A Json<W> Drain that serializes any slog Record plus its owned and logger key-values into a single JSON object via serde_json
  • Json::default(io) for a zero-configuration drain with ts (RFC3339 timestamp), level, and msg fields pre-populated
  • JsonBuilder for custom configuration: set_newlines, set_flush, set_pretty, and add_key_value for extra static or computed fields
  • Optional nested-values feature (via erased-serde) to serialize structured/nested values instead of flattening everything to strings
  • Optional dynamic-keys feature that forwards to slog’s own dynamic-keys support for runtime-determined key names

Common Use Cases

  • Emitting line-delimited JSON application logs to stdout/stderr for collection by Docker, Kubernetes, or a log shipper (Fluentd, Vector, Filebeat)
  • Writing structured JSON logs to a rotating file for later ingestion into Elasticsearch, Loki, or a similar log store
  • Combining with slog-async to serialize logs to JSON off the hot path in latency-sensitive services
  • Fanning out the same slog Logger to both a human-readable terminal drain and a JSON drain for production log pipelines

Under The Hood

Architecture - The crate centers on two types: Json<W: io::Write>, the slog::Drain implementation, and JsonBuilder<W>, its configuration builder. On each log() call, Json picks a serde_json::Serializer (pretty or compact, per the pretty flag) wrapping the wrapped io::Write, then delegates to log_impl, which builds a SerdeSerializer<S> adapter — a newtype around serde_json’s SerializeMap state — and feeds it three things in order: the builder’s static values (an OwnedKVList produced by add_key_value/add_default_keys), the logger’s own OwnedKVList, and finally the record’s per-call key-values, so later keys can shadow earlier ones in the resulting map. SerdeSerializer implements slog’s Serializer trait (emit_bool, emit_str, emit_arguments, etc.), translating each slog value type into a serialize_entry call on the underlying serde map; formatted (emit_arguments) values are rendered into a thread-local String buffer (TL_BUF) to avoid a fresh allocation per field. After serialization, Json optionally appends a newline and flushes the writer, both gated by builder flags.

Tech Stack - Pure Rust, edition = "2018", MSRV 1.53. Core dependencies are slog (the drain/record/KV trait ecosystem this crate plugs into), serde and serde_json (the actual JSON serialization), and time (RFC3339 timestamp formatting for the default ts field, replacing an earlier chrono dependency per the changelog). erased-serde is an optional dependency gated behind the nested-values Cargo feature for serializing arbitrary nested structured values. slog-async appears only as a dev-dependency, used in the examples/pretty.rs example to demonstrate non-blocking usage. No async runtime, no unsafe code beyond what slog/serde pull in, no macros beyond slog’s own o!.

Code Quality - There is no dedicated test suite (no tests/ directory, no #[test] functions in src/lib.rs); the only executable verification is a doctest embedded in the crate-level doc comment showing basic Json::default usage, plus the examples/pretty.rs example. The single-file src/lib.rs (~350 lines) is organized with {{{/}}} vim fold markers into clearly delimited Imports, Serialize, Json, and JsonBuilder sections, uses #![warn(missing_docs)] to enforce doc coverage on public items, and keeps error handling consistent by wrapping serde errors into io::Error::new(io::ErrorKind::Other, ...) via a shared impl_m! macro. Field and method naming follows slog-rs conventions consistently (add_key_value, set_pretty, set_newlines) but the absence of unit tests is a real gap for a crate handling record serialization.

API Design - The API is a small, idiomatic builder over a single Drain type: Json::default(io) covers the common case in one call, while Json::new(io) returns a JsonBuilder for set_pretty/set_newlines/set_flush/add_key_value chaining ending in .build(). Because Json<W> implements slog::Drain, it composes directly with Fuse, Mutex, and slog-async::Async the same way any other slog drain does, so there’s effectively zero boilerplate beyond what slog itself requires. The main ergonomic rough edge is that the crate assumes familiarity with slog-rs’s own drain/KV vocabulary (OwnedKVList, SendSyncRefUnwindSafeKV) — it is not meant to be used standalone, and its docs point users toward the parent slog-rs project for broader context.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search