tracing-throttle
High-performance log deduplication and rate limiting for the Rust tracing ecosystem.
Overview
tracing-throttle suppresses repetitive or bursty log events in high-volume systems. It helps you:
- Reduce I/O bandwidth from repetitive logs
- Improve log visibility by filtering noise
- Lower storage costs for log aggregation
- Prevent log backend overload during traffic spikes
The crate provides a tracing::Layer that deduplicates events based on their signature (level, message, and structured fields) and applies configurable rate limiting policies.
Features
- 🚀 High Performance: Sharded maps and lock-free operations
- 🎯 Flexible Policies: Count-based, time-window, exponential backoff, and custom policies
- 📊 Per-signature Throttling: Events with identical signatures are throttled together
- 💾 Memory Control: Optional LRU eviction to prevent unbounded memory growth
- 📈 Observability Metrics: Built-in tracking of allowed, suppressed, and evicted events
- 🛡️ Fail-Safe Circuit Breaker: Fails open to preserve observability during errors
- ⏱️ Suppression Summaries: Periodic emission of suppression statistics (coming in v0.2)
- 🔧 Easy Integration: Drop-in
tracing::Layercompatible with existing subscribers
Installation
Add this to your Cargo.toml:
[]
= "0.1.1"
= "0.1.41"
= "0.3.20"
Quick Start
use ;
use *;
use Duration;
// Create a rate limit filter with safe defaults
// Defaults: 100 events per signature, 10k max signatures with LRU eviction and a 30 second summary interval.
let rate_limit = new;
// Add it as a filter to your fmt layer
registry
.with
.init;
// Now your logs are rate limited!
for i in 0..1000
// Only the first 100 will be emitted
Observability & Metrics
Monitor rate limiting behavior with built-in metrics:
use ;
let rate_limit = builder
.with_policy
.build
.expect;
// ... after some log events have been processed ...
// Get current metrics
let metrics = rate_limit.metrics;
println!;
println!;
println!;
// Or get a snapshot for calculations
let snapshot = metrics.snapshot;
println!;
println!;
// Check how many unique signatures are being tracked
println!;
Available Metrics:
events_allowed()- Total events allowed throughevents_suppressed()- Total events suppressedsignatures_evicted()- Signatures removed due to LRU evictionsignature_count()- Current number of tracked signaturessuppression_rate()- Ratio of suppressed to total events (0.0 - 1.0)
Use Cases:
- Monitor suppression rates in production dashboards
- Alert when suppression rate exceeds threshold
- Track signature cardinality growth
- Observe LRU eviction frequency
- Validate rate limiting effectiveness
Fail-Safe Operation
tracing-throttle uses a circuit breaker pattern to prevent cascading failures. If rate limiting operations fail (e.g., panics or internal errors), the library fails open to preserve observability:
- Closed: Normal operation, rate limiting active
- Open: After threshold failures (default: 5), fails open and allows all events
- HalfOpen: After recovery timeout (default: 30s), tests if system has recovered
- Fail-Open Strategy: Preserves observability over strict rate limiting
This ensures your logs remain visible during system instability, preventing silent data loss.
Rate Limiting Policies
Count-Based Policy
Allow N events, then suppress all subsequent occurrences:
use Policy;
let policy = count_based.expect;
// Allows first 50 events, suppresses the rest
Time-Window Policy
Allow K events within a sliding time window:
use Duration;
use Policy;
let policy = time_window
.expect;
// Allows 10 events per minute
Exponential Backoff Policy
Emit events at exponentially increasing intervals (1st, 2nd, 4th, 8th, 16th, ...):
use Policy;
let policy = exponential_backoff;
// Useful for extremely noisy logs
Custom Policies
Implement the RateLimitPolicy trait for custom behavior:
use RateLimitPolicy;
use Instant;
;
Memory Management
By default, the layer tracks up to 10,000 unique event signatures with LRU eviction. Each signature uses approximately 150-250 bytes.
Typical memory usage:
- 10,000 signatures (default): ~1.5-2.5 MB
- 50,000 signatures: ~7.5-12.5 MB
- 100,000 signatures: ~15-25 MB
// Increase limit for high-cardinality applications
let rate_limit = builder
.with_max_signatures
.build
.expect;
// Monitor usage in production
let sig_count = rate_limit.signature_count;
let evictions = rate_limit.metrics.signatures_evicted;
📖 See detailed memory documentation for:
- Memory breakdown and overhead calculations
- Signature cardinality analysis and estimation
- Configuration guidelines for different use cases
- Production monitoring and profiling techniques
Performance
See BENCHMARKS.md for detailed measurements and methodology.
Run benchmarks yourself:
Examples
Run the included examples:
# Basic count-based rate limiting
# Demonstrate different policies
Roadmap
v0.1.0 (MVP)
✅ Completed:
- Domain policies (count-based, time-window, exponential backoff)
- Basic registry and rate limiter
tracing::Layerimplementation- LRU eviction with configurable memory limits
- Maximum signature limit with LRU eviction
- Input validation (non-zero limits, durations, reasonable max_events)
- Observability metrics (events allowed/suppressed, eviction tracking, signature count)
- Circuit breaker for fail-safe operation
- Memory usage documentation
- Comprehensive integration tests
- Mock infrastructure with test-helpers feature
- Extensive test coverage (unit, integration, and doc tests)
- Performance benchmarks (20M ops/sec)
- Hexagonal architecture (clean ports & adapters)
- CI/CD workflows (test, lint, publish)
v0.1.1 (Production Hardening)
✅ Completed:
- Graceful shutdown for async emitter with
EmitterHandle - Comprehensive shutdown testing (12 dedicated shutdown tests)
- Explicit shutdown requirement (no Drop implementation to prevent race conditions)
- Final emission support on shutdown
- Panic safety for emit functions with proper resource cleanup
- Structured error handling with
ShutdownErrorenum - Shutdown timeout support (default 10s, customizable)
- Improved error handling and diagnostics
- Biased shutdown signal prioritization for fast shutdown
- Cancellation safety documentation
v0.2.0 (Enhanced Observability)
- Active suppression summary emission
- Metrics adapters (Prometheus/OTel)
- Configurable summary formatting
- Memory usage telemetry
v0.3.0 (Advanced Features)
- Pluggable storage backends (Redis, etc.)
- Streaming-friendly summaries
- Rate limit by span context
- Advanced eviction policies
v1.0.0 (Stable Release)
- Stable API guarantee
- Production-ready documentation
- Optional WASM support
- Performance regression testing
Contributing
Contributions are welcome! Please open issues or pull requests on GitHub.
License
Licensed under the MIT License.