Skip to main content

Crate kvlog

Crate kvlog 

Source
Expand description

High-performance structured binary logging for Rust applications.

kvlog provides macros for emitting structured log messages with key-value pairs, optimized for high throughput and fast compile times. Log messages are encoded in a compact binary format with nanosecond-resolution timestamps.

§Log Messages

Each log message contains:

  • A nanosecond-resolution timestamp
  • An optional fixed string message
  • A target (Rust module path)
  • A series of key-value pairs
  • Optional span information for distributed tracing

§Log Levels

  • debug!: Development-only logging, requires the debug feature flag
  • info!: Provides useful context about application state
  • warn!: Something bad happened but it was expected
  • error!: Something bad happened unexpectedly, typically requires intervention

§Examples

Basic logging with key-value pairs:

// Simple message
kvlog::info!("Request completed");

// With key-value pairs (shorthand: `status` is equivalent to `status = status`)
kvlog::info!("Request completed", status, object_id);

Using format specifiers:

// %expr uses Display formatting
kvlog::error!("Failed to connect", %err);

// ?expr uses Debug formatting
kvlog::warn!("Unexpected config", ?config);

Conditional fields:

kvlog::info!(
    "Response sent",
    if let Some(len) = response_length { length = len }
);

Conditional logging with an environment guard:

static AUDIO_LOGS: kvlog::EnvGuard =
    kvlog::EnvGuard::new("APP_AUDIO_LOGS");

kvlog::info!(AUDIO_LOGS; "Audio initialized", codec = "opus");

§Spans

kvlog supports building trees of spans for distributed tracing. Unlike other tracing systems, logs are emitted immediately with correlation IDs that track parent-child relationships.

§Basic Span Usage

use kvlog::SpanID;

let span = SpanID::next();
kvlog::info!("Starting operation", span.start = span);
kvlog::info!("Processing", span.current = span);
kvlog::info!("Operation complete", span.end = span);

§Nested Spans

Use span.parent = Some(parent_id) to create hierarchical span trees:

use kvlog::SpanID;

let request_span = SpanID::next();
kvlog::info!("Request received", span.start = request_span);

// Create a child span for database work
let db_span = SpanID::next();
kvlog::info!("Querying database", span.start = db_span, span.parent = Some(request_span));
kvlog::info!("Query complete", span.end = db_span);

kvlog::info!("Request complete", span.end = request_span);

§Span Guards

Use SpanID::enter to set a thread-local span context. This is useful when calling functions that should inherit the current span:

use kvlog::SpanID;

fn process_item() {
    // This log automatically includes the current span context
    kvlog::info!("Processing item");
}

let span = SpanID::next();
let _guard = span.enter();  // Set span as current
kvlog::info!("Starting work", span.start = span);
process_item();  // Logs here inherit the span
kvlog::info!("Work complete", span.end = span);
// Guard dropped, previous span context restored

§Default Test Logger

When no collector is explicitly initialized, kvlog automatically emits logs to stdout in a human-readable format. Colors are enabled when stdout is a terminal or FORCE_COLOR=1 is set. This works seamlessly with Rust’s test runner, use cargo test -- --nocapture to see log output:

#[test]
fn my_test() {
    // No setup needed - logs are automatically printed to stdout
    kvlog::info!("Test starting", test_id = 42);
    // ... test logic ...
}

This zero-configuration behavior is ideal for development and debugging. Set KVLOG=0 to discard records from this implicit default logger. Explicitly initialized collectors are unaffected.

§Collector Setup

For production use, initialize a log collector to capture and output logs with better performance and output control:

let _guard = kvlog::spawn_collector_from_env(Some("my-service"), false);
kvlog::info!("Application started");
// Guard must be held for the duration of logging

Re-exports§

pub use collector::LogBuffer;
pub use encoding::BStr;
pub use encoding::Encode;
pub use encoding::SpanInfo;
pub use encoding::ValueEncoder;

Modules§

collector
Log collection and output infrastructure.
encoding

Macros§

debug
error
info
warn

Structs§

EnteredSpan
Guard that restores the previous span context when dropped.
EnvGuard
Lazily enables logging based on an environment variable.
Mutex
Mutex wrapper that logs warnings when held for too long in debug builds.
MutexGuard
lock guard returned by Mutex::lock.
SpanID
Unique identifier for correlating related log messages.
Spanning
Wrapper that carries span context with a value.
Timer
Simple stopwatch for measuring elapsed time in log messages.
Timestamp
UTC timestamp with nanosecond precision.

Enums§

CollectorConfig
Configuration for how log messages should be collected.
LogLevel
The severity level of a log message.

Functions§

continue_span
Wraps a value with the current span context, or creates a new span if none exists.
spawn_collector_from_env
Spawn background log collector thread with configuration from the env var: KVLOG_COLLECTOR_CONFIG Using CollectorConfig::default() if the env var can’t be read. If quiet is not set to true, the selected logging configuration will be printed to stdout.