Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Rust Observability

ASecurity

Logs are structured events with named fields, not formatted strings — tracing over log over println!, spans for async context, error chains logged once, and never a secret in a field. Use when adding or reviewing logging, tracing, or metrics in Rust, when println! or string-interpolated log messages appear, when a library installs a subscriber, or when the user asks how to instrument Rust code.

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentrustgobashgitapi

Works with

cliapi

Security Analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned 9/19/2026

$npx -y skills add rewrite-rs/skills --skill rust-observability --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rust Observability?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Rust Observability
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rewrite-rs-rust-observability/badge)](https://www.skillsdirectory.com/skills/rewrite-rs-rust-observability)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: rust-observability
description: Logs are structured events with named fields, not formatted strings — tracing over log over println!, spans for async context, error chains logged once, and never a secret in a field. Use when adding or reviewing logging, tracing, or metrics in Rust, when println! or string-interpolated log messages appear, when a library installs a subscriber, or when the user asks how to instrument Rust code.
---

# Rust Observability

A log line is a structured event with named fields, and a library never installs
a subscriber. This skill governs *how Rust code reports what it is doing*; what
an error type contains is `/rust-errors`, and span behaviour across cancellation
is `/async-rust`.

## A log line is an event, not a sentence

The core move: fields stay fields.
`error!(user_id, %path, "config load failed")` is queryable — `user_id` and
`path` are named columns. The interpolated form,
`error!("config load failed for user {user_id} at {path}")`, is a string
someone will later write a regex against. The difference shows up the first
time somebody needs "all failures for one user" — the moment logging either
pays for itself or does not.

## The three layers, and which to use

`println!` writes to stdout with no level, no filter, and no structure; it
belongs in a CLI producing output the user asked for, never in a library.
`log` is the older facade, right when the dependency budget is tight.
`tracing` is the default here: spans carry context across `.await` points,
which is the problem async code actually has.

## Naming events

`component.operation.state` — `config.load.failed`,
`pool.connection.acquired`. A consistent scheme is what makes a dashboard
possible; ad-hoc English messages are what make it impossible. Message
templates with placeholder syntax are one implementation of the field idea,
not the idea itself — a codebase already on templates is fine.

## Spans

`#[tracing::instrument]` on a function makes every event inside it inherit the
request context; `skip` keeps large or secret arguments out of the fields.
The rule: a span is a unit of work with a beginning and an end; an event is a
point in time.

## Levels and filtering

- `error!` — someone should look at this.
- `warn!` — something went wrong and the code handled it.
- `info!` — lifecycle events a reader wants without a bug.
- `debug!` / `trace!` — developer detail, off in production.

The boundary that matters is `error!`: because it means someone should look, a
handled and expected failure is `warn!` or `debug!` at most. `EnvFilter`
gives per-module control, and in a library, filtering is the whole story:

A library emits and never installs a subscriber. Installing one is global
state the application owns: the binary installs the subscriber exactly once,
and a library that installs one too fights for the global — a panic at
startup with `tracing`, a re-formatted event stream with `log`.

## Errors are logged once, with the chain

Log at the boundary that handles the error, not at every level it passes
through, and log the whole `source` chain rather than the top-level `Display`
alone, which is usually the least specific sentence available. What the error
type contains is `/rust-errors`.

## Never log a secret

Tokens, passwords, keys, personal data. The structural answer, not a review
habit: a newtype whose `Debug` and `Display` print a redacted form, so the
secret cannot be logged even by a future careless call site. The `?` form
prints via `Debug`, the `%` form via `Display`, and the bare form does not
compile for a custom type at all — every path redacted or absent:

```rust
struct ApiToken(String);

impl std::fmt::Debug for ApiToken {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("ApiToken(<redacted>)")
    }
}

impl std::fmt::Display for ApiToken {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("<redacted>")
    }
}
```

Whether the newtype is the right model is `/type-driven-design`.

## Overhead

Building an event that a filter discards still costs when the work is done
before the macro call. The macros take field values lazily, so do not
`format!` or allocate an argument eagerly for a `debug!` that is off in
production: `let summary = summarize();` before `debug!(?summary);` runs on
every call, level or not, while `debug!(summary = ?summarize());` runs only
when the event is enabled.

## Deferrals

What an error type contains and how it chains is `/rust-errors`. Whether the
redacting newtype is the right model is `/type-driven-design`. Span behaviour
across cancellation is `/async-rust`.

## Verification

```bash
cargo clippy --all-targets
rg 'println!|eprintln!' src/     # expect zero in a library
rg 'info!\("|warn!\("|error!\("' src/   # a message with interpolation and no fields is the smell
cargo test
```

Run clippy at the lint level the target repo configures —
`cargo clippy -- -D warnings` is the fallback only when the repo
configures no lints at all. The greps are a starting point, not a
verdict: a CLI printing its actual output is a legitimate `println!`.

Attribution

rewrite-rsrewrite-rs
View sourceSee grades on GitHubMore from rewrite-rs →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes
View all in development →