backbeat
A low-overhead flight recorder for Rust: capture structured events into per-core ring buffers, dump them to disk, and read the dump back as Parquet or a Chrome/Perfetto trace.
Features
- Cheap to capture. The hot path is an atomic
fetch_addplus amemcpyinto a per-core ring — no locks, no cross-core contention, no allocation. When disabled it's a single relaxed load. - Self-describing dumps. Add, remove, or reorder an event's fields freely; the embedded schema reflects it, and old tooling still reads new dumps.
- Define events with a derive.
#[derive(Event)]on a#[repr(C)]struct is all it takes; events register themselves, so the dumper finds them automatically. - Spans, not just points. Mark a pair of events as a span and the trace output renders real begin/end duration slices.
- Useful output.
convertwrites sparse-wide Parquet (query it with anything) or Chrome/Perfetto trace JSON (open it in Perfetto orchrome://tracing). no_std-friendly. Events can be defined inno_stdcrates; the default recorder runtime needsstd.
Getting started
Add the library to the crate that produces events:
[]
= "0.1"
= { = "0.8", = ["derive"] }
Define events, record them, and dump:
use ;
use ;
use Recorder;
/// Which side is sending a packet.
/// A packet was sent.
let rec = new;
rec.set_enabled;
rec.record;
// Dump everything compiled in (the registry self-populates via the derive).
let dump = rec.dump;
write.unwrap;
Then read the dump with the CLI:
$ cargo install backbeat-cli
$ backbeat inspect trace.bb # envelope, schema registry, per-shard counts
$ backbeat convert trace.bb -o out.parquet # → sparse-wide Parquet
$ backbeat convert trace.bb -o out.json # → Chrome / Perfetto trace
convert accepts multiple dumps and merges them into one output.
Global recorder
For a system-wide recorder you usually want a single process-wide instance you can reach from
anywhere, dumped asynchronously off the hot path. backbeat::global provides exactly that — a
lazily-built recorder behind a OnceLock plus a background dumper thread:
use global;
enable; // arm capture (starts disabled)
record; // instrument anywhere — no handle to thread through
// When something looks wrong, ask the background thread to flush the rings to disk. This returns
// immediately; the (blocking) snapshot + write happen on the dumper thread, throttled so a trigger
// storm can't fill the disk. Each dump is a new timestamp-named file, so a dump's age is obvious and
// no earlier dump is overwritten.
trigger;
It is configured by environment variables, read once on first use, so a binary can be traced with no code change:
| Variable | Meaning | Default |
|---|---|---|
BACKBEAT_ENABLE |
Arm capture as soon as the recorder is built | off |
BACKBEAT_SHARDS |
Number of per-CPU rings | available parallelism (capped at 16) |
BACKBEAT_BYTES |
Bytes per shard | 16 MiB |
BACKBEAT_PATH |
Base dump path (each dump inserts a UTC timestamp before the extension) | ${TMPDIR}/backbeat.<pid>.bb |
BACKBEAT_THROTTLE_MS |
Minimum interval between dumps | 1000 |
BACKBEAT_MAX_DUMPS |
Cap on dump files kept (0 = unlimited) |
8 |
BACKBEAT_LIMIT_POLICY |
At the cap: keep-oldest (stop) or keep-newest (evict oldest) |
keep-oldest |
BACKBEAT_HOST |
Host label embedded in each dump | system hostname |
BACKBEAT_SIGNAL |
Unix: kill -<sig> triggers a dump (usr1/usr2/number) |
none |
BACKBEAT_DUMP_ON_PANIC |
Trigger a final dump from a panic hook | off |
Prebuilt binaries
Install the latest backbeat CLI with one line — it detects your platform, verifies the checksum,
and drops the binary in ~/.local/bin:
$ curl -fsSL https://raw.githubusercontent.com/camshaft/backbeat/main/install.sh | sh
Override where it lands with BACKBEAT_INSTALL_DIR, or pin a version with BACKBEAT_VERSION=v0.1.0.
Tagged releases publish prebuilt backbeat CLI binaries you can drop onto a host to convert a dump:
statically-linked musl builds for x86_64/aarch64 Linux and a self-contained aarch64 macOS
build, attached to the GitHub Release as
per-target .tar.gz archives (each with a .sha256). The latest release always resolves to the
newest tag, so the installer URL and
https://github.com/camshaft/backbeat/releases/latest/download/backbeat-<target>.tar.gz never need
updating. Prefer to build from source? cargo install backbeat-cli.
License
This project is licensed under the MIT license.