一键导入
logging-and-observability
Set up structured logging, distributed tracing, and metrics dashboards. Covers the three pillars of observability for any tech stack.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Set up structured logging, distributed tracing, and metrics dashboards. Covers the three pillars of observability for any tech stack.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Full WCAG 2.2 AA accessibility audit procedure. Goes beyond the reference checklist with step-by-step testing methodology, tooling, and remediation guidance.
Design a RESTful API from requirements. Use when creating a new API, adding endpoints, or restructuring an existing API. Produces endpoint specifications, schemas, and implementation guidance.
Assess system architecture, identify risks and bottlenecks, document decisions with ADRs. Covers modular monolith, microservices, event-driven, and serverless patterns.
Shift Left quality gates, feature flag pipelines, and deployment automation. Use when setting up or modifying build and deploy pipelines, or when establishing quality gates for a project.
Perform a thorough code review with structured feedback. Use when reviewing pull requests, code submissions, or when you want a quality check on your code. Covers correctness, security, performance, readability, and maintainability.
Reduce complexity while preserving exact behavior. Use when code works but is harder to read or maintain than it should be. Applies Chesterton's Fence — understand the code before simplifying it.
| name | logging-and-observability |
| description | Set up structured logging, distributed tracing, and metrics dashboards. Covers the three pillars of observability for any tech stack. |
Observability tells you what your system is doing — and why it's misbehaving — without deploying new code. It rests on three pillars: logs (discrete events), traces (request paths across services), and metrics (aggregated measurements). Most teams start with logs, slap on metrics later, and never get tracing working. This skill sets up all three from the start so you're not reverse-engineering production failures.
Structured logging replaces "printf debugging in production" with queryable, machine-readable events. Distributed tracing connects the dots across service boundaries. Metrics give you the 10,000-foot view with dashboards and alerts. Together, they let you answer "is it broken?", "where is it broken?", and "why is it broken?" — in that order.
console.log / Logger.info with structured loggingWhen NOT to use: Quick prototypes or throwaway scripts where nobody will be on-call. If the code won't run in production, you don't need production observability.
Agree on a logging contract before writing a single log line.
Log format — always JSON:
{
"timestamp": "2025-01-15T10:23:45.123Z",
"level": "error",
"service": "order-service",
"trace_id": "abc123def456",
"span_id": "789ghi",
"message": "Payment processing failed",
"error": "TimeoutError: gateway did not respond within 5000ms",
"context": {
"order_id": "ord_42",
"user_id": "usr_99",
"amount_cents": 4999
}
}
Log level rules:
| Level | When to Use | Example |
|---|---|---|
error | Something failed and needs human attention | Payment gateway timeout, database unreachable |
warn | Something unexpected but handled — may need attention | Retry succeeded after 2 attempts, cache miss |
info | Normal operations worth recording | Request completed, user logged in, job started |
debug | Detailed information for troubleshooting (off in prod) | SQL query executed, cache key checked |
Rules:
trace_id and span_id when availableuser_id, not userId in one and user-id in another)Replace string-based logging with structured JSON output.
Node.js (Pino):
import pino from 'pino'
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label }),
},
timestamp: pino.stdTimeFunctions.isoTime,
redact: ['req.headers.authorization', 'body.password'],
})
// Usage — pass context as first argument
logger.info({ orderId: 'ord_42', userId: 'usr_99' }, 'Order placed')
logger.error({ err, orderId: 'ord_42' }, 'Payment failed')
Elixir (Logger with JSON formatter):
# config/config.exs
config :logger, :console,
format: {MyApp.JSONFormatter, :format},
metadata: [:request_id, :trace_id, :user_id]
# Attach metadata at the request boundary
Logger.metadata(request_id: conn.assigns[:request_id], user_id: current_user.id)
Logger.info("Order placed", order_id: order.id)
Python (structlog):
import structlog
structlog.configure(
processors=[
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer(),
],
)
log = structlog.get_logger()
log.info("order_placed", order_id="ord_42", user_id="usr_99")
Tracing connects a single user request across every service it touches. Use OpenTelemetry — it's the vendor-neutral standard.
Core concepts:
traceparent)Node.js (OpenTelemetry):
import { NodeSDK } from '@opentelemetry/sdk-node'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces',
}),
instrumentations: [getNodeAutoInstrumentations()],
serviceName: 'order-service',
})
sdk.start()
Correlation ID middleware:
import { context, trace } from '@opentelemetry/api'
function correlationMiddleware(req, res, next) {
const span = trace.getActiveSpan()
if (span) {
const traceId = span.spanContext().traceId
req.traceId = traceId
res.setHeader('X-Trace-Id', traceId)
}
next()
}
Metrics answer "how is the system doing right now?" Pick metrics that map to user experience, not internal implementation details.
The RED method (for request-driven services):
| Metric | What It Measures | Example |
|---|---|---|
| Rate | Requests per second | http_requests_total |
| Error | Error rate (% of requests) | http_errors_total / http_requests_total |
| Duration | Request latency (p50/p95/p99) | http_request_duration_seconds |
The USE method (for resources — CPU, memory, queues):
| Metric | What It Measures | Example |
|---|---|---|
| Utilization | % of resource in use | cpu_usage_percent |
| Saturation | Queued work | thread_pool_queue_length |
| Errors | Resource errors | disk_errors_total |
Prometheus metrics example:
import { Counter, Histogram } from 'prom-client'
const httpRequestsTotal = new Counter({
name: 'http_requests_total',
help: 'Total HTTP requests',
labelNames: ['method', 'route', 'status'],
})
const httpRequestDuration = new Histogram({
name: 'http_request_duration_seconds',
help: 'HTTP request duration in seconds',
labelNames: ['method', 'route'],
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
})
Cardinality management — the silent killer of metrics systems:
Start with one overview dashboard per service. Add drill-down dashboards only when the overview isn't enough.
Grafana dashboard layout:
Row 1: Traffic Overview
- Request rate (requests/sec)
- Error rate (%)
- Availability (% of non-5xx responses)
Row 2: Latency
- p50 response time
- p95 response time
- p99 response time
Row 3: Resources
- CPU usage
- Memory usage
- Active connections / thread pool
Row 4: Dependencies
- Database query latency
- External API latency
- Cache hit rate
Dashboard rules:
Alerts tell you when SLOs are at risk. Bad alerts page people for things they can't act on.
SLI → SLO → Alert chain:
SLI: 99th percentile latency of /api/orders
SLO: p99 latency < 500ms, measured over 30-day rolling window
Error budget: 0.1% of requests can exceed 500ms
Alert: Fire when burn rate exceeds 10x (consuming 10% of budget in 1 hour)
Alert rules:
Prometheus alert example:
groups:
- name: order-service
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{service="order-service", status=~"5.."}[5m]))
/ sum(rate(http_requests_total{service="order-service"}[5m]))
> 0.01
for: 5m
labels:
severity: critical
annotations:
summary: 'Error rate > 1% for order-service'
runbook: 'https://wiki.internal/runbooks/order-service-errors'
Confirm that all three pillars are working end-to-end.
Verification checklist:
| Rationalization | Reality |
|---|---|
| "We'll add observability later" | Later means after the first production incident when you have zero visibility. Set it up now. |
| "Logs are enough — we don't need tracing" | Logs tell you something happened. Tracing tells you where in the chain it happened. Both are necessary. |
| "We can just grep the logs" | Grepping works for one server. With 5+ instances, you need structured logs and a log aggregator. |
| "Metrics add overhead" | Prometheus-style metrics add microseconds of overhead. The cost of not having them is hours of debugging. |
| "We'll use DEBUG level everywhere to be safe" | DEBUG in production generates noise that drowns out real signals and inflates storage costs. |
| "Let's track everything — more data is better" | High-cardinality metrics blow up your metrics backend. Track what matters, not everything. |
trace_id when tracing is active