Next.js Produktions-Monitoring: Sentry, Logs und Alerts in der Praxis

Freitag, 21:17 Uhr – das Handy vibriert.
Im Team-Chat: „Zahlungsseite geht nicht“, „Bestellung fehlgeschlagen“, „weißer Bildschirm“. Lokal läuft alles. Server-Logs: nur „Internal Server Error“. Nutzer: Klick auf Bezahlen, dann hängt die Seite – nicht reproduzierbar.
Am Wochenende Vercel-Logs, Test-Deploys – Ursache: Zahlungs-SDK des Drittanbieters mit sporadischem Timeout in Produktion. Fehlersuche wie Nadeln im Dunkeln.
In Dev läuft Next.js butterweich – live öffnet sich Pandoras Box: sporadische SSR-500er, Edge-Fehler, API-Latenzen ohne Engpass.
Ursache: kein vollständiges Produktions-Monitoring. Dieser Artikel zeigt Sentry, strukturierte Logs, Performance und Alerts – mit kopierbaren Configs. Danach wissen Sie von Problemen, bevor die Nutzer es tun.
Warum Next.js ein spezielles Monitoring braucht
Die „Dreikopf“-Architektur von Next.js
Herkömmliche Frontend-Apps laufen nur im Browser, Fehler werden direkt in der DevTools-Konsole angezeigt. Next.js ist anders – die gleiche Anwendung läuft gleichzeitig in drei völlig unterschiedlichen Umgebungen:
- Client (Browser): Komponenten im Browser des Benutzers reagieren
- Server (Node.js): SSR-Rendering, API-Routen, Serveraktionen
- Edge-Netzwerk (Edge Runtime): Middleware, Edge-Funktionen
Eine Zahlungsfunktion kann Folgendes umfassen: clientseitige Formularvalidierung → Middleware-Authentifizierung → Serveraktionsaufruf → API-Route-Datenbankabfrage → Rückgabe an den Client zur Anzeige. Wenn ein Link unterbrochen wird, erkennt die herkömmliche Browserüberwachung nicht das vollständige Bild.
Letztes Jahr bin ich auf einen bizarren Fehler gestoßen: Benutzer haben berichtet, dass die Seite langsam geladen wird und dann 500 angezeigt wird. Das Browser-Netzwerk-Panel bestätigte, dass die Anfrage langsam war, konnte aber nicht genau sagen, wo. Nachdem ich das verteilte Tracing von Sentry integriert hatte, stellte ich fest, dass das serverseitige Rendering eine Drittanbieter-API aufrief, die von den üblichen 200 ms auf 8 Sekunden anstieg. Die clientseitige Überwachung würde dies niemals erkennen.
SSRs „Black-Box-Effekt“
Wenn das serverseitige Rendering fehlschlägt, sehen Benutzer oft nur eine leere 500-Seite. Kein Stack-Trace, kein Kontext, nichts.
Noch schlimmer sind Hydration-Fehler. Sie kennen vielleicht diese Warnung:
Warning: Expected server HTML to contain a matching <div> in <div>
Diese Fehler mögen in der Entwicklung geringfügig erscheinen, können aber in der Produktion zu vollständigen Fehlschlägen bei der Seiteninteraktion führen. Ohne Überwachung werden Sie diese nur durch passives Benutzer-Feedback entdecken, das besagt: „Die Seite reagiert nicht“.
Laut Vercel-Daten sind SSR-bezogene Fehler für etwa 35 % der Produktionsprobleme von Next.js verantwortlich. Dabei handelt es sich nur um Fehler – Leistungsprobleme wie die plötzliche Erhöhung der SSR-Zeit einer Komponente, die den Benutzern das Gefühl gibt, dass „die Seite langsamer geladen wird“, ohne eine Ahnung zu haben, wo der Engpass liegt, gehören nicht dazu.
Vier Säulen der umfassenden Überwachung
Eine zuverlässige Next.js-Überwachungslösung muss diese Grundlagen abdecken:
Fehlertracking
Nicht nur das Erfassen von Ausnahmen, sondern auch das Wissen darüber, wer den Fehler ausgelöst hat (Benutzerinformationen), in welcher Umgebung (Gerät, Browser, Netzwerk), welche Vorgänge sie ausgeführt haben (Breadcrumb-Trail) und was die zugehörigen Anforderungsparameter waren.
Leistungsüberwachung
Überschreitet LCP (Largest Contentful Paint) 2,5 Sekunden? Verlangsamen sich die API-Antwortzeiten? Welche Datenbankabfrage zieht die gesamte Anfrage nach unten?
Log-Management
Strukturierte Protokolle, die nach Zeit, Benutzer und Anforderungs-ID durchsuchbar sind. Hübsche Ausgabe für das Entwicklungs-Debugging, integriert in Protokollplattformen für die Produktionsanalyse.
Alert-Konfiguration
Sofortige Teambenachrichtigungen, wenn Fehlerraten Schwellenwerte überschreiten, Slack drängt beim ersten Auftreten auf neue Fehlertypen, automatische Warnungen bei Leistungsrückgängen.
Wenn diese vier vorhanden sind, sind Sie bei Produktionsproblemen nicht mehr blind. Gehen wir sie einzeln an.
Sentry-Integration in der Praxis – von Installation bis Tiefeinstellung
5-Minuten-Schnelleinrichtung
Die Next.js-Unterstützung von Sentry ist recht ausgereift und verfügt über einen offiziellen Assistenten für die automatische Konfiguration. Wirklich nur 5 Minuten:
# Install SDK
npm install @sentry/nextjs
# Run configuration wizard
npx @sentry/wizard@latest -i nextjs
Der Assistent stellt ein paar Fragen (Sentry-Projekt-DSN, ob Quellkarten hochgeladen werden sollen usw.) und erstellt dann automatisch drei Konfigurationsdateien:
sentry.client.config.ts– Browserumgebungsentry.server.config.ts– Node.js serverseitigsentry.edge.config.ts– Edge Runtime
Außerdem wird „next.config.js“ geändert, um das Webpack-Plugin von Sentry hinzuzufügen. Führen Sie den Assistenten einmal aus, die grundlegende Überwachung ist live.
Aber das ist erst der Anfang. Produktionsumgebungen erfordern eine verfeinerte Konfiguration.
Grundlagen der App-Router-Fehlererfassung
Wenn Sie App Router verwenden, achten Sie besonders auf die folgenden Bereiche:
Globale Fehlerbehandlung
Erstellen Sie „app/global-error.tsx“, die letzte Verteidigungslinie für App Router:
'use client';
import * as Sentry from '@sentry/nextjs';
import { useEffect } from 'react';
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Send to Sentry
Sentry.captureException(error);
}, [error]);
return (
<html>
<body>
<div style={{ padding: '2rem', textAlign: 'center' }}>
<h2>Etwas ist schiefgelaufen</h2>
<p>Wir haben den Fehler protokolliert und beheben ihn bald</p>
<button onClick={() => reset()}>Erneut versuchen</button>
</div>
</body>
</html>
);
}
Fehlererfassung bei Serveraktionen
Serveraktionen sind eine Killerfunktion von App Router, aber die Fehlerbehandlung wird oft übersehen:
'use server';
import * as Sentry from '@sentry/nextjs';
export async function createOrder(formData: FormData) {
return await Sentry.withServerActionInstrumentation(
'createOrder', // action name, shows up in Sentry
{
recordResponse: true, // record response data
},
async () => {
// Your business logic
const productId = formData.get('productId');
const order = await db.order.create({
data: { productId, userId: getCurrentUserId() },
});
return order;
}
);
}
Mit diesem Wrapper werden alle Fehler in Serveraktionen automatisch gemeldet und die Ausführungszeit verfolgt.
Optimierung der Produktionsumgebung
Nach der Integration von Sentry könnte Sie die Rechnung Ihres ersten Monats schockieren, da die Standardkonfiguration alle Ereignisse meldet. Sampling-Raten anpassen:
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
// Performance tracing sample rate
// Development 100%, production 10% (adjust based on traffic)
tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
// Session Replay sampling
replaysSessionSampleRate: 0.1, // 10% of normal sessions recorded
replaysOnErrorSampleRate: 1.0, // 100% of error sessions recorded
// Environment identifier
environment: process.env.NEXT_PUBLIC_VERCEL_ENV || 'development',
// Ignore specific errors
ignoreErrors: [
// Browser extension injected errors
'ResizeObserver loop limit exceeded',
// Third-party script errors
/chrome-extension/,
/^Non-Error promise rejection/,
],
});
TracesSampleRate-Einstellungsanleitung:
- Tägliche UV-Strahlung < 10K: 0,2 - 0,5
- Tägliche UV-Strahlung 10K-100K: 0,1 - 0,2
- Tägliche UV-Strahlung > 100 K: 0,05 – 0,1
Unser Projekt erreicht täglich etwa 30.000 UV-Strahlung, ist auf 0,15 eingestellt und nutzt etwa 60 % des monatlichen Sentry-Kontingents – ausreichend Probenabdeckung, ohne das Budget zu überschreiten.
Quellzuordnungen: Debugbar, ohne Code offenzulegen
Produktions-JavaScript-Code wird normalerweise minimiert und verschleiert. Fehlerstapel sehen folgendermaßen aus:```
at r.render (app.js:1:23456)
Völlig unleserlich. **Source Maps können verschleierten Code wieder dem Originalcode zuordnen**, aber durch die direkte Offenlegung von Source Maps geht Quellcode verloren.
Sentrys Ansatz: Quellkarten auf Sentry-Server hochladen, Benutzerbrowser können nicht darauf zugreifen, nur Sentry verwendet sie intern, um Stapel wiederherzustellen.
Konfigurieren Sie in CI/CD (Beispiel für GitHub-Aktionen):
```yaml
# .github/workflows/deploy.yml
- name: Upload Source Maps to Sentry
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: your-org
SENTRY_PROJECT: your-project
run: npm run build
Das Sentry-Plugin in „next.config.js“ verarbeitet den Upload automatisch. Denken Sie daran, „SENTRY_AUTH_TOKEN“ zu GitHub Secrets hinzuzufügen, verpflichten Sie sich nicht zum Repo.
Erweiterte Funktionen: Sitzungswiedergabe und verteilte Ablaufverfolgung
Session Replay ist meine Lieblingsfunktion – sie spielt Benutzeraktionen wie das Ansehen einer Aufzeichnung ab, um die Szene zu rekonstruieren.
Sobald ein Benutzer gemeldet hat: „Kann nicht auf die Schaltfläche „Zahlung“ klicken“. Ich schaute mir ihre Sitzungsaufzeichnung an und stellte fest, dass sie das iPad im Querformat verwendeten und die Zahlungstaste durch eine virtuelle Tastatur verdeckt war. Diese Art von Problem würde mit Fehlerprotokollen allein niemals gefunden werden.
Einfach zu aktivieren, zur Client-Konfiguration hinzufügen:
import * as Sentry from '@sentry/nextjs';
import { Replay } from '@sentry/nextjs';
Sentry.init({
integrations: [
new Replay({
maskAllText: false, // whether to hide all text
blockAllMedia: true, // whether to block all media
maskAllInputs: true, // hide form inputs (avoid leaking sensitive info)
}),
],
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
Verteilte Ablaufverfolgung kann den gesamten Lebenszyklus einer Anfrage verfolgen. Der Benutzer klickt auf die Schaltfläche → Frontend sendet Anfrage → API-Route fragt Datenbank ab → kehrt zum Rendern zum Frontend zurück, die Dauer jedes Schritts ist sichtbar.
Auch die Konfiguration ist nicht komplex. Stellen Sie lediglich sicher, dass Frontend und Backend dieselbe Sentry.init-Konfiguration verwenden. Sentry SDK übergibt automatisch „sentry-trace“ in Anforderungsheadern.
Benutzerdefinierter Kontext: Fehler aussagekräftiger machen
Standardmäßig weiß Sentry nur, dass ein Fehler aufgetreten ist. Durch benutzerdefinierten Kontext werden Fehlerberichte wertvoller:
import * as Sentry from '@sentry/nextjs';
// Set user information
Sentry.setUser({
id: user.id,
email: user.email,
username: user.username,
// Don't put sensitive info like passwords!
});
// Add business context
Sentry.setContext('purchase', {
orderId: '12345',
amount: 99.99,
paymentMethod: 'credit_card',
});
// Add tags (for filtering)
Sentry.setTag('feature', 'checkout');
Sentry.setTag('ab_test', 'variant_b');
So wissen Sie bei auftretenden Fehlern sofort, welcher Benutzer in welchem Geschäftsszenario den Fehler ausgelöst hat.
Realer Fall: Wir haben einmal festgestellt, dass ein Zahlungsfehler häufiger als erwartet auftrat, haben den Sentry-Kontext überprüft und festgestellt, dass es sich bei allen um „ab_test: variant_b“-Benutzer handelte. Es wurde ein Fehler im neuen Zahlungsfluss des A/B-Tests festgestellt und diese Variante sofort deaktiviert, um größere Verluste zu vermeiden.
Protokollverwaltung – Damit Protokolle für Sie arbeiten
console.log ist nicht genug
Schon früh habe ich es auch geliebt, überall „console.log“ zu verteilen. Fühlte sich zum Debuggen großartig an, war aber nach der Live-Schaltung nutzlos:
- Kann nicht filtern: Finden Sie die Anforderungsdatensätze eines Benutzers in 100.000 Protokollen? Viel Glück.
- Kann nicht aggregiert werden: Möchten Sie wissen, wie viele Datenbankabfragen in der letzten Stunde langsamer als 1 Sekunde waren? Kann nicht zählen.
- Kann keine Benachrichtigung erhalten: „Zahlung fehlgeschlagen“ erscheint in den Protokollen? Niemand weiß es.
Strukturierte Protokollierung löst diese Probleme. Anstatt einfach Zeichenfolgen zu drucken, können Sie JSON-Objekte ausgeben, wobei jedes Protokoll Metadaten wie Zeitstempel, Protokollebene, Anforderungs-ID und Benutzer-ID enthält. Später können Sie nach jedem Feld suchen und aggregieren.
Pino vs. Winston: Wie man wählt
Zwei große Protokollierungsbibliotheken im Node.js-Ökosystem, jede mit Stärken:
| Funktion | Pino | Winston |
|---|---|---|
| Leistung | Superschnelle, asynchrone Protokollierung, nahezu kein Overhead | Etwas langsamer, aber immer noch ausreichend |
| Benutzerfreundlichkeit | Einfache Konfiguration, sofort einsatzbereit | Funktionsreiches, gutes Plugin-Ökosystem |
| Erweiterbarkeit | Über Transport erweitern | Mehrere integrierte Transportmöglichkeiten |
| Gemeinschaft | Next.js offiziell empfohlen | Veteranenbibliothek, vollständigste Dokumente |
Meine Empfehlung:
- Szenarien mit hoher Parallelität (QPS > 1000): Wählen Sie Pino, der Leistungsvorteil ist klar
- Komplexe Protokollverarbeitungsanforderungen (mehrere Formate, Ziele): Wählen Sie Winston
- Sie wissen nicht, was Sie auswählen sollen: Wählen Sie Pino, alle offiziellen Dokumente von Next.j verwenden es
Pino Praktische Konfiguration
Erstinstallation:
npm install pino
npm install pino-pretty --save-dev # development environment pretty output
Erstellen Sie einen globalen Logger:
// lib/logger.ts
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
// Format log level
formatters: {
level: (label) => ({ level: label.toUpperCase() }),
},
// Development environment uses pino-pretty for pretty output
transport: process.env.NODE_ENV === 'development'
? {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'HH:MM:ss',
ignore: 'pid,hostname',
},
}
: undefined,
});
export { logger };
Die Entwicklungsausgabe wird koloriert und lesbar sein, die Produktion erfolgt in JSON für eine einfache Protokollplattformanalyse.
Verwendung in API-Routen
Der Schlüssel besteht darin, jeder Anfrage eine correlationId (Korrelations-ID) zuzuweisen, um alle mit dieser Anfrage verbundenen Protokolle aneinanderzureihen:
// app/api/products/route.ts
import { logger } from '@/lib/logger';
import { randomUUID } from 'crypto';
export async function GET(request: Request) {
// Generate unique request ID
const correlationId = request.headers.get('x-correlation-id') || randomUUID();
// Create child logger, automatically includes correlationId
const log = logger.child({ correlationId });
try {
log.info({ url: request.url }, 'Processing product request');
const products = await db.product.findMany();
log.info({ count: products.length }, 'Products fetched successfully');
return Response.json(products);
} catch (error) {
log.error({ error: error.message, stack: error.stack }, 'Failed to fetch products');
throw error;
}
}
Auf diese Weise werden alle Protokolle mit derselben „correlationId“ miteinander verknüpft. Suchen Sie bei der Fehlerbehebung einfach nach dieser ID und die gesamte Anforderungskette ist klar.
Best Practices auf Protokollebene
Zu wenige Protokolle sind nutzlos, zu viele übertönen wichtige Informationen. Mein Nivellierungsstandard:
FEHLER – Probleme, die sofortige Aufmerksamkeit erfordern
- Datenbankverbindung fehlgeschlagen
- Aufruf der Zahlungsschnittstelle fehlgeschlagen
– Kritische Geschäftslogik hat eine Ausnahme ausgelöst
log.error({ error, userId, orderId }, 'Payment processing failed');
WARNUNG – Ungewöhnliche, aber behebbare Situationen
– Wiederholung des API-Aufrufs erfolgreich
- Fallback-Logik ausgelöst
- Kontingentgrenze nähert sich
log.warn({ retryCount: 3 }, 'External API retry succeeded');
INFO – Kritische Geschäftskontrollpunkte
- Benutzeranmeldung/-abmeldung
- Auftrag erstellt/abgeschlossen
- Wichtige Konfigurationsänderungen
log.info({ userId, ip }, 'User logged in');
DEBUG – Detaillierte Debug-Informationen
- Funktionsparameter und Rückgabewerte
- Zwischenstaaten
- Leistungs-Timing
log.debug({ params }, 'Calling external API');
Produktionsstandard-INFO-Ebene, bei der Fehlerbehebung vorübergehend auf DEBUG erhöhen.
Protokollaggregation und -analyse
Lokale Pino-Pretty-Entwicklung reicht aus, die Produktion erfordert eine Integration mit der Log-Plattform. Mehrere Mainstream-Optionen:
Vercel-Protokolle
Bei Bereitstellung auf Vercel, integriertes Protokollierungssystem, Nullkonfiguration. Behält aber nur 7 Tage, eingeschränkte Suchfunktionalität.
Datenhund
Unternehmenslösung, APM + Protokolle + Überwachung, komplette Suite. Konfiguration:
import { datadogLogs } from '@datadog/browser-logs';
datadogLogs.init({
clientToken: process.env.NEXT_PUBLIC_DATADOG_CLIENT_TOKEN,
site: 'datadoghq.com',
forwardErrorsToLogs: true,
sampleRate: 100,
});
Logtail/BetterStack
Gutes Preis-Leistungs-Verhältnis, konzentriert sich auf die Protokollanalyse. Unterstützt Echtzeitsuche, Warnregeln und benutzerdefinierte Dashboards.
Für persönliche Projekte verwende ich Logtail, einfache Konfiguration, 1 GB Protokolle kostenlos pro Monat. Teamprojekte nutzen Datadog, teuer, aber leistungsstark.
Key-Log-Felddesign
Ein gutes Protokoll sollte diese Felder enthalten:
{
"timestamp": "2025-12-20T15:00:06.123Z", // Timestamp
"level": "INFO", // Log level
"correlationId": "abc-123-def", // Request correlation ID
"userId": "user_456", // User ID
"action": "create_order", // Business action
"duration": 234, // Execution duration (ms)
"status": "success", // Status
"metadata": { // Additional metadata
"orderId": "order_789",
"amount": 99.99
}
}
Protokolle wie dieses können antworten: „Wer hat was wann getan, mit welchem Ergebnis“.
Leistungsüberwachung – Datengesteuerte Optimierung
Core Web Vitals: Kennzahlen, die Google wichtig sind
Google verwendet Core Web Vitals als Suchranking-Faktoren, Sie sollten sich auch darum kümmern:
- LCP (Largest Contentful Paint): Größte Content-Paint-Zeit, idealer Wert < 2,5 s
- FID (First Input Delay) / INP (Interaction to Next Paint): Interaktionsreaktionszeit, < 100 ms / < 200 ms
- CLS (Cumulative Layout Shift): Kumulative Layoutverschiebung, < 0,1
Next.js verfügt über integrierte Web Vitals-Berichte. Fügen Sie einfach ein paar Zeilen in „app/layout.tsx“ hinzu:
'use client';
import { useReportWebVitals } from 'next/web-vitals';
export function WebVitalsReporter() {
useReportWebVitals((metric) => {
// Send to Sentry
if (window.Sentry) {
window.Sentry.captureMessage(`Web Vital: ${metric.name}`, {
level: 'info',
tags: {
web_vital: metric.name,
},
contexts: {
web_vitals: {
value: metric.value,
rating: metric.rating,
},
},
});
}
// Or send to your analytics platform
fetch('/api/analytics/web-vitals', {
method: 'POST',
body: JSON.stringify(metric),
});
});
return null;
}
Dann im Root-Layout importieren:
// app/layout.tsx
export default function RootLayout({ children }) {
return (
<html>
<body>
<WebVitalsReporter />
{children}
</body>
</html>
);
}
API-Leistungsverfolgung
Die Frontend-Leistung beträgt nur die Hälfte, langsame Backend-APIs lassen die Benutzer trotzdem warten. Die Leistungsüberwachung von Sentry kann jede API-Anfrage verfolgen:
// app/api/products/[id]/route.ts
import * as Sentry from '@sentry/nextjs';
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
// Create a transaction
return await Sentry.startSpan(
{
op: 'api.request',
name: 'GET /api/products/[id]',
},
async () => {
// Track database query
const product = await Sentry.startSpan(
{
op: 'db.query',
name: 'Fetch product from database',
},
async () => {
return await db.product.findUnique({
where: { id: params.id },
include: { reviews: true },
});
}
);
if (!product) {
return Response.json({ error: 'Not found' }, { status: 404 });
}
// Track external API call
const pricing = await Sentry.startSpan(
{
op: 'http.client',
name: 'Fetch pricing from external API',
},
async () => {
const res = await fetch(`https://pricing-api.com/product/${params.id}`);
return res.json();
}
);
return Response.json({ ...product, pricing });
}
);
}
Im Sentry-Dashboard sehen Sie Folgendes:
- Gesamtanfragezeit 450 ms
- Datenbankabfrage 120ms
- Externer API-Aufruf 300 ms
- Andere Logik 30 ms
Ganz klar, der Engpass ist die externe API.
Warnungen zu langsamen Abfragen
Datenbanken sind häufige Leistungsengpässe. Kann Überwachung in der Prisma-Middleware hinzufügen:
// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
import { logger } from './logger';
const prisma = new PrismaClient();
// Monitor slow queries
prisma.$use(async (params, next) => {
const before = Date.now();
const result = await next(params);
const after = Date.now();
const duration = after - before;
// Queries over 1 second logged as WARN
if (duration > 1000) {
logger.warn({
model: params.model,
action: params.action,
duration,
args: params.args,
}, 'Slow database query detected');
// Also send to Sentry
Sentry.captureMessage('Slow database query', {
level: 'warning',
tags: { model: params.model, action: params.action },
extra: { duration, args: params.args },
});
}
return result;
});
export { prisma };
Auf diese Weise entgeht Ihnen keine langsame Anfrage.
Echte Benutzerüberwachung vs. synthetische Überwachung
Real User Monitoring (RUM)
Verwendet Sentry, Datadog usw., um Leistungsdaten von echten Benutzern zu sammeln. Der Vorteil spiegelt reale Szenarien wider (verschiedene Netzwerke, Geräte), der Nachteil ist reaktiv und weiß erst, wenn Probleme auftreten.
Synthetische Überwachung
Verwendet Checkly, Pingdom usw., um regelmäßig Besuche auf Ihrer Website aus der ganzen Welt zu simulieren. Der Vorteil liegt in der proaktiven Problemerkennung, der Nachteil besteht darin, dass nicht alle Benutzerszenarien abgedeckt werden können.
Am besten beides kombinieren:
- RUM konzentriert sich auf Benutzererfahrungsmetriken
- Die synthetische Überwachung überwacht die Verfügbarkeit und kritische Abläufe (Anmeldung, Zahlung).
Ich verwende Checkly, um alle 5 Minuten von 5 geografischen Standorten aus auf die Startseite und die Anmeldeendpunkte zuzugreifen. Bei jeder Zeitüberschreitung oder jedem Fehler wird eine sofortige Warnung ausgelöst.
Alarmkonfiguration – Probleme zuerst erkennen
Slack-Integration: Das Team weiß sofort Bescheid
Die Integration von Sentry Slack ist einfach: Einstellungen → Integrationen → Slack, autorisieren Sie und wählen Sie dann aus, auf welchen Kanal gepusht werden soll.
Aber die Standardkonfiguration verschiebt alle Fehler und führt schnell zu Rauschen. Benachrichtigungsregeln müssen konfiguriert werden:
In den Sentry-Projekteinstellungen:
- Warnungen → Warnungsregel erstellen
- Auslösebedingungen auswählen:
- Fehlerratenwarnung: „Fehleranzahl > 50 in 10 Minuten“
- Neue Fehlerwarnung: „Bei erstem Auftreten sofort benachrichtigen“
- Leistungsregression: „API P95-Antwortzeit > 1 s“
- Wählen Sie Aktion: Benachrichtigung über Slack senden
Slack-Nachrichtenformat:```
🚨 Production Error Spike
Project: my-nextjs-app
Environment: production
Error: TypeError: Cannot read property ‘id’ of undefined
Events: 127 events in 10 minutes
View in Sentry: https://sentry.io/…
Klicken Sie auf den Link, um direkt zu Sentry zu springen, Details anzuzeigen und zu stapeln.
### Alarmpriorisierung: Ermüdung vermeiden
Nicht alle Themen sind gleich dringend. Meine Priorisierungsstrategie:
**P0 – Kritisch (sofortige Reaktion)**
- Dienst völlig nicht verfügbar
- Die Zahlungsfunktion ist fehlgeschlagen
- Datenbankverbindung unterbrochen
Auslöser: Telefon (PagerDuty) + Slack @channel
**P1 – Wichtig (innerhalb einer Stunde antworten)**
- Kernfunktionalität abnormal
- Fehlerratenspitze (> 100 in 10 Minuten)
- API-Antwortzeit P95 > 3s
Auslöser: Slack-Push zum Entwicklungskanal
**P2 – Normal (Handhabung während der Arbeitszeit)**
- Kleinere Fehler (< 10/Stunde)
- Nicht kritische Funktionalität abnormal
- Skriptfehler von Drittanbietern
Auslöser: Tägliche Zusammenfassung per E-Mail
**Konfigurationsbeispiel** (Sentry-Alarmregel):
```javascript
// P0 alert: payment failure
{
conditions: [
{ type: 'event.tag', key: 'feature', value: 'payment' },
{ type: 'event.level', value: 'error' }
],
frequency: 'every event', // notify every time
actions: [
{ type: 'slack', channel: '#critical-alerts', mention: '@channel' },
{ type: 'pagerduty', service: 'payments' }
]
}
// P1 alert: error rate spike
{
conditions: [
{ type: 'event.count', value: 100, interval: '10m' }
],
frequency: 'once per issue', // notify once per issue
actions: [
{ type: 'slack', channel: '#alerts-dev' }
]
}
Techniken zur Reduzierung von Alarmgeräuschen
Wenn Sie die Überwachung zum ersten Mal integrieren, werden Sie möglicherweise mit Warnmeldungen überhäuft. Mehrere Techniken zur Geräuschreduzierung:
1. Bekannte Probleme ignorieren
Entwicklungs-Hot-Reload-Fehler, Skriptausnahmen von Drittanbietern, diese Geräusche können gefiltert werden:
// sentry.client.config.ts
Sentry.init({
ignoreErrors: [
// Browser extension errors
/chrome-extension/,
/moz-extension/,
// Third-party scripts
/google-analytics/,
// Development hot reload
/HMR/,
],
denyUrls: [
// Ignore errors from specific domains
/extensions\//i,
/^chrome:\/\//i,
],
});
2. Doppelte Warnungen zusammenführen
Derselbe Fehler wird nur alle 10 Minuten gemeldet, um Kanal-Spam zu vermeiden. Die „Issue Grouping“ von Sentry führt ähnliche Fehler automatisch zusammen.
3. Legen Sie Ruhezeiten fest
Während der Bereitstellung kann es zu kurzen Fehlerspitzen kommen, Sie können „Stumm für 10 Minuten“ einstellen.
4. Fingerabdrücke verwenden
Benutzerdefinierte Fehlergruppierungsregeln zum Zusammenführen von Fehlern mit derselben Grundursache:
Sentry.captureException(error, {
fingerprint: ['database-connection-error', databaseName],
});
Auf diese Weise werden Verbindungsfehler aus verschiedenen Datenbanken getrennt und lassen sich leichter lokalisieren.
Praxisfall – Vollständige Implementierung der Überwachungslösung
E-Commerce-Site-Monitoring-Architektur
Letztes Jahr half eine E-Commerce-Website bei der Überwachung der Transformation und teilte die Komplettlösung mit:
Hintergrund:
- Täglich UV 80K
- Spitzen-QPS 3000+
- Hauptprobleme: sporadische Zahlungsausfälle, langsames Laden der Homepage
Überwachungsarchitektur:```
┌─────────────┐
│ Next.js │
│ Frontend/SSR│
└──────┬──────┘
│
├─ Sentry (error + performance)
├─ Pino (structured logs) → Datadog
├─ Web Vitals → Sentry
└─ Checkly (synthetic monitoring)
**Schlüsselkonfiguration**:
1. **Tracking des Benutzerverhaltens**
```typescript
// lib/tracking.ts
import * as Sentry from '@sentry/nextjs';
export function trackCheckoutStep(step: string, data: any) {
Sentry.addBreadcrumb({
category: 'checkout',
message: `Checkout step: ${step}`,
data,
level: 'info',
});
}
// Call in shopping flow
trackCheckoutStep('add_to_cart', { productId, price });
trackCheckoutStep('proceed_to_payment', { cartTotal });
trackCheckoutStep('payment_submitted', { method: 'credit_card' });
Wenn die Zahlung fehlschlägt, kann auf diese Weise der gesamte Einkaufspfad des Benutzers angezeigt werden.
- Zahlungsüberwachung
// app/api/payment/route.ts
export async function POST(request: Request) {
const log = logger.child({ action: 'payment' });
try {
const result = await processPayment(data);
log.info({ orderId, amount, method }, 'Payment succeeded');
return Response.json({ success: true, orderId });
} catch (error) {
log.error({ error, orderId, userId }, 'Payment failed');
// P0 alert
Sentry.captureException(error, {
tags: { feature: 'payment', severity: 'critical' },
level: 'fatal',
});
return Response.json({ error: 'Payment failed' }, { status: 500 });
}
}
Jeder Zahlungsausfall benachrichtigt das Team sofort.
- Leistungsgrundeinstellung
Verwenden Sie Sentry Performance Monitoring, um eine Basislinie festzulegen:
- Homepage-LCP < 2s
- Produktdetailseite LCP < 2,5 s
- API /api/products P95 < 500 ms
Automatische Warnung bei Überschreitung der Grundlinie.
Ergebnisse:
- Die Zeit für die Erkennung von Vorfällen wurde von durchschnittlich 40 Minuten auf 3 Minuten verkürzt
- Zahlungsausfallrate von 0,8 % auf 0,2 % gesenkt
- Homepage-LCP von 3,2 Sekunden auf 1,8 Sekunden optimiert
Überwachungscheckliste
Abschließend noch eine Checkliste zur Prüfung Ihres Projekts:
**Error Monitoring**
- [ ] Sentry configured and tested
- [ ] Source Maps uploaded successfully
- [ ] global-error.tsx created (App Router)
- [ ] Server Actions wrapped with error handling
- [ ] Ignore rules configured (filter noise)
**Log Management**
- [ ] Logging library integrated (Pino/Winston)
- [ ] Production outputs JSON format
- [ ] Logs include correlationId
- [ ] Log level correctly set (production INFO)
- [ ] Logs integrated with aggregation platform
**Performance Monitoring**
- [ ] Web Vitals reporting enabled
- [ ] Core Web Vitals meeting standards (LCP<2.5s, INP<200ms, CLS<0.1)
- [ ] Critical APIs have performance tracking
- [ ] Slow query monitoring configured
- [ ] Synthetic monitoring set up (optional)
**Alert Configuration**
- [ ] Slack/email alerts tested
- [ ] Alert rules prioritized by severity
- [ ] Alert noise reduction rules configured
- [ ] Team members know alert procedures
- [ ] P0 incidents have clear responders
**Continuous Improvement**
- [ ] Weekly monitoring data review
- [ ] Error trend analysis (which errors increasing)
- [ ] Performance regression detection (which pages slowing)
- [ ] Alert rules regularly optimized
Fazit
Von der reaktiven Brandbekämpfung bis zur proaktiven Entdeckung – die Überwachung gibt Ihnen die Kontrolle über die Produktion.
Zusammenfassung des von uns erstellten Überwachungssystems:
- Sentry übernimmt die Fehlerverfolgung und Leistungsüberwachung und kann sogar Benutzeraktionen wiedergeben
- Pino stellt strukturierte Protokolle bereit und verknüpft die gesamte Anforderungskette anhand der Korrelations-ID
- Web Vitals konzentriert sich auf Kennzahlen zur Benutzererfahrung und wirkt sich direkt auf SEO-Rankings aus
- Slack-Benachrichtigungen informieren das Team sofort über Probleme, die Priorisierung verhindert Ermüdung
Noch wichtiger ist eine Änderung der Denkweise: Überwachung ist kein „nice to have“, sondern der Airbag der Produktionsumgebung. Sie würden nicht auf einen Autounfall warten, um einen Airbag einzubauen, und Sie sollten auch nicht auf Produktionsprobleme warten, um über eine Überwachung nachzudenken.
Werden Sie noch heute aktiv. Wenn Ihr Projekt noch keine Überwachung hat:
- Verbringen Sie dieses Wochenende zwei Stunden damit, Sentry zu integrieren und die grundlegende Fehlerverfolgung zu konfigurieren
- Fügen Sie nächste Woche die strukturierte Protokollierung und die Korrelations-ID hinzu
- Eine Woche nach der Einrichtung von Slack-Benachrichtigungen und Leistungs-Baselines
Streben Sie nicht in einem Schritt nach Perfektion, sondern erst die grundlegende Fehlerüberwachung zum Laufen bringen und dann schrittweise verbessern. Fragen Sie sich nach jedem Produktionsvorfall: „Könnte die Überwachung dieses Problem früher entdeckt haben?“ Kontinuierliche Verbesserung und Überwachung werden zu Ihrem zuverlässigsten Teamkollegen.
Wenn Ihnen dieser Artikel schließlich geholfen hat, teilen Sie ihn mit Ihrem Team, um gemeinsam besser zu werden. Schließlich ist die Überwachung eine Teamleistung und kein Einzelkampf.
Möge Ihre Next.js-App absolut stabil sein und niemals abstürzen. (Aber die Realität enttäuscht oft, daher ist die Überwachung wirklich wichtig 😄)
Next.js Produktions-Monitoring komplett einrichten
Von Sentry über Logs und Performance bis zu Alerts
⏱️ Estimated time: 3 hr
- 1
Step 1: Sentry-Fehlertracking integrieren
Installation:
```
bash
npm install @sentry/nextjs
```
Initialisierung:
```
bash
npx @sentry/wizard@latest -i nextjs
```
Client:
```
ts
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
})
```
Server:
```
ts
// sentry.server.config.ts
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
})
```
Wichtig: Client und Server getrennt konfigurieren, tracesSampleRate setzen, Umgebungsvariablen hinterlegen - 2
Step 2: Strukturierte Logs konfigurieren
correlationId pro Request:
```
ts
// middleware.ts
import { v4 as uuidv4 } from 'uuid'
export function middleware(request: NextRequest) {
const correlationId = request.headers.get('x-correlation-id') || uuidv4()
const response = NextResponse.next()
response.headers.set('x-correlation-id', correlationId)
return response
}
```
In Logs:
```
ts
import { headers } from 'next/headers'
export async function handler() {
const headersList = headers()
const correlationId = headersList.get('x-correlation-id')
console.log({ correlationId, message: 'User action', timestamp: new Date().toISOString() })
}
```
Wichtig: eindeutige ID pro Request, in allen Logs mitschreiben - 3
Step 3: Performance-Monitoring konfigurieren
Sentry APM:
```
ts
Sentry.init({
tracesSampleRate: 1.0,
integrations: [new Sentry.Integrations.Http({ tracing: true })],
})
```
Custom:
```
ts
const transaction = Sentry.startTransaction({ op: 'http.server', name: 'API Route' })
try { await processRequest() } finally { transaction.finish() }
```
Wichtig: tracesSampleRate, API-Zeiten, Engpässe erkennen - 4
Step 4: Alerts konfigurieren
Sentry Dashboard: Regeln, Schwellen, Slack/E-Mail. Slack-Webhook im Dashboard. E-Mail-Empfänger und Bedingungen. Wichtig: sinnvolle Schwellen, Alert-Müdigkeit vermeiden, schnell reagieren
FAQ
Warum braucht Next.js ein spezielles Monitoring?
Wie integriere ich Sentry?
Wie richte ich strukturierte Logs ein?
Wie konfiguriere ich Performance-Monitoring?
Wie konfiguriere ich Alerts?
Was sind Monitoring-Best Practices?
17 Min. Lesezeit · Veröffentlicht am: 20. Dez. 2025 · Aktualisiert am: 14. Juli 2026
Next.js Komplettleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
Weg von Vercel: Der vollständige Leitfaden zur Next.js Docker-Self-Hosting
Genervt von hohen Vercel-Rechnungen? Dieser Leitfaden zeigt, wie Sie Next.js mit Docker selbst hosten – inklusive Standalone-Konfiguration, Reverse-Proxy-Setup und Fixes für Streaming-Rendering. Sparen Sie monatlich 300–500 $.
Teil 42 von 51
Nächster
Next.js Dark Mode: next-themes – der vollständige Leitfaden
Vom Flackern zur perfekten Lösung: Schritt für Schritt Dark Mode in Next.js mit next-themes – flackerfrei. Mit vollständigem Code, Erklärung der Funktionsweise und Fehlerbehebung.
Teil 44 von 51
Ähnliche Beiträge
Next.js App Router Einstieg: Kernkonzepte und Grundlagen im Überblick

Next.js App Router Einstieg: Kernkonzepte und Grundlagen im Überblick
Next.js 15 in der Praxis: Wie ich an einem Wochenende ein produktionsreifes Blog-System aufgebaut habe


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen