| Crates.io | rootcause-tracing |
| lib.rs | rootcause-tracing |
| version | 0.11.1 |
| created_at | 2026-01-03 13:20:30.890846+00 |
| updated_at | 2026-01-03 13:20:30.890846+00 |
| description | Tracing span support for the rootcause error reporting library |
| homepage | |
| repository | https://github.com/rootcause-rs/rootcause |
| max_upload_size | |
| id | 2020048 |
| size | 41,564 |
Tracing span support for the rootcause error reporting library.
This crate provides automatic tracing span capture for rootcause error reports. When an error occurs, it captures the current tracing span information, helping you understand which operation was being performed when the error occurred.
This is especially useful for:
Add to your Cargo.toml:
[dependencies]
rootcause = "0.11.1"
rootcause-tracing = "0.11.1"
tracing = "0.1.44"
tracing-subscriber = "0.3.22"
How it works: rootcause-tracing needs two things:
RootcauseLayer - A tracing layer that quietly captures span field values in the backgroundSpanCollector (optional) - A rootcause hook that automatically attaches captured spans to all rootcause reportsYou add RootcauseLayer to your tracing subscriber alongside your existing layers (formatting, filtering, log forwarding, etc.). Each layer operates independently - RootcauseLayer captures span data for error reports while your other layers continue their normal work.
Complete example with automatic span capture:
use rootcause::hooks::Hooks;
use rootcause_tracing::{RootcauseLayer, SpanCollector};
use tracing_subscriber::{layer::SubscriberExt, Registry};
fn main() {
// 1. Set up tracing with RootcauseLayer (required)
let subscriber = Registry::default()
.with(RootcauseLayer) // Captures span field values for error reports
.with(tracing_subscriber::fmt::layer()); // Regular tracing output
tracing::subscriber::set_global_default(subscriber)
.expect("failed to set subscriber");
// 2. Install hook to automatically capture spans for all errors
Hooks::new()
.report_creation_hook(SpanCollector::new())
.install()
.expect("failed to install hooks");
// 3. Use your app normally - spans are captured automatically
if let Err(e) = run_app() {
eprintln!("{}", e);
}
}
#[tracing::instrument]
fn run_app() -> Result<(), rootcause::Report> {
// Your application code
Ok(())
}
Output: Errors automatically show span context with field values:
● Failed to process request
├ src/main.rs:45:10
╰ Tracing spans
│ process_request{user_id=42 session="abc-123"}
╰─
If you prefer to attach spans selectively, use the SpanExt trait:
use rootcause_tracing::SpanExt;
#[tracing::instrument]
fn operation() -> Result<(), rootcause::Report> {
Err(rootcause::report!("failed"))
}
let result = operation().attach_span(); // Manually attach span to this error
Note: You still need RootcauseLayer in your subscriber setup (see above).
tracing_subscriber::fmt::init()If you currently use tracing_subscriber::fmt::init(), you need to set up your subscriber manually to add RootcauseLayer.
Before:
fn main() {
tracing_subscriber::fmt::init(); // Simple one-line setup
// ...
}
After:
use rootcause_tracing::RootcauseLayer;
use tracing_subscriber::{layer::SubscriberExt, Registry};
fn main() {
// Set up subscriber with multiple layers
let subscriber = Registry::default()
.with(RootcauseLayer) // Captures spans for error reports
.with(tracing_subscriber::fmt::layer()); // Console output (same as before)
tracing::subscriber::set_global_default(subscriber)
.expect("failed to set subscriber");
// ...
}
What changed: Instead of fmt::init() creating a subscriber for you, you create it yourself with Registry::default(). This lets you add multiple layers. Add RootcauseLayer alongside your existing layers (formatting, filtering, etc.).
With nested instrumented functions, each error captures the full span hierarchy from the active span to the root:
● Request failed
├ Tracing spans
│ │ handle_request{request_id="abc"}
│ ╰─
│
● Auth check failed
├ Tracing spans
│ │ check_auth{user_id=42}
│ │ handle_request{request_id="abc"}
│ ╰─
│
● Database error
╰ Tracing spans
│ query_db{query="SELECT..."}
│ check_auth{user_id=42}
│ handle_request{request_id="abc"}
╰─
Spans are ordered innermost to outermost. See examples/tracing_spans.rs for a complete example.
Control tracing span capture behavior at runtime:
ROOTCAUSE_TRACING - Comma-separated options:
leafs - Only capture tracing spans for leaf errors (errors without children)Example:
# Only capture tracing spans for leaf errors
ROOTCAUSE_TRACING=leafs cargo run
Customize when tracing spans are captured:
use rootcause::hooks::Hooks;
use rootcause_tracing::SpanCollector;
let collector = SpanCollector {
capture_span_for_reports_with_children: false, // Only leaf errors
};
Hooks::new()
.report_creation_hook(collector)
.install()
.expect("failed to install hooks");
rootcause-backtrace and rootcause-tracing serve complementary purposes:
| Feature | rootcause-backtrace | rootcause-tracing |
|---|---|---|
| What it captures | Stack frames / function calls | Tracing spans / logical operations |
| Best for | Understanding call paths | Understanding business logic flow |
| Information type | Technical: file:line, function names | Semantic: operation names, contextual metadata |
| Overhead | Moderate (symbol resolution) | Low (span metadata already exists) |
For maximum debugging power, use both together!
RootcauseLayer must be added to your tracing subscribertracing-subscriber::Registry)#[tracing::instrument] or manual span entry)