StrataDB uses the tracing crate for structured logging. Instrumentation is built into the engine but produces zero overhead unless you wire up a subscriber in your application.

How It Works

StrataDB emits tracing spans and events on key code paths. Your application controls what gets collected by configuring a tracing subscriber. If no subscriber is set up, all instrumentation is compiled away to no-ops.

use tracing_subscriber::EnvFilter;

// Wire up a subscriber before opening the database
tracing_subscriber::fmt()
    .with_env_filter(EnvFilter::from_default_env())
    .init();

let db = Strata::open("/data/myapp")?;
// Now you'll see structured log output

Subsystem Targets

StrataDB defines 10 subsystem targets for fine-grained log control:

TargetSubsystemWhat Gets Logged
strata::branchBranch managementBranch create, delete, switch
strata::spaceSpace managementSpace registration, deletion
strata::commandCommand dispatchCommand execution, routing
strata::txnTransactionsBegin, commit, abort, validation, conflicts
strata::dbDatabaseDatabase-level operations, lifecycle
strata::walWrite-Ahead LogRecord append, rotation, flush, sync
strata::snapshotSnapshotsSnapshot writing, atomic operations
strata::recoveryRecoveryParticipant registration, WAL replay
strata::compactionCompactionWAL compaction operations
strata::vectorVector storeUpsert, search, collection management

Log Levels

Each subsystem uses standard tracing levels:

LevelWhen Used
errorUnrecoverable failures — corruption detected, recovery failure
warnRecoverable issues — transaction conflicts, retries, degraded performance
infoKey lifecycle events — branch created, transaction committed, snapshot written
debugDetailed operational data — individual key operations, search parameters

Configuration

Use the RUST_LOG environment variable to control which targets and levels are active:

# All strata logs at info level
RUST_LOG=info

# Transaction debugging
RUST_LOG=strata::txn=debug

# Multiple subsystems
RUST_LOG=strata::txn=debug,strata::wal=info,strata::recovery=debug

# Everything at debug (verbose)
RUST_LOG=strata=debug

# Only errors
RUST_LOG=strata=error

Setting Up a Subscriber

Basic Console Output

use tracing_subscriber::EnvFilter;

tracing_subscriber::fmt()
    .with_env_filter(EnvFilter::from_default_env())
    .init();

JSON Output

For structured log consumption (log aggregators, monitoring):

use tracing_subscriber::EnvFilter;

tracing_subscriber::fmt()
    .json()
    .with_env_filter(EnvFilter::from_default_env())
    .init();

Custom Subscriber

use tracing_subscriber::{fmt, EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};

tracing_subscriber::registry()
    .with(fmt::layer().with_target(true))
    .with(EnvFilter::new("strata::txn=debug,strata::wal=info"))
    .init();

Example Output

With RUST_LOG=strata::txn=debug,strata::branch=info:

2026-02-04T10:30:00Z  INFO strata::branch: branch created name="experiment-1"
2026-02-04T10:30:00Z DEBUG strata::txn: transaction begun txn_id=42 branch="default"
2026-02-04T10:30:00Z DEBUG strata::txn: transaction committed txn_id=42 writes=3

Zero Overhead

When no subscriber is configured, tracing macros compile to no-ops. There is no runtime cost — no string formatting, no allocation, no I/O. You only pay for what you collect.

Next