# log-io v1.0.0 - Stable API
**Date:** 2026-05-18
**Compare:** `v0.10.0...v1.0.0`
## Headline
The public surface is frozen. Backwards-incompatible changes after
`1.0.0` require a major version bump per Semantic Versioning. See
[`REPS.md`](../../REPS.md) section 8 for the binding stability policy
and [`docs/API.md`](../API.md) for the complete public-symbol
reference.
No functional code changes from `v0.10.0`. The 1.0.0 release is a
freeze, a documentation polish, and the CI gate that protects the
guarantee going forward.
Behind the line: the journey from `v0.1.0` (scaffold) to `v1.0.0`
landed three formats (JSON / logfmt / human), five sinks, per-target
filtering with directive parsing, thread-local context propagation
with RAII guards, per-logger default fields, a multi-sink fanout
with continue-on-error dispatch, RFC 3339 timestamps with no
runtime dependency, an allocation-free steady-state hot path, and a
112-test suite covering unit, integration, stress, property, and
doctest paths plus four `cargo-fuzz` harnesses.
## What changed since `v0.10.0`
### New - `cargo-semver-checks` CI job
A dedicated CI job runs
[`cargo-semver-checks`](https://github.com/obi1kenobi/cargo-semver-checks)
against the published baseline on every pull request and every push
to `main`. Backwards-incompatible additions to the public surface
fail CI before they can ship.
### New - `docs/API.md` rewritten as the complete reference
Every public item now has a dedicated section in
[`docs/API.md`](../API.md) with description, signature, parameter
breakdown, and runnable examples. The document mirrors the rustdoc
on docs.rs and serves as the offline reference.
### Changed - `README.md` polished for production
Removed pre-release status banner and dev-facing notes; added an
overview, installation, performance summary, examples index, and a
direct link to the API reference.
### Changed - `REPS.md` section 8 declares stability
The stability section was previously "0.x.y releases are not
API-stable". It now declares the public API frozen and enumerates
what is and isn't covered by the SemVer guarantee.
### Changed - `CHANGELOG.md` consolidated
The 1.0.0 entry summarises the complete public surface and the
features / hardening / performance work that landed across the
`0.9` and `0.10` pre-release lines. The historical entries remain
as brief pointers to their git tags.
There are no source-level changes to the crate code between
`v0.10.0` and `v1.0.0`. The package contents on crates.io are
functionally identical; the version bump signals API stability.
## Frozen public surface
Full listing in [`docs/API.md`](../API.md). Summary by module:
### Always available (data model, `no_std`-compatible)
- `log_io::{Level, ParseLevelError}`
- `log_io::{Value, Field, Metadata, Record}`
- `log_io::format::{Format, JsonFormat, LogfmtFormat, HumanFormat}`
(each formatter behind its own feature flag, all on by default)
- `log_io::VERSION`
### `std` feature (default)
- `log_io::{Filter, FilterRule, ParseFilterError}`
- `log_io::{Logger, LoggerBuilder, ErrorHandler}`
- `log_io::{Error, Result, Sink}`
- `log_io::sink::{StdoutSink, StderrSink, FileSink, WriterSink, NullSink}`
- `log_io::context::{ContextGuard, MAX_CONTEXT_SLOTS, with_field,
with_trace_id, with_request_id, with_snapshot, clear, len}`
- Macros: `log_at!`, `trace!`, `debug!`, `info!`, `warn!`, `error!`
### Feature flags
| `std` | yes | Logger, sinks, context, timestamps. |
| `json` | yes | `JsonFormat`. |
| `logfmt` | yes | `LogfmtFormat`. |
| `human` | yes | `HumanFormat` (no_std-compatible). |
### MSRV
`1.75`, unchanged from `v0.10.0`.
### Runtime dependencies
Zero. The crate depends only on `core` and (with `std` enabled)
`std`. `proptest` is a dev-dependency only, used in
`tests/property.rs`.
## Verification
Local matrix (Windows x86_64-pc-windows-msvc, stable 1.95):
- `cargo build` (default features) [OK]
- `cargo build --no-default-features` [OK]
- `cargo build --all-features` [OK]
- `cargo +1.75 build --all-features` (MSRV) [OK]
- `cargo fmt --all -- --check` [OK]
- `cargo clippy --all-targets --all-features -- -D warnings` [OK]
- `cargo clippy --all-targets --no-default-features -- -D warnings` [OK]
- `cargo test --all-features` - **112 tests pass, 0 ignored**
(61 unit + 18 integration + 16 stress + 11 property + 6 doctest)
- `RUSTDOCFLAGS="-D warnings -D rustdoc::broken-intra-doc-links" cargo doc --all-features --no-deps` [OK]
- `cargo package` [OK] (50 files, 224.6 KiB; 59.4 KiB compressed)
- Banned-word and em-dash scan across `src/`, `tests/`, `examples/`,
`benches/`, `docs/`, `README.md`, `CHANGELOG.md`: 0 hits
CI matrix runs on ubuntu-latest, macos-latest, windows-latest for
the `test` job plus dedicated `clippy`, `fmt`, `docs`, `msrv`, and
`semver-checks` jobs.
## Performance
Measured on a developer laptop (release, `lto = "thin"`); full
methodology in [`BENCH.md`](../../BENCH.md).
### Format-only (ns / record, 5 fields)
| JSON | ~131 |
| logfmt | ~159 |
| human | ~210 |
| JSON, no fields | ~12 |
### Full pipeline (ns / call, 3 fields)
| `dispatch_only` (null sink) | ~6 |
| `below_threshold` (filtered) | ~1 |
| `json + writer` | ~59 |
| `logfmt + writer` | ~63 |
| `json + writer`, no fields | ~25 |
### Concurrent throughput (records / second)
| 1 | 100 K | 6 ms | ~15 M rec/s |
| 2 | 200 K | 8 ms | ~22 M rec/s |
| 4 | 400 K | 14 ms | ~28 M rec/s |
| 8 | 800 K | 82 ms | ~10 M rec/s |
| 16 | 1.6 M | 211 ms | ~7.6 M rec/s |
Filtered-out records cost ~1 ns; put coarse target-based filtering
up front rather than guarding at the call site.
## Migration
### From `v0.10.0`
No source changes required. The public API surface is unchanged.
### From `v0.9.0`
`v0.10.0` introduced breaking changes to the builder API; see the
[v0.9.0 to v0.10.0 migration notes](https://github.com/jamesgober/log-io/blob/v0.10.0/CHANGELOG.md#0100---2026-05-18)
in the `0.10.0` changelog. Key changes:
- `.stdout().json().build()` is now `.stdout_json().build()` or
`.stdout(JsonFormat::new()).build()`.
- Builder methods `.file()`, `.file_append()`, `.null()`, and the
factory-style `.writer(closure)` are removed. Use
`.with_sink(FileSink::create(...)?)` for files,
`.with_sink(NullSink::new())` for null, and `.writer(W, F)`
passing the writer directly.
- `Logger::try_log_with_target` is now `Logger::try_log`.
- The `warn_!` macro is now `warn!`.
- `Logger` dispatch now continues across sink failures: the first
error is surfaced but every sink still receives the record.
- `HumanFormat` no longer requires the `std` feature.
- The `NoFormat` placeholder is gone; `build()` panics if no sink
has been installed (the panic is a clear programmer-error
signal, not a runtime failure mode).
## Stability commitment
From `1.0.0` forward (full policy in
[`REPS.md`](../../REPS.md) section 8):
- **Patch (`1.0.x`)** - bug fixes, doc improvements, internal
performance work, test additions. No new public items.
- **Minor (`1.x.0`)** - pure additions to the public surface, new
opt-in features, new variants on enums that are reserved for
growth, MSRV bumps.
- **Major (`2.0.0`)** - anything that removes, renames, or changes
the signature of a public symbol, or that adds a non-opt-in
runtime dependency.
The CI `semver-checks` job enforces this for the public API
surface; the policy itself binds documentation and dependency
posture as well.
## Release ceremony
```bash
# After the version bump + CHANGELOG + verification:
git tag -a v1.0.0 -m "Release v1.0.0 - Stable API"
git push origin main
git push origin v1.0.0
# Publish.
cargo publish
# Verify the index updated.
GitHub release title: `v1.0.0 - Stable API`. Not tagged as
pre-release.
## Acknowledgements
`log-io` reached `1.0.0` through `0.1.0` (scaffold), `0.9.0` (first
implementation), `0.10.0` (hardening), and this freeze. Pre-release
work was extensive but the project never had external dependencies
and never carried `unsafe` code; the public-API surface declared
here is the same one that compiled and tested green for the
preceding twelve hours of development.
---
**Full Changelog:** https://github.com/jamesgober/log-io/compare/v0.10.0...v1.0.0