The first stable release of cl-log-kit — a dependency-free, SBCL-only
structured logging toolkit for Common Lisp, modelled on Go's log/slog.
Immutable log records are separated from handlers that serialize them,
and handle-log-record is the single method through which a record reaches
output — so "this line got logged twice" is structurally impossible rather
than merely avoided.
What 1.0.0 establishes
- Records and snapshotting — every field value is deep-copied on the way
in and on the way out, cycles are rejected instead of followed, and depth,
node count, string length, and collection size are all capped with
structured conditions. A logging call cannot become the vector for an
unbounded-memory or non-terminating bug, even on attacker-influenced input. - Injection-safe wire formats —
text-handlerescapes control,
bidirectional, and invisible characters so user data cannot forge or
disguise a log line;json-handleremits strict RFC 8259 and validates the
whole record before writing a byte. - Composition handlers — multi, filter, function, null, processor,
rotating-file, and buffered, over a lifecycle that guarantees
close-at-most-once under concurrent and re-entrant callers, verified with
real threads. - Context and correlation — logger derivation, dynamically scoped
with-log-context, explicit cross-thread propagation, spans with
parent/child correlation, and bounded condition logging that does not run
an untrustedreportmethod unless you ask it to. - Zero per-call allocation in
handle-log-recordon every benchmarked
wire format — asserted by the test suite, not just measured once.
Stability
101 exported symbols, every one carrying a docstring, are now a stable
surface under Semantic Versioning: anything that changes their shape or
behavior gets a major version and a documented migration path.
Verification
179 examples (property-based, fuzz, mutation, snapshot, allocation-bound,
and real multi-threaded specs) pass on SBCL 2.6.0 and 2.6.6; the coverage
gate holds at 93.95% expression / 98.77% branch; nix flake check runs the
same suite a contributor runs locally, under an enforced timeout.
Full details in CHANGELOG.md.
Documentation: https://nerima-lisp.github.io/cl-log-kit/