Transform hub-guide from a single-skill Hub monorepo guide into a comprehensive programming best-practice plugin covering all situations. Skills (26): - Core: engineering-principles, clean-code, clean-architecture, design-patterns, testing, error-handling, security, api-design, git-workflow, documentation, logging-observability, performance - Languages: typescript, python, rust, go - Frameworks: react-frontend, elysiajs, hono-backend, drizzle-database, nextjs - Infrastructure: docker, ci-cd, monitoring - Monorepo: monorepo, hub-guide (existing) Hooks: - SessionStart: auto-detect project type and activate relevant skills - PreToolUse (Write|Edit): inject language-specific rules per file type Reference files for deep dives: - clean-architecture/references/solid.md (SOLID + component principles) - design-patterns/references/catalog.md (full GoF catalog with examples) - testing/references/mocks.md (test double taxonomy) Restructure plugin to modern skills/ directory format.
181 lines
6.3 KiB
Markdown
181 lines
6.3 KiB
Markdown
---
|
|
name: logging-observability
|
|
description: Best practices for logging, metrics, tracing, alerting, and observability — structured logging, correlation IDs, Prometheus metrics, distributed tracing, and dashboard design. Use when adding logging, designing monitoring, setting up dashboards, debugging production issues, or whenever the user mentions "logging," "observability," "metrics," "tracing," "Prometheus," "Grafana," "Jaeger," "OpenTelemetry," "structured logging," or "alerting."
|
|
---
|
|
|
|
# Logging & Observability
|
|
|
|
## The Three Pillars
|
|
|
|
```
|
|
Logs — discrete events: "user logged in at 10:32:14"
|
|
Metrics — aggregatable numbers: 50 req/s, 200ms p99 latency
|
|
Traces — request lifecycle across services: "order #123 took 400ms total"
|
|
```
|
|
|
|
All three are needed. None replaces the others.
|
|
|
|
## Structured Logging
|
|
|
|
**Log in JSON format** — machine-readable, parsable, searchable.
|
|
|
|
```json
|
|
// ❌ Unstructured (text search grey area)
|
|
"User 123 created order 456 for $50.99"
|
|
|
|
// ✅ Structured (parseable, filterable)
|
|
{
|
|
"level": "info",
|
|
"time": "2025-07-25T10:32:14Z",
|
|
"message": "order created",
|
|
"service": "order-service",
|
|
"trace_id": "abc123def456",
|
|
"user_id": "123",
|
|
"order_id": "456",
|
|
"amount": 50.99,
|
|
"currency": "USD",
|
|
"duration_ms": 45
|
|
}
|
|
```
|
|
|
|
### Log Levels — Use Consistently
|
|
|
|
| Level | When | Example |
|
|
|-------|------|---------|
|
|
| **ERROR** | Something is broken. Needs human attention. | DB connection failed, payment declined |
|
|
| **WARN** | Something unexpected but recoverable. | Retry succeeded, rate limit approaching |
|
|
| **INFO** | Notable lifecycle events. User-triggered actions. | Order created, user signed up, scheduled job ran |
|
|
| **DEBUG** | Detailed context for debugging. Off in prod. | SQL query, request body, iteration details |
|
|
| **TRACE** | Very fine-grained. For deep debugging only. | Function entry/exit, loop iterations |
|
|
|
|
### What to Log
|
|
|
|
- **Every error** with stack trace, context, and correlation ID.
|
|
- **Every request** at INFO — method, path, status, duration.
|
|
- **Business events** — state transitions (order created → paid → shipped).
|
|
- **Auth events** — login success/failure, token refresh, privilege change.
|
|
- **Third-party calls** — external API call duration, status.
|
|
|
|
### What NOT to Log (Security)
|
|
|
|
- ❌ Passwords, tokens, secrets, API keys
|
|
- ❌ PII beyond necessity (email, phone, SSN, address)
|
|
- ❌ Full request/response bodies (except DEBUG, and even then — sanitize)
|
|
- ❌ Database connection strings
|
|
- ❌ Internal IPs in public-facing systems
|
|
|
|
## Metrics (Prometheus)
|
|
|
|
### RED Method (for services)
|
|
|
|
| Metric | What | Good |
|
|
|--------|------|------|
|
|
| **Rate** | Requests per second | Flat line — load |
|
|
| **Errors** | Failed requests / total | <1% (target), <0.1% (excellent) |
|
|
| **Duration** | Latency distribution | p50 < 100ms, p99 < 500ms |
|
|
|
|
### USE Method (for infrastructure)
|
|
|
|
| Metric | What |
|
|
|--------|------|
|
|
| **Utilization** | CPU, RAM, disk, network bandwidth |
|
|
| **Saturation** | Queue depth, swap usage, load average |
|
|
| **Errors** | Disk IO errors, packet drops, OOM kills |
|
|
|
|
### Four Golden Signals (Google SRE)
|
|
|
|
1. **Latency** — time to serve a request
|
|
2. **Traffic** — demand on the system (RPS, active users)
|
|
3. **Errors** — explicit failures + implicit (200 with wrong data)
|
|
4. **Saturation** — how "full" the system is
|
|
|
|
### Key Metrics to Expose
|
|
|
|
```prometheus
|
|
# Service
|
|
http_requests_total{method, path, status}
|
|
http_request_duration_seconds{quantile="0.99"}
|
|
errors_total{type}
|
|
active_users
|
|
|
|
# Business
|
|
orders_created_total{currency}
|
|
revenue_total
|
|
jobs_failed_total
|
|
|
|
# System
|
|
process_cpu_seconds_total
|
|
process_resident_memory_bytes
|
|
process_open_fds
|
|
```
|
|
|
|
## Distributed Tracing (Jaeger / OpenTelemetry)
|
|
|
|
- **Every request gets a `trace_id`** — propagate through headers (`x-trace-id`, `traceparent`).
|
|
- **Span per operation** — HTTP handler, DB query, external API call.
|
|
- **Annotate spans** — with relevant metadata (user ID, order ID, error details).
|
|
- **Sampling:** sample 100% of errors, 1-10% of successful requests.
|
|
- **Dapr/Jaeger:** auto-injects trace headers across sidecars.
|
|
|
|
```typescript
|
|
// OpenTelemetry example
|
|
const tracer = opentelemetry.trace.getTracer('order-service');
|
|
const span = tracer.startSpan('createOrder', { attributes: { orderId } });
|
|
try {
|
|
const result = await createOrder(input);
|
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
return result;
|
|
} catch (e) {
|
|
span.recordException(e);
|
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
throw e;
|
|
} finally {
|
|
span.end();
|
|
}
|
|
```
|
|
|
|
## Alerting
|
|
|
|
### Alert Design
|
|
|
|
- **Alert on symptoms, not causes** — "API error rate >1%" not "server CPU >90%"
|
|
- **Alert fatigue kills alerts** — every alert should need human action. If nobody acts, delete it.
|
|
- **Define SLOs** — 99.9% uptime, 95% requests <500ms. Alert when approaching breach.
|
|
- **Alert structure:**
|
|
```
|
|
Title: [P1] High error rate on order-service
|
|
Summary: Error rate = 5.2% (threshold: 1%) over last 5 minutes
|
|
Runbook: /runbooks/high-error-rate.md
|
|
Severity: P1 (critical, paging) / P2 (urgent, business hours) / P3 (warning, ticket)
|
|
```
|
|
|
|
### Common Alert Rules
|
|
|
|
| Rule | Severity | Threshold |
|
|
|------|----------|-----------|
|
|
| High error rate | P1 | >1% over 5min |
|
|
| High latency | P2 | p99 >1s over 5min |
|
|
| Service down | P1 | No metrics for 5min |
|
|
| Disk space | P2 | <10% free |
|
|
| Certificate expiring | P2 | <30 days |
|
|
| Rate limit hit rate | P3 | >10% of requests rate-limited |
|
|
|
|
## Observability Stack (for this repo)
|
|
|
|
| Component | Role |
|
|
|-----------|------|
|
|
| **Prometheus** | Metrics collection + alerting |
|
|
| **Jaeger** | Distributed tracing (all-in-one, OTLP receiver) |
|
|
| **Traefik** | Metrics endpoint (`--metrics.prometheus=true`) |
|
|
| **Docker labels** | Auto-discovery: `prometheus.io/scrape=true` |
|
|
| **Dashboard** | `/dashboard` — auto-refresh 15s, shows containers + traces + metrics |
|
|
|
|
## Anti-patterns
|
|
|
|
- ❌ **String interpolation in logs** — `log.info("User " + id + " logged in")` instead of structured fields
|
|
- ❌ **Logging in every function** — no, log at service boundaries and business events
|
|
- ❌ **No correlation IDs** — cannot trace request across services
|
|
- ❌ **Silent catch** — `catch (e) {}` swallows errors with no log
|
|
- ❌ **Alert fatigue** — 50 alerts daily means none are actionable
|
|
- ❌ **Dashboards without action** — beautiful dashboard but nobody knows what to do when a metric goes red
|