tracing-best-practices

Enforces structured tracing and logging standards for Rust code using the tracing crate.

1.6k|73|Updated Mar 13, 2025
One-click install
npx skills add https://github.com/UniClipboard/UniClipboard --skill tracing-best-practices
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: tracing-best-practices
Source: https://github.com/UniClipboard/UniClipboard/tree/main/.agents/skills/tracing-best-practices
Command: npx skills add https://github.com/UniClipboard/UniClipboard --skill tracing-best-practices

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Rust projects using the tracing crate often suffer from inconsistent span usage, silent functions with no log output, leaked secrets in logs, and broken async span propagation. This Skill enforces a single, consistent set of tracing standards whenever you write, modify, or review Rust code involving spans, events, or subscribers.

Core Features & Use Cases

  • Span and Event Standards: Defines where #[instrument] spans are required (entry layers, usecases, external boundaries) and where they are forbidden (hot paths, pure utilities), plus the rule that every span must contain at least one event.
  • Async-Safe Patterns: Provides three correct patterns for span lifecycle in async code (#[instrument], .instrument(span), inline async blocks) and forbids holding .entered() guards across .await points that break Send bounds.
  • Structured Field Conventions: Standardizes snake_case field names like trace_id, session_id, and error_kind, mandates skip() for secrets and large payloads, and defines level usage from ERROR to TRACE.
  • Use Case: When adding a new Tauri command or reviewing a state machine handler, apply this Skill to generate correctly instrumented code with propagated trace IDs, structured error events, and no sensitive data leakage.

Quick Start

Review my Rust function that handles pairing session events and add proper tracing instrumentation following the project standards.

Frequently Asked Questions about tracing-best-practices

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I use #[instrument] correctly in async Rust functions?

Apply #[instrument] with an explicit name, level, skip list for sensitive parameters, and structured fields like session_id. Ensure the function body emits at least one tracing event, since a span alone produces no log output with tracing_subscriber::fmt.

How do I propagate tracing spans across tokio::spawn?

Use .in_current_span() on the spawned future or create a span and pass it via .instrument(span). Never hold an EnteredSpan guard across .await points, because EnteredSpan is not Send and will cause compilation failures in tokio::spawn.

Why does my #[instrument] function produce no log output?

The #[instrument] attribute creates a span, but tracing_subscriber::fmt only writes events to output. A function with no info!, debug!, or similar macro inside is invisible in logs, so always emit at least one event describing the outcome.

What parameters should I skip in #[instrument] attributes?

Always skip self, secrets like passwords and tokens, large collections, binary data, and sensitive DTOs. The attribute records parameters via Debug by default, so unskipped secrets or large payloads will leak into log output.

When should I avoid using #[instrument] in Rust code?

Avoid it on pure utility functions without business semantics, high-frequency hot paths like per-poll loops, and functions with large sensitive parameters. Use sampled events or aggregate stats for hot paths instead of per-call spans.

How should errors be logged with the tracing crate?

Log errors once at the discovery boundary with structured fields like error_kind, error_code, retryable, and relevant context IDs. Do not repeat the same error at every stack layer; upper layers should propagate via ? or log only business outcomes.