Monitoring- und Alerting-Strategien, die wirklich funktionieren
Alarmmüdigkeit sabotiert die Incident-Reaktion — baue deine Monitoring-Strategie auf SLIs, sinnvollen Schwellenwerten und umsetzbaren Alarmen auf.

Die meisten Monitoring-Setups scheitern nicht an fehlenden Daten, sondern daran, dass sie zu viel Rauschen erzeugen. Teams versinken in Alarmen, die keine Reaktion erfordern, und ignorieren irgendwann ihre Pager komplett. Effektives Monitoring beginnt damit, festzulegen, was wirklich zählt, Schwellenwerte zu setzen, die den tatsächlichen Einfluss auf die Nutzer widerspiegeln, und sicherzustellen, dass jeder Alarm einen klaren Reaktionsweg hat.
Die vier goldenen Signale
Googles SRE-Buch beschreibt vier Signale, die die meisten Monitoring-Anforderungen abdecken. Jeder Dienst sollte diese vier erfassen, bevor irgendetwas anderes hinzukommt.
// Express middleware that captures the four golden signals
import { Counter, Histogram, Gauge } from "prom-client";
// 1. Latency — how long requests take
const httpDuration = new Histogram({
name: "http_request_duration_seconds",
help: "Duration of HTTP requests in seconds",
labelNames: ["method", "route", "status_code"],
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
});
// 2. Traffic — how many requests per second
const httpRequests = new Counter({
name: "http_requests_total",
help: "Total number of HTTP requests",
labelNames: ["method", "route", "status_code"],
});
// 3. Errors — rate of failed requests
const httpErrors = new Counter({
name: "http_errors_total",
help: "Total number of HTTP errors",
labelNames: ["method", "route", "error_type"],
});
// 4. Saturation — how full your resources are
const activeConnections = new Gauge({
name: "http_active_connections",
help: "Number of active HTTP connections",
});
app.use((req, res, next) => {
activeConnections.inc();
const end = httpDuration.startTimer({
method: req.method,
route: req.route?.path ?? req.path,
});
res.on("finish", () => {
const labels = {
method: req.method,
route: req.route?.path ?? req.path,
status_code: res.statusCode.toString(),
};
end(labels);
httpRequests.inc(labels);
activeConnections.dec();
if (res.statusCode >= 500) {
httpErrors.inc({ ...labels, error_type: "server_error" });
}
});
next();
});Service-Level-Indikatoren (SLIs)
SLIs übersetzen Rohdaten aus Metriken in Qualitätswerte, die sich auf die Nutzererfahrung beziehen. Sie beantworten die Frage: Ist die Nutzererfahrung akzeptabel?
# Prometheus alerting rules based on SLIs
groups:
- name: sli-alerts
rules:
# Availability SLI: proportion of successful requests
- alert: HighErrorRate
expr: |
(
sum(rate(http_errors_total[5m]))
/
sum(rate(http_requests_total[5m]))
) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "Error rate exceeds 1% for 5 minutes"
runbook: "https://wiki.internal/runbooks/high-error-rate"
# Latency SLI: proportion of requests served within threshold
- alert: HighLatency
expr: |
(
sum(rate(http_request_duration_seconds_bucket{le="0.5"}[5m]))
/
sum(rate(http_request_duration_seconds_count[5m]))
) < 0.95
for: 5m
labels:
severity: warning
annotations:
summary: "Less than 95% of requests served within 500ms"Prinzipien für gute Alarme
Ein Alarm sollte jemanden nur dann wecken, wenn sofortiges menschliches Eingreifen nötig ist. Alles andere gehört auf ein Dashboard.
# ❌ Noisy alert — fires on any single error
- alert: AnyServerError
expr: http_errors_total > 0
labels:
severity: critical
# ✅ Meaningful alert — fires on sustained elevated error rate
- alert: ElevatedErrorRate
expr: |
(
sum(rate(http_errors_total[10m]))
/
sum(rate(http_requests_total[10m]))
) > 0.005
for: 10m # Must sustain for 10 minutes
labels:
severity: warning
annotations:
summary: "Error rate above 0.5% for 10 minutes"
impact: "Approximately {{ $value | humanizePercentage }} of users affected"
runbook: "https://wiki.internal/runbooks/elevated-errors"
dashboard: "https://grafana.internal/d/api-overview"Jede Alarm-Annotation sollte enthalten, was gerade passiert, wer betroffen ist, einen Link zum Runbook und einen Link zum passenden Dashboard. Wenn die Bereitschaftsperson erst nach Kontext suchen muss, ist der Alarm unvollständig.
Strukturiertes Logging zur Korrelation
Metriken zeigen dir, dass etwas nicht stimmt. Logs zeigen dir, warum. Strukturierte Logs mit Korrelations-IDs ermöglichen es, eine bestimmte fehlgeschlagene Anfrage über mehrere Dienste hinweg zu verfolgen.
// ❌ Unstructured logs — impossible to search or correlate
console.log("Error processing order for user " + userId);
// ✅ Structured JSON logs with correlation ID
import { randomUUID } from "crypto";
app.use((req, res, next) => {
req.correlationId = req.headers["x-correlation-id"] as string ?? randomUUID();
res.setHeader("x-correlation-id", req.correlationId);
next();
});
function log(level: string, message: string, context: Record<string, unknown>) {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level,
message,
correlationId: context.correlationId,
service: "order-service",
...context,
}));
}
// Usage in route handler
app.post("/orders", async (req, res) => {
log("info", "Processing order", {
correlationId: req.correlationId,
userId: req.body.userId,
itemCount: req.body.items.length,
});
try {
const order = await createOrder(req.body);
log("info", "Order created", {
correlationId: req.correlationId,
orderId: order.id,
});
res.json(order);
} catch (error) {
log("error", "Order creation failed", {
correlationId: req.correlationId,
error: error instanceof Error ? error.message : String(error),
});
res.status(500).json({ error: "Order processing failed" });
}
});Dashboard-Hierarchie
Strukturiere Dashboards in Schichten: eine übergeordnete Übersicht für die schnelle Erstbewertung, Dashboards auf Service-Ebene für die Untersuchung und Dashboards auf Komponentenebene für die detaillierte Fehlersuche.
Dashboard Hierarchy:
├── System Overview (RED metrics for all services)
│ ├── API Gateway (request rate, error rate, latency p50/p95/p99)
│ ├── Services (per-service health summary)
│ └── Infrastructure (CPU, memory, disk across clusters)
├── Service: Order API (detailed metrics)
│ ├── Endpoint breakdown (latency per route)
│ ├── Database queries (slow queries, pool utilization)
│ └── Downstream dependencies (timeout rates)
└── Component: PostgreSQL (deep dive)
├── Connection pool utilization
├── Query performance (p95, p99)
├── Replication lag
└── Disk I/O and buffer cache hit ratio
Die wichtigsten Erkenntnisse
- Beginne mit den vier goldenen Signalen — Latenz, Traffic, Fehler und Auslastung decken die meisten Anforderungen ab
- Definiere SLIs, die die Nutzererfahrung widerspiegeln — alarmiere bei anhaltender Verschlechterung, nicht bei einzelnen Fehlern
- Jeder Alarm braucht ein Runbook — wenn die Bereitschaftsperson erst recherchieren muss, was der Alarm bedeutet, ist er unvollständig
- Strukturierte Logs mit Korrelations-IDs — ermöglichen die Verfolgung einer einzelnen Anfrage über mehrere Dienste hinweg
- Staffele deine Dashboards — Übersicht für die Erstbewertung, Service-Ebene für die Untersuchung, Komponentenebene für die Fehlersuche
- Alarmiere bei Symptomen, nicht bei Ursachen — Nutzer interessieren sich für Fehlerraten und Latenz, nicht für CPU-Auslastung


