Expand description
A tracing-subscriber
layer for sending logs to Better Stack.
This crate provides a seamless integration between Rust’s tracing
ecosystem and Better Stack’s
log management platform. It automatically collects, batches, and sends your application logs
to Better Stack for centralized logging, monitoring, and analysis.
§Features
- 🚀 Asynchronous & Non-blocking: Logs are sent in background tasks without blocking your application
- 📦 Automatic Batching: Efficiently batches logs to minimize HTTP requests and improve performance
- 🔄 Retry Logic: Built-in exponential backoff retry mechanism for handling transient failures
- 🎯 Structured Logging: Full support for structured fields, span context, and nested spans
- ⚡ Lazy Initialization: Gracefully handles tokio runtime initialization and shutdown
- 🛡️ Production Ready: Comprehensive error handling with fail-open behavior to never crash your app
- 🗜️ Multiple Formats: Choose between JSON and MessagePack serialization formats
§Quick Start
use tracing::{info, error};
use tracing_better_stack::{BetterStackLayer, BetterStackConfig};
use tracing_subscriber::prelude::*;
#[tokio::main]
async fn main() {
// Configure Better Stack layer with your ingesting host and source token
// Get these from https://logs.betterstack.com/
let layer = BetterStackLayer::new(
BetterStackConfig::builder(
"s1234567.us-east-9.betterstackdata.com",
"your-source-token"
).build()
);
// Initialize tracing with the Better Stack layer
tracing_subscriber::registry()
.with(layer)
.init();
// Your logs are now being sent to Better Stack!
info!(user_id = 123, "User logged in");
error!(error = "Connection timeout", "Failed to connect to database");
}
§Serialization Formats
Better Stack supports both JSON and MessagePack formats. This crate provides both via mutually exclusive feature flags:
§MessagePack (Default)
MessagePack is a binary serialization format that’s more compact and efficient than JSON:
[dependencies]
tracing-better-stack = "0.1" # Uses MessagePack by default
§JSON
JSON is human-readable and useful for debugging:
[dependencies]
tracing-better-stack = { version = "0.1", default-features = false, features = ["json"] }
§Configuration
The BetterStackConfig
builder provides extensive configuration options:
use std::time::Duration;
use tracing_better_stack::{BetterStackLayer, BetterStackConfig};
let layer = BetterStackLayer::new(
BetterStackConfig::builder(
"s1234567.us-east-9.betterstackdata.com",
"your-source-token"
)
.batch_size(200) // Max events per batch
.batch_timeout(Duration::from_secs(10)) // Max time between batches
.max_retries(5) // Retry attempts on failure
.initial_retry_delay(Duration::from_millis(200)) // Initial backoff delay
.max_retry_delay(Duration::from_secs(30)) // Maximum backoff delay
.include_location(true) // Include file/line info
.include_spans(true) // Include span context
.build()
);
§Structured Logging
Take full advantage of tracing’s structured logging capabilities:
use tracing::{info, instrument, warn};
#[instrument(fields(request_id = %request_id))]
fn process_order(order_id: u64, request_id: &str) {
info!(
order_id,
status = "processing",
amount = 99.99,
currency = "USD",
"Processing payment for order"
);
// Nested spans are automatically included
process_payment(order_id);
}
#[instrument]
fn process_payment(order_id: u64) {
warn!(order_id, "Payment gateway slow");
}
§Integration with Other Layers
Combine with other tracing layers for comprehensive observability:
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
use tracing_better_stack::{BetterStackLayer, BetterStackConfig};
tracing_subscriber::registry()
// Better Stack for production logging
.with(BetterStackLayer::new(
BetterStackConfig::builder("host", "token").build()
))
// Console output for local development
.with(fmt::layer().pretty())
// Environment-based filtering
.with(EnvFilter::from_default_env())
.init();
§How It Works
- Event Collection: The layer intercepts tracing events and converts them to log events
- Batching: Events are collected into batches (configurable size and timeout)
- Serialization: Batches are serialized to MessagePack or JSON
- Async Sending: Batches are sent asynchronously to Better Stack’s HTTP API
- Retry Logic: Failed requests are retried with exponential backoff
- Graceful Degradation: Errors are logged but never panic or block your application
§Performance Considerations
- Batching: Reduces network overhead by sending multiple logs in a single request
- Async Processing: All network I/O happens in background tasks
- MessagePack: ~30-50% more compact than JSON, reducing bandwidth usage
- Bounded Buffers: Memory usage is controlled via batch size limits
- Fail-Open: If Better Stack is unreachable, logs are dropped without affecting your app
§Error Handling
This crate is designed to never panic or interfere with your application:
- Network errors are logged to stderr and retried
- Serialization errors are logged and the batch is dropped
- Full batches trigger an immediate send
- The layer continues working even if Better Stack is down
Structs§
- Better
Stack Config - Configuration for the Better Stack tracing layer.
- Better
Stack Config Builder - Builder for creating a
BetterStackConfig
with a fluent API. - Better
Stack Layer - A tracing layer that sends log events to Better Stack.
Enums§
- Better
Stack Error - Error types that can occur when using the Better Stack tracing layer.
Type Aliases§
- Result
- Convenience type alias for Results with BetterStackError.