skills/logging-observability/SKILL.md
Structured logging, distributed tracing, and metrics for production applications. [What: OpenTelemetry setup, log level strategy, correlation IDs, SLI/SLO alerting thresholds, Grafana dashboard design, PagerDuty integration] [When: setting up production logging, adding observability to a service, debugging distributed systems, designing alerting, implementing traces/metrics/logs] [Keywords: logging, observability, OpenTelemetry, OTel, structured logs, distributed tracing, correlation ID, metrics, Grafana, Prometheus, PagerDuty, Winston, Pino, structlog, log levels, SLI, SLO, alerting] NOT for application performance profiling (use a profiler), load testing, or database query optimization.
npx skillsauth add curiositech/windags-skills logging-observabilityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Structured logging, distributed tracing, and metrics for production systems. Covers the full observability stack from log formatting to alert routing.
1. Log Level Assignment by Event Type
Event occurs →
├── System failure?
├── YES → Service cannot continue?
├── YES → FATAL (page immediately)
└── NO → ERROR (operation failed, will retry)
└── NO → Unexpected condition?
├── YES → WARN (circuit breaker, deprecation)
└── NO → Business event?
├── YES → INFO (user action, payment processed)
└── NO → Debug helper?
├── YES → DEBUG (DB queries, cache hits)
└── NO → TRACE (spans, fine-grained flow)
2. Observability Stack Choice by Scale
Request volume →
├── < 1000/min → Structured logs + simple metrics
├── < 10k/min → Add distributed tracing (10% sampling)
├── < 100k/min → Full OTel + head-based sampling
└── > 100k/min → Tail-based sampling + cardinality limits
3. Alert Threshold Setting
SLI established →
├── User-facing service?
├── YES → Start with 99% SLO (44min/month error budget)
└── NO → Start with 95% SLO (36hr/month error budget)
└── Historical data available?
├── YES → Set threshold at 95th percentile of normal operation
└── NO → Set conservative threshold, tune weekly for 1 month
4. Trace Sampling Decision
Performance impact →
├── Latency sensitive service?
├── YES → 1-5% sampling rate
└── NO → 10-20% sampling rate
└── Error debugging needed?
├── YES → Always sample errors (status=error)
└── NO → Uniform probability sampling
5. PII Handling Strategy
Field contains sensitive data →
├── Required for debugging?
├── YES → Hash or tokenize (preserve cardinality)
└── NO → Complete redaction
└── Regulatory compliance?
├── GDPR/CCPA → Allowlist approach only
└── PCI → Redact payment fields specifically
1. Alert Fatigue
2. PII Leakage
"password":, "ssn":, credit card regex3. Trace Orphaning
traceparent header propagation on outbound HTTP calls4. Log-and-Throw Duplication
5. Cardinality Explosion
Scenario: Payment service returning 500s sporadically. Need to trace through API Gateway → Payment Service → Bank API.
Step 1: Trace ID Recovery
# Customer reports failed payment at 14:35 UTC
# Find trace ID from customer-facing logs
grep -A5 -B5 "payment_failed" /var/log/api-gateway.log | grep "14:3[0-9]"
# Extract: trace_id: "abc123def456"
Step 2: Cross-Service Trace Following
# Follow trace through each service
kubectl logs payment-service | grep "abc123def456"
# Shows: bank_api_call_failed, status_code: 502, bank_error: "insufficient_funds"
# Verify bank API logs (if accessible)
curl -H "X-Trace-ID: abc123def456" https://bank-api/logs
Decision Point: Sampling trade-off encountered
Step 3: Root Cause Analysis
// Found in payment service code
logger.error({
trace_id,
bank_response_code: 502,
bank_error: "insufficient_funds",
our_retry_count: 3
}, "payment_processing_failed");
Resolution: Bank API returns 502 for business logic errors (insufficient funds). Change error handling to return 400 instead of retrying on 502.
Node.js Payment Service Implementation:
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL ?? 'info',
redact: {
paths: ['req.headers.authorization', 'body.cardNumber', '*.ssn'],
censor: '[REDACTED]'
}
});
// Correlation middleware
export function correlationMiddleware(req, res, next) {
const traceId = req.headers['x-trace-id'] ?? randomUUID();
res.setHeader('x-trace-id', traceId);
// AsyncLocalStorage context
requestContext.run({ traceId }, () => {
logger.info({
traceId,
method: req.method,
path: req.path,
userAgent: req.headers['user-agent']
}, 'request_received');
next();
});
}
Alert Noise Syndrome
Schema Drift
Sampling Blind Spots
This skill handles: Production observability, structured logging, distributed tracing, alerting strategy
Delegate elsewhere:
performance-optimization skill insteadinfrastructure-scaling skilldatabase-architect skillsecurity-architect skillcost-optimization skilldata-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.