agentsclimarketplace

Rust tracing

Skill dawidpereira/rust-skills/skills/rust-tracing

Curated Rust skill files for Claude Code: ownership, async, errors, types, architecture, DDD, and more

Install
npx -y skills add dawidpereira/rust-skills --skill rust-tracing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Rust observability with tracing — structured logging, spans, subscribers, and instrumentation. Use when choosing between tracing and log, setting up subscribers and layers, adding #[instrument] to functions, configuring RUST_LOG, instrumenting async code (.instrument() vs span.enter()), integrating tower-http or sqlx middleware, protecting sensitive data in logs, or preparing tracing for production with OpenTelemetry. Also use when reviewing code for logging quality or adding request correlation IDs.

SKILL.md

8.9 KB, as published. Nobody here has run it

Tracing & Observability

Core Question

What happened, and why, at every layer of this request?

Events say what happened. Spans say the context in which it happened. If you only emit events without spans, you lose the "why." tracing unifies both into one structured, async-aware API.


Error → Design Question

SymptomDon't Just SayAsk Instead
Logs are noise, nobody reads them"Add more log levels"What decisions will an operator make from this output?
span.enter() in async code"Use .instrument()"Does this span need to cross await points?
Sensitive data appears in logs"Filter it in the output"Should this field exist in the span at all?
No context in error logs"Add more fields"Should this be a span (context) rather than an event (fact)?
info! scattered everywhere"Logging is good practice"Which layer owns this observability concern?
Perf regression after adding spans"Remove some traces"Are you using compile-time filtering and non-blocking writers?

Quick Decisions

SituationReach ForWhy
New project, choosing a logging cratetracingStructured, span-aware, async-compatible, log-compat
Library cratetracing with log featureConsumers using log still see events
Dev/local outputfmt::layer().pretty()Human-readable, colored
Production JSON outputfmt::layer().json()Machine-parseable for log aggregators
Controlling verbosity at runtimeEnvFilter + RUST_LOGPer-module filtering without recompile
Stripping debug/trace from releasetracing max_level_info featureZero cost for disabled levels at compile time
Instrumenting an async function#[instrument]Auto-creates span, captures args, async-safe
Propagating span through .await.instrument(span)Span stays active across yield points
Entering a span in sync codelet _guard = span.enter()RAII guard, dropped at scope end
Axum/tower HTTP request tracingtower_http::trace::TraceLayerPer-request spans with method, URI, status, latency
SQL query tracingsqlx with tracing featureAutomatic spans for every query
Outbound HTTP tracingreqwest-tracingSpan per outbound request
Protecting sensitive fieldssecrecy::Secret<T> or RedactedPrevents accidental exposure in logs
Request ID / correlationExtract or generate UUID in span fieldTies all spans/events for one request
Sending traces to OTel collectortracing-opentelemetry layerBridges tracing spans to Jaeger/Tempo/Datadog
Writing traces to filestracing-appender + non_blockingRolling files without blocking the runtime
Testing that traces were emittedtracing-test + #[traced_test]Captures logs per-test with logs_contain!

The Async Span Problem

Never use span.enter() in async code. The guard is tied to the current thread — when the future yields at an .await and resumes on a different thread, the span context is wrong.

// Bad: guard held across await
async fn handle(req: Request) -> Response {
    let span = info_span!("handle_request");
    let _guard = span.enter();
    let data = fetch_data().await; // span context lost here
    process(data)
}

// Good: #[instrument] handles async spans correctly
#[instrument(skip(req))]
async fn handle(req: Request) -> Response {
    let data = fetch_data().await;
    process(data)
}

// Good: .instrument() for dynamic span names
async fn handle(req: Request) -> Response {
    let span = info_span!("handle_request", method = %req.method());
    async {
        let data = fetch_data().await;
        process(data)
    }
    .instrument(span)
    .await
}

Spawned tasks also need explicit span propagation:

let span = info_span!("background_job", job_id = %id);
tokio::spawn(
    async move { run_job().await }.instrument(span)
);

Log Levels

LevelUse ForExample
errorFailures requiring operator attentionDB connection lost, payment failed
warnDegraded but recoverableRetry succeeded, cache miss fallback
infoBusiness-significant eventsRequest handled, user created, deployed
debugDeveloper troubleshootingSQL text, parsed config, cache hit/miss
traceFine-grained flowLoop iterations, byte-level I/O

If you would wake someone at 3am for it, it is error. If you would mention it in a standup, it is info. Everything else is debug or trace.


Usage Scenarios

Scenario 1: "I'm starting a new Axum service and need logging" → Set up tracing_subscriber with fmt::layer() for dev and json() for production. Add TraceLayer to your router for per-request spans. Use #[instrument] on handlers. See references/setup.md for init patterns.

Scenario 2: "I have logs but can't tell which belong to the same request" → Extract or generate a request ID in middleware, add it as a span field. All events within that span tree carry the ID. See references/instrumentation.md for correlation patterns.

Scenario 3: "I need traces in Jaeger for production but plain text locally" → Use a layered subscriber: fmt::layer() for local, tracing-opentelemetry for production. Switch via config. See references/production.md for OpenTelemetry setup.


Reference Files

FileRead When
references/setup.mdCargo.toml deps, subscriber init (dev/prod), RUST_LOG syntax, EnvFilter, compile-time filtering
references/instrumentation.md#[instrument] options, tower-http/sqlx/reqwest middleware, correlation IDs, what to log by layer
references/structured-fields.mdField sigils (%, ?), naming conventions, error logging patterns, sensitive data protection
references/production.mdOpenTelemetry, file output, non-blocking writers, performance, testing, production checklist

Cross-References

WhenCheck
Span context across .await, Send boundsrust-async → Quick Decisions
Error logging, error chain displayrust-errors → Quick Decisions
Project Cargo.toml setup, lint defaultsrust-quality → Quick Decisions
Axum middleware and architecture patternsrust-architecture → Quick Decisions

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.