Skip to content
Back to skills

Observability Checklist

ASecurity

What good observability looks like — structured logs, trace spans, metrics, correlation ids, and the instrumentation rules that turn logs into answers. Use when adding a feature, reviewing a service, or debugging a prod issue.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 26, 2026
devopspythonrustgonodedebugging

Works with

  • cli

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add atuljha23/holocron --skill observability-checklist --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Observability Checklist?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Observability Checklist
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/atuljha23-observability-checklist/badge)](https://www.skillsdirectory.com/skills/atuljha23-observability-checklist)

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

Download with Pro
SKILL.md
---
name: observability-checklist
description: What good observability looks like — structured logs, trace spans, metrics, correlation ids, and the instrumentation rules that turn logs into answers. Use when adding a feature, reviewing a service, or debugging a prod issue.
---

# Observability checklist

The goal isn't logs — it's answering "what happened" in under five minutes at 2am. Design backward from the question.

## Logs

### Structured or nothing
- JSON (or logfmt), not free text.
- Every log has: `ts`, `level`, `service`, `request_id`, `msg`, and relevant fields.
- Fields are snake_case or camelCase — pick one per service. No mixing.
- Durations in milliseconds as numbers, not "took 2s" strings.

### Levels are a contract
- `error`: something failed the user can't recover from. Alert-worthy.
- `warn`: something unexpected but handled. Review-worthy.
- `info`: the shape of normal traffic. Sampling OK.
- `debug`: developer-only. Off in prod.
- Don't invent new levels.

### What to log
- Request entry (method, path, user, request_id).
- Outcome (status, duration).
- Branch decisions that matter (authz check, cache hit/miss, retry).
- Errors with the full context you need to reproduce.

### What NOT to log
- Secrets, tokens, passwords, PII — scrub before logging.
- The full request body by default. Specific fields, yes. Everything, no.
- Stack traces as separate lines — include as a `stack` field so they stay with the event.

## Traces

### Span per unit of work
- HTTP request handler = 1 span.
- Outbound call = child span.
- DB query = child span (with `db.statement` truncated / hashed, not raw if PII risk).
- Background job step = 1 span.

### Mandatory attributes
- `service.name`, `service.version`.
- For HTTP: `http.method`, `http.route`, `http.status_code`.
- For DB: `db.system`, `db.operation`.
- For errors: `exception.type`, `exception.message`.

### Propagation
- Every outbound request carries trace context headers.
- Every background job enqueues with trace context.
- A trace that ends at the HTTP edge and restarts at the worker is useless.

## Metrics

### RED for services
- **Rate** — requests per second, per endpoint.
- **Errors** — error rate, per endpoint.
- **Duration** — p50/p95/p99, per endpoint.

### USE for resources
- **Utilization** — % of capacity in use.
- **Saturation** — queue depth / wait time.
- **Errors** — failed operations.

### Cardinality discipline
- No unbounded tags (user_id, tenant_id, url with params). They explode your TSDB bill.
- Pre-aggregate cardinal dimensions; keep labels coarse.
- `http.route` (the template), not `http.url` (the instance).

## Correlation

- `request_id` in: logs, traces (as `request.id` attr), response headers, error payloads.
- `trace_id` in: logs (auto-injected by SDK), response headers for user bug reports.
- A user reporting "I got a 500" should give you enough to find the request — the `request_id` is visible and searchable.

## Per-language

### Node
- Pino or Winston with JSON transport.
- OpenTelemetry SDK (`@opentelemetry/sdk-node`).
- Prom-client for metrics.

### Python
- `structlog` with `ProcessorFormatter`.
- `opentelemetry-sdk` + `opentelemetry-instrumentation-*`.
- `prometheus_client`.

### Go
- `slog` (stdlib, Go 1.21+) with JSON handler.
- `go.opentelemetry.io/otel` + auto-instrumentation.
- `prometheus/client_golang`.

### Rust
- `tracing` + `tracing-subscriber` with JSON formatter.
- `opentelemetry-otlp`.
- `prometheus` crate.

## Anti-patterns

- "Log everything, we'll figure it out later" — the noise hides the signal you need.
- Traces without sampling — you'll drown; sample intelligently (head-based at edges, tail-based for errors).
- Metrics where logs would do — counting "user clicked button" 1M times/day is cheaper as a metric than a log.
- Logs where metrics would do — "latency: 247ms" as a log line is wasting money; it's a histogram.
- Alerts on everything — page only on symptoms that hurt users, not causes.

## Smells

- A single log line has more than ~10 fields — probably two events glued together.
- You use `grep` to find things — you should have a field + dashboard.
- Error messages are generic ("an error occurred") — they cost you the 2am minutes.
- `console.log` in prod code — belongs in a logger, tagged and leveled.

Attribution

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

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.