agentleFS
AlteriomAlteriom/ai-dev-skills/skills/monitoring/SKILL.md

monitoring

Skill0 starsChanged 3 months agoMITView on GitHub

Build production observability with metrics, logs, traces, and alerts using Prometheus, Grafana, Loki, and Sentry

  • Reads credentials
  • Installs packages

16 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use authentication, database and 9 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • MicrosoftSkill

    authentication

    Wire this in whenever the app uses or connects to data — records, a database, entities, per-user data, row-level security — or when the user wants sign-in, accounts, login, or protected pages. Rayfin data is always accessed as an authenticated user, so **data implies auth**; only a static page over public data skips it. The starter ships as a no-auth "hello world" that previews with no backend, and the full Fabric auth scaffolding is already in the project — this skill wires it in: AuthProvider + bootstrapAuth in main.tsx, the route guard in App.tsx, the sign-in page, sign-out, and the env/deploy requirement. Triggers: auth, authentication, sign in, sign-in, login, log in, sign out, logout, account, user, identity, protect route, require login, gated page, data, database, records, per-user, row-level security, who is the current user, Fabric auth, Entra.

    Also in 3 projects that use this

  • mijunriSkill

    database

    数据库脚本与操作规范。脚本放在 db_scripts 目录,遵循查询优化、事务、安全等实践。

    Also in 3 projects that use this

  • JohnJBorenSkill

    ci-cd

    CI/CD pipeline design, GitHub Actions, testing automation, and deployment strategies

    Also in 3 projects that use this

  • klauswgSkill

    performance

    Optimize web performance for faster loading and better user experience. Use when asked to "speed up my site", "optimize performance", "reduce load time", "fix slow loading", "improve page speed", or "performance audit".

    Also in 4 projects that use this

  • mrgoonieSkill

    devops

    Deploy to Cloudflare (Workers, R2, D1), Docker, GCP (Cloud Run, GKE), Kubernetes (kubectl, Helm). Use for serverless, containers, CI/CD, GitOps, security audit.

    Also in 3 projects that use this

  • AnthropicSkill

    documentation

    Write and maintain technical documentation. Trigger with "write docs for", "document this", "create a README", "write a runbook", "onboarding guide", or when the user needs help with any form of technical writing — API docs, architecture docs, or operational runbooks.

    Also in 4 projects that use this

The file

We split this skill into the rules it gives an agent

8 rules. 0 are common, 7 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 13 edited versions we read keep these.

  • 7

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill when:

    line 27
  2. Distinctive:

    Don't use: when you need:

    line 37
  3. Distinctive:

    Karpathy Principle: Simplicity First: - If your app fits on one server, don't set up distributed tracing.

    line 82
  4. Very specific:

    Karpathy Principle: Goal-Driven Execution: - After instrumenting, verify metrics appear: curl localhost:3000/metrics.

    line 167
  5. Distinctive:

    Karpathy Principle: When NOT to Use: - Don't send logs to Prometheus (use Loki).

    line 171
  6. Distinctive:

    Add Prometheus data source: Configuration → Data Sources → Prometheus

    line 176
  7. Distinctive:

    Create dashboard: + → Dashboard → Add panel

    line 177
  8. Distinctive:

    Before going to production:

    line 491

“Common” is measured: kept by at least 6 in 10 of the 13 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Monitoring - Production Observability

When to Use

Use this skill when:

  • Setting up observability for production systems
  • Debugging performance issues or errors
  • Creating dashboards for team visibility
  • Configuring alerts for incidents
  • Centralizing logs from multiple services
  • Tracking SLAs and uptime
  • Implementing distributed tracing

Don't use when you need:

  • Simple uptime checks (use UptimeRobot)
  • Local development debugging (use logs)
  • One-time performance profiling (use profilers)
  • Security auditing (use specialized security tools)

Karpathy Principle: Think Before Coding - Monitoring adds operational complexity. Start with simple uptime checks. Add metrics when you need them. Add logs when debugging requires it. Add tracing only for complex distributed systems. Don't build the full stack on day one.

Karpathy Principle: Trade-offs Everywhere - High-cardinality metrics (user IDs, UUIDs) explode storage. Prometheus guidelines: <10 labels per metric, <100k unique series. Violate this = OOM crash.

Prerequisites

Required Knowledge

  • System metrics (CPU, memory, disk, network)
  • HTTP metrics (request rate, latency, errors)
  • Log aggregation concepts
  • Alert management and on-call rotation
  • Time-series data basics

Required Tools

# Prometheus (metrics)
docker run -p 9090:9090 prom/prometheus

# Grafana (dashboards)
docker run -p 3000:3000 grafana/grafana

# Loki (logs)
docker run -p 3100:3100 grafana/loki

# Node Exporter (system metrics)
docker run -p 9100:9100 prom/node-exporter

# Sentry (error tracking)
# Sign up at sentry.io or self-host

Monitoring Levels

LevelToolsSetup TimeUse Case
MinimalUptimeRobot15 minSide projects
BasicUptime Kuma + Sentry1 hourStartups
StandardPrometheus + Grafana4 hoursProduction apps
AdvancedFull stack + Loki + Tracing1-2 daysMicroservices

Karpathy Principle: Simplicity First - If your app fits on one server, don't set up distributed tracing. Use Sentry for errors and Uptime Kuma for uptime. Complexity scales with need.

Karpathy Principle: Fail Fast, Fail Loud - Alert fatigue kills on-call teams. Set alert thresholds to fire 2-3 times/month, not 20/day. One critical alert beats 100 ignored warnings.

Core Workflows

1. Application Metrics (Prometheus)

Instrument Node.js App:

// npm install prom-client express
import express from 'express'
import promClient from 'prom-client'

const app = express()
const register = new promClient.Registry()

// Default metrics (CPU, memory, event loop)
promClient.collectDefaultMetrics({ register })

// Custom metrics
const httpRequestDuration = new promClient.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status_code'],
  buckets: [0.1, 0.5, 1, 2, 5],
})
register.registerMetric(httpRequestDuration)

const httpRequestTotal = new promClient.Counter({
  name: 'http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'route', 'status_code'],
})
register.registerMetric(httpRequestTotal)

// Middleware to track requests
app.use((req, res, next) => {
  const start = Date.now()
  
  res.on('finish', () => {
    const duration = (Date.now() - start) / 1000
    const route = req.route?.path || 'unknown'
    
    httpRequestDuration.observe(
      { method: req.method, route, status_code: res.statusCode },
      duration
    )
    
    httpRequestTotal.inc({
      method: req.method,
      route,
      status_code: res.statusCode,
    })
  })
  
  next()
})

// Metrics endpoint
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType)
  res.end(await register.metrics())
})

app.listen(3000)

Prometheus Configuration:

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'my-app'
    static_configs:
      - targets: ['localhost:3000']
    
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']

Karpathy Principle: Goal-Driven Execution - After instrumenting, verify metrics appear: curl localhost:3000/metrics. Check Prometheus targets: http://localhost:9090/targets. If targets are down, nothing works.

Karpathy Principle: Security By Design - Grafana/Prometheus admin dashboards are unauthenticated by default. Enable authentication immediately. Exposed metrics leak infrastructure topology.

Karpathy Principle: When NOT to Use - Don't send logs to Prometheus (use Loki). Don't trace with Prometheus (use Jaeger). Prometheus is for metrics, not everything.

2. Dashboards (Grafana)

Create Dashboard:

  1. Add Prometheus data source: Configuration → Data Sources → Prometheus
  2. Create dashboard: + → Dashboard → Add panel
  3. Query metrics:

Request Rate:

rate(http_requests_total[5m])

Error Rate:

rate(http_requests_total{status_code=~"5.."}[5m])

Latency (p95):

histogram_quantile(0.95, 
  rate(http_request_duration_seconds_bucket[5m])
)

CPU Usage:

100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

3. Error Tracking (Sentry)

Node.js Setup:

import * as Sentry from '@sentry/node'

Sentry.init({
  dsn: 'https://...@sentry.io/...',
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1, // 10% of transactions
})

app.use(Sentry.Handlers.requestHandler())
app.use(Sentry.Handlers.tracingHandler())

// Your routes
app.get('/', (req, res) => {
  res.send('Hello')
})

// Error handler
app.use(Sentry.Handlers.errorHandler())

app.use((err, req, res, next) => {
  res.status(500).json({ error: 'Internal server error' })
})

Python (FastAPI):

import sentry_sdk
from sentry_sdk.integrations.fastapi import FastApiIntegration

sentry_sdk.init(
    dsn="https://...@sentry.io/...",
    traces_sample_rate=0.1,
    integrations=[FastApiIntegration()],
)

app = FastAPI()

4. Centralized Logs (Loki)

Promtail Configuration (log shipper):

# promtail-config.yml
server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: app-logs
    static_configs:
      - targets:
          - localhost
        labels:
          job: my-app
          __path__: /var/log/app/*.log

Query Logs in Grafana:

{job="my-app"} |= "error" | json

Filter by level:

{job="my-app"} | json | level="error"

5. Alerts (Alertmanager)

Prometheus Alert Rules:

# alert.rules.yml
groups:
  - name: app-alerts
    interval: 30s
    rules:
      - alert: HighErrorRate
        expr: |
          rate(http_requests_total{status_code=~"5.."}[5m]) > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "High error rate detected"
          description: "{{ $labels.instance }} has {{ $value }}% error rate"
      
      - alert: HighLatency
        expr: |
          histogram_quantile(0.95,
            rate(http_request_duration_seconds_bucket[5m])
          ) > 2
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "High latency detected"
          description: "p95 latency is {{ $value }}s"
      
      - alert: ServiceDown
        expr: up{job="my-app"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Service is down"
          description: "{{ $labels.instance }} is unreachable"

Alertmanager Configuration:

# alertmanager.yml
global:
  resolve_timeout: 5m

route:
  receiver: 'team-slack'
  group_by: ['alertname', 'severity']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

receivers:
  - name: 'team-slack'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/...'
        channel: '#alerts'
        text: "{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}"

Common Patterns

1. Health Check Endpoint

app.get('/health', async (req, res) => {
  const checks = {
    database: false,
    redis: false,
  }
  
  try {
    await db.query('SELECT 1')
    checks.database = true
  } catch (error) {
    console.error('Database health check failed:', error)
  }
  
  try {
    await redis.ping()
    checks.redis = true
  } catch (error) {
    console.error('Redis health check failed:', error)
  }
  
  const healthy = Object.values(checks).every(Boolean)
  
  res.status(healthy ? 200 : 503).json({
    status: healthy ? 'healthy' : 'unhealthy',
    checks,
  })
})

2. RED Metrics (Rate, Errors, Duration)

const metrics = {
  requestRate: new promClient.Counter({
    name: 'http_requests_total',
    help: 'Total HTTP requests',
    labelNames: ['method', 'route', 'status'],
  }),
  
  errorRate: new promClient.Counter({
    name: 'http_errors_total',
    help: 'Total HTTP errors',
    labelNames: ['method', 'route'],
  }),
  
  requestDuration: new promClient.Histogram({
    name: 'http_request_duration_seconds',
    help: 'HTTP request duration',
    labelNames: ['method', 'route'],
    buckets: [0.1, 0.5, 1, 2, 5],
  }),
}

3. Structured Logging

import winston from 'winston'

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'my-app' },
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
})

// Usage
logger.info('User logged in', { userId: '123', ip: req.ip })
logger.error('Database connection failed', { error: err.message })

Common Pitfalls

1. No Alerts = No Monitoring

❌ Bad (dashboards nobody watches):

# Just Grafana dashboards, no alerts

✅ Good (alerts for critical issues):

# Alerts for downtime, high error rate, high latency

2. Alert Fatigue

❌ Bad (too many alerts):

- alert: CPUHigh
  expr: cpu_usage > 50  # Fires constantly!

✅ Good (actionable threshold):

- alert: CPUCritical
  expr: cpu_usage > 90
  for: 10m  # Sustained high usage

3. Missing Runbooks

❌ Bad (alert without context):

annotations:
  summary: "Database slow"

✅ Good (actionable runbook):

annotations:
  summary: "Database slow queries detected"
  description: "p95 query latency is {{ $value }}ms"
  runbook: "https://wiki.example.com/runbooks/slow-queries"

4. Storing All Logs Forever

❌ Bad (unbounded storage):

# No retention policy, logs grow forever

✅ Good (retention policy):

# Loki config
retention_period: 30d  # Keep logs for 30 days

5. No External Monitoring

❌ Bad (only internal checks):

# Only monitoring from inside the network

✅ Good (external checks):

# UptimeRobot or external Prometheus checking from outside

Verification Checklist

Before going to production:

Metrics

  • Application instrumented (request rate, errors, latency)
  • Infrastructure metrics collected (CPU, memory, disk)
  • Prometheus scraping all targets
  • Grafana dashboards created

Logs

  • Structured logging enabled (JSON format)
  • Log levels configured (ERROR, WARN, INFO)
  • Centralized log aggregation (Loki or ELK)
  • Log retention policy set (7-30 days)

Alerts

  • Critical alerts configured (service down, high error rate)
  • Alert severity levels defined (critical, warning, info)
  • Runbooks linked in alert annotations
  • On-call rotation configured

Error Tracking

  • Sentry or equivalent integrated
  • Error grouping and deduplication working
  • Source maps uploaded (for JS/TS)
  • Alert notifications to Slack/email

Integration with Other Skills

With Docker

  • Prometheus/Grafana/Loki in docker-compose
  • Container metrics with cAdvisor
  • Log collection from Docker containers

With Kubernetes

  • Prometheus Operator
  • Kube-state-metrics
  • Node Exporter DaemonSet

With Next.js / Node.js

  • prom-client for metrics
  • winston/pino for structured logs
  • Sentry SDK for errors

With FastAPI / Python

  • prometheus_client for metrics
  • structlog for structured logs
  • Sentry SDK for errors

References

Tools

Guides

Books

  • Site Reliability Engineering (Google)
  • Observability Engineering (Honeycomb)

Meta: Skill Quality

Completeness: ✅ Comprehensive (9/9 sections)
Karpathy Principles: ✅ 5 mentions
Code Examples: ✅ 15+ working examples
Production Tested: ✅ Used across Alteriom infrastructure
Last Updated: 2026-04-13

Coverage:

  • ✅ Application metrics (Prometheus)
  • ✅ Dashboards (Grafana)
  • ✅ Error tracking (Sentry)
  • ✅ Log aggregation (Loki)
  • ✅ Alerting (Alertmanager)
  • ✅ Health checks
  • ✅ RED metrics pattern
  • ✅ Structured logging
  • ✅ Common pitfalls

Skill Level: Intermediate to Advanced
Time to Learn: 4-6 hours
Prerequisites Met: System administration, metrics concepts

Known Gaps: None - production-ready

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.