tracing-dedup
A Rust crate that deduplicates consecutive identical log events in tracing, showing a repeat count instead of spamming your logs.
What it does
When your application emits the same log message multiple times in a row, tracing-dedup will:
- Show the first occurrence
- Suppress subsequent identical messages
- Display "previous message repeated X times" when a different message appears
This keeps your logs clean and readable while preserving information about how many times each event occurred.
Example
use fmt;
use DeduplicatingFormatter;
Output:
2025-10-13T17:50:28.654623Z INFO simple: First message
previous message repeated 3 times
2025-10-13T17:50:28.654652Z INFO simple: Different message
Features
- Zero overhead when no duplicates: Only tracks state when consecutive duplicates occur
- Respects output destination: Works with stdout, files, or any custom writer
- Level-aware: Messages with different log levels (INFO vs WARN) are treated as distinct
- Target-aware: Same message from different modules/targets are treated as distinct
- Thread-safe: Uses proper locking for concurrent access
Installation
Add this to your Cargo.toml:
[]
= "0.1"
= "0.1"
= "0.3"
Usage
Basic usage (stdout)
use fmt;
use DeduplicatingFormatter;
fmt
.event_format
.init;
With custom writer (file output)
use File;
use fmt;
use DeduplicatingFormatter;
let log_file = create?;
fmt
.event_format
.with_writer
.init;
With custom formatting
You can wrap any formatter that implements FormatEvent:
use format;
use DeduplicatingFormatter;
let formatter = default
.with_level
.with_target
.compact;
fmt
.event_format
.init;
How it works
tracing-dedup implements the FormatEvent trait, wrapping an inner formatter. It:
- Extracts the message, level, and target from each event
- Compares with the previous event
- If identical: increments a counter and skips formatting
- If different: outputs the repeat count (if any) then formats the new event
This approach ensures that repeat count messages are written to the same destination as your logs (stdout, file, etc.) without triggering recursive logging.
Examples
Run the included examples:
# Basic example
# File output example
License
MIT OR Apache-2.0