rust.missing_tracing
Observability
Low
Detects code without tracing instrumentation.
Why It Matters
Section titled “Why It Matters”Without distributed tracing:
- Blind debugging — No visibility into request flow
- Lost time — Can’t identify where latency comes from
- Blame games — Can’t tell which service caused the issue
- Incident chaos — Production problems take hours to diagnose
Tracing is essential for operating distributed systems.
Example
Section titled “Example”// ❌ Beforeasync fn handle_request(req: Request) -> Response { let user = get_user(req.user_id).await; let data = fetch_data(user.id).await; process(data).await}No visibility into what happened during the request.
// ✅ Afteruse tracing::{instrument, info};
#[instrument(skip(req))]async fn handle_request(req: Request) -> Response { info!(user_id = %req.user_id, "handling request");
let user = get_user(req.user_id).await; let data = fetch_data(user.id).await; process(data).await}
#[instrument]async fn get_user(user_id: UserId) -> User { // Automatically creates span with function name and args}What Unfault Detects
Section titled “What Unfault Detects”- Public async functions without
#[instrument] - Request handlers without tracing
- Missing span creation in service boundaries
Auto-Fix
Section titled “Auto-Fix”Unfault adds #[instrument] attributes to functions.
Tracing Setup
Section titled “Tracing Setup”use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
fn init_tracing() { tracing_subscriber::registry() .with(tracing_subscriber::fmt::layer()) .with(tracing_subscriber::EnvFilter::from_default_env()) .init();}
// With OpenTelemetryuse tracing_opentelemetry::OpenTelemetryLayer;use opentelemetry::sdk::trace::TracerProvider;
fn init_otel_tracing() { let tracer = opentelemetry_jaeger::new_pipeline() .install_simple() .unwrap();
tracing_subscriber::registry() .with(OpenTelemetryLayer::new(tracer)) .init();}Best Practices
Section titled “Best Practices”// Skip large fields#[instrument(skip(password, body))]async fn login(username: &str, password: &str) { }
// Add custom fields#[instrument(fields(request_id = %req.id))]async fn handle(req: Request) { }
// Error logging#[instrument(err)]async fn fallible() -> Result<(), Error> { }