Claude Code & Prometheus: Metriken und Alerting für Node.js einrichten

Ein Service, der läuft, ist kein Service, der beobachtbar ist. Der Unterschied zeigt sich erst dann, wenn etwas schiefläuft: entweder hast du Metriken, die dir sagen, wann und wo — oder du hast einen Alarm vom Kunden. Prometheus ist der De-facto-Standard für Metriken in produktionsreifen Node.js-Anwendungen, und dieser Artikel zeigt, wie du ihn von Null an einrichtest: prom-client, Counter, Gauge, Histogram, den /metrics-Endpoint, Scrape-Config, AlertManager und ein Grafana-Dashboard.

Claude Code beschleunigt dabei den Boilerplate erheblich: Metrik-Definitionen, Alert-Regeln, PromQL-Abfragen für das Dashboard — alles was repetitiv und fehleranfällig ist, lässt sich generieren und direkt in den Kontext einbinden.

Claude Code Mastery — Produktionsreife Workflows auf Deutsch

Monitoring ist ein Teil davon. Der Kurs zeigt, wie du Claude Code vollständig in deinen Entwicklungsalltag integrierst — Agents, Hooks, MCP-Server, Multi-Agent-Workflows. Einmalig bezahlt, kein Abo.

Zum Kurs — Jetzt starten → Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht

1. Prometheus Grundkonzepte

Prometheus ist ein Pull-basiertes Monitoring-System: es fragt deine Anwendung regelmäßig nach Metriken, anstatt dass die Anwendung sie aktiv wegschickt. Das hat einen wichtigen Vorteil — der Monitoring-Stack ist von deiner Anwendungslogik entkoppelt. Deine App stellt einen /metrics-Endpoint bereit, Prometheus scrapt ihn in konfigurierbaren Intervallen.

Die vier Metrik-Typen, die du kennen musst:

Faustregel: Histogram für Latenz und Request-Größen, Counter für Ereignisse, Gauge für Zustände. Summary ist in den meisten Fällen die schlechtere Wahl gegenüber Histogram — Prometheus empfiehlt Histograms offiziell für Latenz-Metriken.

2. prom-client in Node.js einbinden

Das offizielle Prometheus-Client für Node.js ist prom-client. Installation:

npm install prom-client

Grundlegende Einrichtung in einer Express-Anwendung:

const express = require('express');
const client = require('prom-client');

const app = express();

// Default-Metriken aktivieren (Node.js-Prozess-Metriken)
const register = new client.Registry();
client.collectDefaultMetrics({ register });

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

app.listen(3000);

collectDefaultMetrics aktiviert automatisch eine Reihe nützlicher Node.js-Metriken: Heap-Verbrauch, Event-Loop-Lag, aktive Handles, CPU-Zeit. Das sind gute Basismetriken ohne zusätzliche Arbeit.

3. Counter, Gauge, Histogram, Summary

Counter

const httpRequestsTotal = new client.Counter({
  name: 'http_requests_total',
  help: 'Gesamtanzahl HTTP-Requests',
  labelNames: ['method', 'route', 'status_code'],
  registers: [register],
});

// In der Route:
app.get('/api/users', (req, res) => {
  // ... Handler-Logik
  httpRequestsTotal.inc({ method: 'GET', route: '/api/users', status_code: 200 });
  res.json(users);
});

Gauge

const activeConnections = new client.Gauge({
  name: 'active_connections',
  help: 'Anzahl aktiver WebSocket-Verbindungen',
  registers: [register],
});

// Bei Verbindungsaufbau:
activeConnections.inc();

// Bei Verbindungsabbau:
activeConnections.dec();

Histogram

const httpRequestDuration = new client.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Request-Dauer in Sekunden',
  labelNames: ['method', 'route', 'status_code'],
  buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
  registers: [register],
});

// Als Middleware:
app.use((req, res, next) => {
  const end = httpRequestDuration.startTimer();
  res.on('finish', () => {
    end({ method: req.method, route: req.path, status_code: res.statusCode });
  });
  next();
});

4. Custom Metrics

Über die Standard-Metriken hinaus willst du in der Regel anwendungsspezifische Metriken messen. Typische Beispiele:

// Business-Metriken
const ordersProcessed = new client.Counter({
  name: 'orders_processed_total',
  help: 'Verarbeitete Bestellungen gesamt',
  labelNames: ['status'],
  registers: [register],
});

const queueDepth = new client.Gauge({
  name: 'job_queue_depth',
  help: 'Anzahl wartender Jobs in der Queue',
  registers: [register],
});

const dbQueryDuration = new client.Histogram({
  name: 'db_query_duration_seconds',
  help: 'Dauer von Datenbankabfragen',
  labelNames: ['query_type', 'table'],
  buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],
  registers: [register],
});

Claude Code hilft dir dabei, die richtigen Metrik-Typen und sinnvolle Label-Schemas zu wählen. Beschreibe, was du messen willst, und es schlägt die passende Implementierung vor — inklusive der Bucket-Grenzen für Histograms, die für dein spezifisches Latenz-Profil sinnvoll sind.

5. /metrics Endpoint absichern

Der /metrics-Endpoint sollte nicht öffentlich erreichbar sein — er enthält interne Informationen über deinen Service. Zwei gängige Ansätze:

// Option A: Separater Port (empfohlen)
const metricsApp = express();
metricsApp.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});
metricsApp.listen(9090, '127.0.0.1'); // Nur intern erreichbar

// Option B: Bearer-Token-Schutz
app.get('/metrics', (req, res, next) => {
  const token = req.headers['authorization'];
  if (token !== `Bearer ${process.env.METRICS_TOKEN}`) {
    return res.status(401).end();
  }
  next();
}, async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});

Port-Binding: Wenn du einen separaten Port verwendest, binde ihn an 127.0.0.1, nicht an 0.0.0.0. Prometheus läuft im selben Netzwerk und erreicht ihn trotzdem — aber er ist von außen nicht erreichbar.

6. Scrape-Konfiguration

Prometheus muss wissen, welche Endpoints es scrapen soll. In prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'node-app'
    static_configs:
      - targets: ['localhost:9090']
    metrics_path: '/metrics'

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']

Mit Docker Compose:

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "127.0.0.1:9091:9090"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=15d'

7. AlertManager

Prometheus wertet Alert-Regeln aus und sendet Alerts an den AlertManager, der für das Routing, Grouping und die eigentliche Benachrichtigung zuständig ist. Alert-Regel-Datei alerts.yml:

groups:
  - name: node-app
    rules:
      - alert: HighErrorRate
        expr: |
          rate(http_requests_total{status_code=~"5.."}[5m])
          / rate(http_requests_total[5m]) > 0.05
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Fehlerquote über 5%"
          description: "{{ $value | humanizePercentage }} der Requests schlagen fehl"

      - alert: HighLatency
        expr: |
          histogram_quantile(0.95,
            rate(http_request_duration_seconds_bucket[5m])
          ) > 1
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "p95-Latenz über 1 Sekunde"

AlertManager-Konfiguration für Slack:

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

receivers:
  - name: 'slack-notifications'
    slack_configs:
      - api_url: '${SLACK_WEBHOOK_URL}'
        channel: '#alerts'
        title: '{{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'

8. Grafana-Dashboard bauen

Grafana visualisiert die Daten aus Prometheus. Nach der Einrichtung der Prometheus-Datasource (URL: http://prometheus:9090) kannst du Dashboards bauen. Vier unverzichtbare Panels für eine Node.js-Anwendung:

# Request-Rate (Requests/Sekunde)
rate(http_requests_total[5m])

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

# p95-Latenz
histogram_quantile(0.95,
  rate(http_request_duration_seconds_bucket[5m])
)

# Node.js Heap-Verbrauch
nodejs_heap_size_used_bytes / nodejs_heap_size_total_bytes

Claude Code kann komplette Grafana-Dashboard-JSON-Definitionen generieren. Beschreibe, welche Metriken du siehst willst und welches Layout du dir vorstellst — es produziert die Dashboard-JSON, die du direkt in Grafana importieren kannst.

9. PromQL-Grundlagen

PromQL ist die Abfragesprache von Prometheus. Die wichtigsten Funktionen:

"PromQL sieht zunächst komplex aus, aber 80% der Dashboards kommen mit vier Funktionen aus: rate(), histogram_quantile(), sum by() und avg_over_time(). Den Rest lernst du, wenn du ihn brauchst."

Ein vollständiges Beispiel — Fehlerquote nach Route, nur für Routen mit mehr als 10 Requests/Minute:

sum by (route) (
  rate(http_requests_total{status_code=~"5.."}[5m])
)
/
sum by (route) (
  rate(http_requests_total[5m])
)
> 0 and
sum by (route) (
  rate(http_requests_total[5m])
) > 10/60

Verwandte Artikel, die auf diesem Thema aufbauen:


Claude Code Mastery — von Monitoring bis zum produktiven Agenten

Prometheus ist ein Baustein. Im Kurs lernst du, wie du Claude Code vollständig in deinen Stack integrierst — Agents, Hooks, MCP-Server, Multi-Agent-Workflows. Vollständig auf Deutsch, einmalig bezahlt.

Jetzt starten → Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht

Kurs · Claude Code Mastery

Von Monitoring zum produktiven AI-Agenten

Prometheus. Agents. MCP. Hooks. Multi-Agent-Workflows. Alles auf Deutsch, einmalig bezahlt — kein Abo, keine Plattformabhängigkeit.

Jetzt einsteigen → Kursübersicht ansehen →

Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht