MCP server exposing rlg log streams to LLM agents via JSON-RPC 2.0 over stdio.
Runs on your machine from its package; the steps are below.

At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
docker run -i --rm ghcr.io/sebastienrousseau/rlg-mcp:0.0.15
MCP client config
{
"mcpServers": {
"rlg": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/sebastienrousseau/rlg-mcp:0.0.15"
]
}
}
}
Near-lock-free structured logging for Rust: records leave the application thread with a few atomic operations and are formatted and written by a background flusher.
Getting started
cargo install for the CLIs and the MCP serverThe rlg ecosystem
rlg, rlg-cli, rlg-report, rlg-mcp, rlg-otlp, rlg-redact, rlg-tower, rlg-test, rlg-wasm, rlg-ebpfLibrary reference
docs/COMPARISON.mddocs/BENCHMARKS.mdOperational
[dependencies]
rlg = "0.0.15"
Satellites install the same way, all at the same version:
[dependencies]
rlg-otlp = "0.0.15" # ship records to an OpenTelemetry Collector
rlg-tower = "0.0.15" # per-request access logs for tower services
rlg-redact = "0.0.15" # scrub secrets and PII before they are written
[dev-dependencies]
rlg-test = "0.0.15" # assert on captured records in tests
cargo install rlg-cli # `rlg`: filter and convert log files
cargo install rlg-report # `rlg-report`: summaries by level, component and message
cargo install rlg-mcp # `rlg-mcp`: log files as tools for AI agents
From a checkout, make install builds the three binaries and installs
them with their manpages and bash, zsh and fish completions under
/usr/local (PREFIX and DESTDIR are honoured; make uninstall
reverses it). The binaries generate both themselves:
rlg --manpage > rlg.1, rlg --completions zsh > _rlg.
rlg-mcp is also published as a container image,
ghcr.io/sebastienrousseau/rlg-mcp, and listed in the MCP registry.
os_log, journald).
Everywhere else, including Windows, rlg writes to a file or stdout.use rlg::log::Log;
use rlg::log_format::LogFormat;
fn main() {
// Keep the guard for the life of the program: dropping it flushes
// pending records and stops the background thread.
let _guard = rlg::init().unwrap();
Log::info("User authenticated")
.component("auth-service")
.with("user_id", 42)
.format(LogFormat::JSON)
.fire();
}
fire() checks the level, pushes the record into a ring buffer and
returns; the flusher thread formats it as JSON and writes it to the
platform sink. This block is compiled and run by cargo test.
Ten crates at lockstep version 0.0.15, released together.
| Component | Purpose | Use case |
|---|---|---|
rlg | The engine: 65,536-slot ring buffer, background flusher, 14 formats, native sinks | Structured logging in any Rust program |
rlg-cli | The rlg binary: filter by level, component or attribute, convert between formats | my-service | rlg --min-level error --format ecs |
rlg-report | The rlg-report binary and library: counts by level and component, top messages, latency percentiles | On-call triage, daily error digests |
rlg-mcp | MCP server: four tools, one prompt, two resources over stdio, streamable HTTP or HTTP+SSE | AI agents reading production logs |
rlg-otlp | OTLP/HTTP exporter to a local OpenTelemetry Collector | Honeycomb, Datadog, Grafana through a Collector |
rlg-redact | Scrubs cards, JWTs, bearer tokens, emails, IPv4 addresses and AWS keys in one pass | GDPR and audit-trail safety |
rlg-tower | tower::Layer emitting one access-log record per request | axum, hyper and other tower services |
rlg-test | Capture records in a test and assert on them | Libraries testing their own log output |
rlg-wasm | wasm-bindgen bindings and a WASI 0.2 component interface | Browsers, Deno, Workers, wasmtime hosts |
rlg-ebpf | Process enrichment, portable; an eBPF enricher scaffold on Linux | Host context on every record |
| Area | Capability | Status |
|---|---|---|
| Ingestion | Atomic level filter, ring-buffer push, no lock on the caller's thread | Stable |
| Formats | JSON, NDJSON, ECS, GELF, Logstash, OTLP, MCP, logfmt, CLF, CEF, ELF, W3C, Apache, Log4j XML | Stable |
| Sinks | os_log (macOS), journald (Linux), file, stdout | Stable |
| Sinks | io_uring file sink (Linux, uring feature) | Scaffold |
| Configuration | TOML load, validation, polling hot-reload (tokio feature) | Stable |
| Bridges | log facade via rlg::init(); tracing layer (tracing-layer feature) | Stable |
| Export | OTLP/HTTP to a local Collector (rlg-otlp) | Stable |
| Agents | MCP server over stdio, streamable HTTP and HTTP+SSE (rlg-mcp) | Stable |
| Enrichment | eBPF kernel context (rlg-ebpf, Linux) | Scaffold |
rlg trades tracing's span model for an event-only engine that keeps
formatting and I/O off the application thread and ships native sinks,
many formats and an agent interface in the box.
| Project | Formatting off the caller's thread | Built-in formats | Native journald / os_log |
|---|---|---|---|
| rlg | yes | 14 | yes |
tracing + tracing-subscriber | add-on | text, JSON | add-on |
slog | add-on | add-on | add-on |
log + env_logger | no | text | no |
See docs/COMPARISON.md for the evidence and complete matrix.
The competitive_bench suite times rlg's fire() against
tracing::info! and log::info! for single records, records with
attributes, 10,000-record bursts and latency distribution. It runs in
CI on every release tag, and its results are published as workflow
artifacts.
| Scenario | Result | Environment |
|---|---|---|
rlg fire(), one record | 598 ns | GitHub-hosted ubuntu-latest, release profile |
tracing::info! to a discarding writer | 591 ns | same run |
rlg fire() with 3 attributes | 947 ns (tracing: 1,117 ns) | same run |
On the calling thread rlg now costs about what tracing costs, without
formatting there; what it buys is that the caller never waits on the
sink's I/O.
See docs/BENCHMARKS.md for methodology and full results.
Everything optional is off by default.
| Feature | Crate | Adds |
|---|---|---|
tokio | rlg | Config::load_async and polling hot-reload |
tui | rlg | A live terminal dashboard, started with RLG_TUI=1 |
tracing-layer | rlg | RlgLayer, a tracing_subscriber::Layer |
fast-queue | rlg | An eight-shard ring buffer for many concurrent producers |
uring | rlg | The io_uring file sink on Linux |
async | rlg-otlp | AsyncOtlpExporter on Tokio |
Config loads from TOML, validates, and creates the log paths it needs.
# rlg.toml
version = "1.0"
profile = "production"
log_file_path = "/var/log/rlg.log"
log_level = "INFO"
logging_destinations = [
{ type = "File", value = "/var/log/rlg.log" },
{ type = "Stdout" },
]
log_rotation = { Size = 10485760 } # 10 MiB
Load it with Config::load(Some("rlg.toml")), or with the tokio
feature Config::load_async, and follow edits with
Config::hot_reload_async. RUST_LOG sets the level too. The
crate README lists every field.
| Example | Shows | Run |
|---|---|---|
example_log_format | All 14 formats side by side | cargo run -p rlg --example example_log_format |
example_config | TOML config, async load, hot-reload | cargo run -p rlg --example example_config --features tokio |
example_macros | The logging macros | cargo run -p rlg --example example_macros |
serve_a_session | A full MCP session against rlg-mcp | cargo run -p rlg-mcp --example serve_a_session |
honeycomb | Exporting through a local Collector | cargo run -p rlg-otlp --example honeycomb |
CI runs every example on each pull request (examples-smoke.yml), except
example_config and example_utils, async demos whose behaviour the
crate's own tests cover.
tracing directly; rlg's layer only bridges its
events.FlushGuard drops
loses what is still buffered.0.0.x: any release may break,
and it has one maintainer.make verify # everything CI runs on a pull request
make demo # re-render .github/demo.gif from .github/demo.tape
DEVELOPMENT.md lists every gate with its local
command: Miri, Loom and Kani for the engine's concurrency and memory
safety, four fuzz targets, cargo-deny and cargo-vet for the dependency
tree, cargo-semver-checks, a 95% coverage floor and complexity ceilings.
Contribution and signing rules are in CONTRIBUTING.md
and AGENTS.md.
SECURITY.md.unsafe is denied across the workspace except the
documented macOS os_log FFI in crates/rlg/src/sink.rs. The engine
runs under Miri on every push.rlg-otlp caps a collector's response
headers at 16 KiB and times out every request.docs/OSS-FUZZ.md for OSS-Fuzz status.pkg/VERIFY.md).Report vulnerabilities according to SECURITY.md.
| Document | For |
|---|---|
| User manual | Tutorials, how-to guides, architecture, ADRs (source) |
| API reference | Every public item, per crate on docs.rs |
DEVELOPMENT.md | Toolchain, local gates, test layout, release model |
docs/ARCHITECTURE.md | How the engine and satellites fit together |
CHANGELOG.md | What changed in each release |
| Migration guides | Coming from log, slog or tracing |
0.0.x, so under Cargo's rules every release
may be breaking. Breaking changes are marked Breaking in the
CHANGELOG, and cargo-semver-checks runs on every pull request so none
slips through unannounced.docs/POLICIES.md
has the full policy.Dual-licensed under either of
LICENSE-APACHE)LICENSE-MIT)at your option. Unless you state otherwise, any contribution you submit for inclusion in rlg is dual-licensed as above, without additional terms.