tracing
24 Feb 2026println! debugging scales poorly. Traditional logging is better — but in async systems, logs alone aren’t enough. You
need structured context.
That’s what tracing provides.
What Problem Does tracing Solve?
Structured, contextual logging with:
- Spans
- Events
- Fields
- Async awareness
It models execution flow.
Minimal Example
Cargo.toml
[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"main.rs
use tracing::{info, span, Level};
use tracing_subscriber;
fn main() {
tracing_subscriber::fmt::init();
let span = span!(Level::INFO, "startup", version = "1.0");
let _enter = span.enter();
info!("application started");
}This prints structured logs with metadata.
What’s Actually Happening?
tracing separates:
- Instrumentation (in your code)
- Subscribers (output behavior)
This means:
- Logs
- JSON output
- Distributed tracing
- Metrics
All can be layered without rewriting call sites.
Where It Fits
Use tracing when:
- You write async services
- You need request-scoped context
- You care about observability
It shines with Tokio.
Trade-offs
Pros
- Structured fields
- Async-aware
- Pluggable backends
Cons
- More complex than
log - Requires setup
Should You Use It?
If your system has concurrency or complexity:
Yes.
Logs without context are noise.