# Monitoring Audit

> Observability audit — logging, error tracking, health endpoints, alerting, runbooks. Deep-dive for /launch-check monitoring.

- Skill: `me2resh/monitoring-audit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add me2resh/monitoring-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/me2resh/monitoring-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: me2resh (https://skillmd.com/u/me2resh)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/me2resh/monitoring-audit

---


## Writing rule

When this skill writes a durable artifact, read .claude/rules/writing-standard.md. Use the controlled technical writing profile.

# /monitoring-audit — Observability & Incident Readiness

Deep-dive observability analysis. Checks that production issues will be detected, alerted on, and resolvable. Invoke when `/launch-check`'s monitoring row shows WARN or FAIL.

## Observability Pillars

| Pillar | Question | What to look for |
|--------|----------|-----------------|
| **Logs** | Can you see what happened? | Structured logging, log levels, no PII in logs |
| **Metrics** | Can you measure what's happening? | Request counts, latency, error rates, business metrics |
| **Traces** | Can you follow a request end-to-end? | Distributed tracing, correlation IDs |
| **Alerts** | Will you know when something breaks? | Alerting rules, on-call, PagerDuty/OpsGenie |

## Process

### Step 1: Error tracking

- Grep for error tracking SDK (Sentry, Datadog, Bugsnag, LogRocket, Rollbar)
- Check initialization: is the SDK configured with the correct DSN/API key (env var, not hardcoded)?
- Check error boundaries (React ErrorBoundary, Vue errorHandler, global uncaughtException handler)
- Check if source maps are uploaded to the error tracker for readable stack traces

### Step 2: Health endpoints

- Check for a health check route (`/health`, `/healthz`, `/api/health`, `/_health`)
- Check what the health endpoint verifies (just "alive"? database connectivity? external service reachability?)
- Check for a readiness probe separate from liveness (Kubernetes-style)

### Step 3: Logging

- Check for a logging library (winston, pino, bunyan, python logging, structured logging)
- Check if logs are structured (JSON) or unstructured (console.log with string concatenation)
- Check for appropriate log levels (error, warn, info, debug) — not everything at `console.log`
- Check that sensitive data (passwords, tokens, PII) is NOT logged

### Step 4: Alerting and incident response

- Check for alerting configuration (CloudWatch Alarms, Datadog monitors, PagerDuty rules)
- Check for a runbook (`docs/runbook.md`, `docs/incident-response.md`, `RUNBOOK.md`)
- Check for a status page configuration (Statuspage.io, Instatus, or self-hosted)

### Step 5: Output

```
MONITORING AUDIT — <project> @ <sha>

| # | Pillar | Status | Finding |
|----|--------|--------|---------|
| M1 | Error tracking | PASS | Sentry configured in lib/sentry.ts, source maps uploaded |
| M2 | Health endpoint | FAIL | No /health route found |
| M3 | Logging | WARN | Using console.log (unstructured), no log levels |
| M4 | Alerting | WARN | No alerting rules found in code or IaC |
| M5 | Runbook | FAIL | No runbook or incident response doc |

Incident readiness: NOT READY (2 fails — health endpoint and runbook are minimum viable)

Priority fixes:
  1. [ ] Add GET /health returning { status: "ok", db: "connected" }
  2. [ ] Create docs/runbook.md with deployment, rollback, and common-issue procedures
  3. [ ] Replace console.log with structured logger (pino recommended for Node.js)
```

## Persist the run + render trend

After printing the findings table, persist via the shared audit-history lib so the monitoring trend across runs becomes legible. See `docs/agdr/AgDR-0019-audit-artefact-persistence.md`.

### Resolve project name + score + verdict

`<project-name>` from `apexyard.projects.yaml` (or basename + `/handover` reminder if unregistered).

Score: `score = max(0, 100 - 25*critical - 10*high - 3*medium - 1*low)`. Verdict by worst-severity: critical/high → `fail`, medium → `conditional`, low/none → `pass`. Legacy "Incident readiness" two-state: NOT READY → `fail`, READY → `pass`.

### Persist + render

```bash
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-audit-history.sh"

# Lowercase severity in the payload — the lib expects critical/high/medium/low/info.
payload=$(mktemp); cat > "$payload" <<'EOF'
{
  "schema_version": 1,
  "findings": [
    {"id": "M2", "severity": "critical", "status": "open", "summary": "No error tracking SDK detected; uncaught errors are silent"},
    {"id": "M3", "severity": "high",     "status": "open", "summary": "No /health endpoint; load balancer can't detect hung instance"},
    {"id": "M4", "severity": "critical", "status": "open", "summary": "No alerting rules; nothing pages on-call"}
  ]
}
EOF

# Body: per templates/audits/monitoring-audit.md
body=$(mktemp); cat > "$body" <<'EOF'
... (filled-in body — findings table + Priority fixes) ...
EOF

ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
audit_run_persist "<project-name>" "monitoring-audit" "$ts" "fail" 35 "$body" < "$payload"
rm -f "$payload" "$body"

audit_render_trend "<project-name>" "monitoring-audit" 5
```

### Opt-in commit

```bash
touch projects/<name>/audits/monitoring-audit/.audit-history-tracked
```

## Rules

1. **Auto-PASS for projects not yet in production.** Pre-launch monitoring gaps are expected — flag them as "set up before first deploy" rather than "FAIL."
2. **Check IaC too.** Alerting rules might be in Terraform, CloudFormation, or CDK files rather than application code.
3. **Don't require all four pillars.** Logs + error tracking + health endpoint is the minimum. Distributed tracing and detailed metrics are "nice to have" for most teams.
4. **Be specific about what the health endpoint should check** — "returns 200" is table stakes; checking database connectivity is the real test.
5. **Always persist via the lib.** The persist step runs regardless of opt-in commit state.
6. **Severity vocabulary in the JSON is lowercase.** The lib expects `critical`/`high`/`medium`/`low`/`info`.

---

*Part of [ApexYard](https://github.com/me2resh/apexyard) — multi-project SDLC framework for Claude Code · MIT.*

