Logging in JavaScript-Anwendungen: Best Practices
Logging ist nicht nur das Aufzeichnen von Ereignissen in einer Datei. In modernen Node.js-Anwendungen ist es ein leistungsstarkes Werkzeug für Monitoring, Debugging und Audit. Ohne qualitativ hochwertiges Logging wird die Ursachensuche für einen Produktionsserver-Absturz zum Ratespiel. In diesem Artikel behandeln wir die Best Practices für Logging in JavaScript (Node.js), die Ihnen helfen, zuverlässige und wartbare Systeme zu erstellen.
Warum standardmäßiges console.log eine schlechte Praxis ist
Viele Anfänger verwenden console.log zum Debuggen. In der Produktion führt dies jedoch zu Problemen:
- Fehlende Ebenen: Sie können Informationsmeldungen und kritische Fehler nicht trennen.
- Keine Struktur: Die Konsolenausgabe ist nur ein String, der schwer zu parsen ist.
- Blockierende Ein-/Ausgabe: Synchrone Schreibe kann die Anwendung verlangsamen.
- Keine Rotation: Logdateien wachsen unbegrenzt.
Verwenden Sie stattdessen spezialisierte Bibliotheken wie winston oder pino. Sie bieten flexible Konfiguration von Transports (Ausgabe in Datei, Konsole, externe Dienste) und asynchrones Schreiben.
Auswahl der Logging-Bibliothek: winston vs pino
Im Node.js-Ökosystem gibt es zwei klare Marktführer. Betrachten wir ihre Eigenschaften:
Winston
Die beliebteste Bibliothek. Unterstützt viele Transports (Datei, HTTP, MongoDB, Elasticsearch) und benutzerdefinierte Formate. Ideal für monolithische Anwendungen.
const winston = require('winston');
const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), new winston.transports.Console({ format: winston.format.simple() }) ]});
logger.info('Server gestartet auf Port 3000');logger.error('Fehler bei der Datenbankverbindung', { db: 'mongo', code: 500 });Pino
Eine extrem schnelle Bibliothek, die 5-10 mal schneller ist als winston. Ideal für High-Load-Systeme und Microservices. Standardmäßig wird JSON ausgegeben.
const pino = require('pino');
const logger = pino({ level: process.env.LOG_LEVEL || 'info', transport: { target: 'pino/file', options: { destination: './app.log' } }});
logger.info({ user: 'admin' }, 'Benutzer hat sich angemeldet');logger.error(new Error('Timeout'), 'Anfragefehler');Tipp: Für die meisten Projekte wählen Sie winston aufgrund seiner Flexibilität. Wenn Leistung kritisch ist, verwenden Sie pino.
Logging-Ebenen: Wie man nicht in Nachrichten ertrinkt
Die richtige Verwendung von Ebenen ist die Grundlage für gutes Logging. In Node.js ist die folgende Hierarchie üblich (von am wenigsten bis am kritischsten):
- trace / silly — maximal detaillierte Debug-Informationen (normalerweise in der Produktion deaktiviert).
- debug — Debug-Meldungen für Entwickler.
- info — Bestätigung des normalen Betriebs (Anfragen, Start von Diensten).
- warn — ungewöhnliche Situation, aber die Anwendung läuft weiter (z. B. Überschreitung des Anfragenlimits).
- error — Fehler, der Aufmerksamkeit erfordert (Anfragenfehler, Ausfall eines externen Dienstes).
- fatal — kritischer Fehler, nach dem die Anwendung nicht weiterarbeiten kann.
Konfigurieren Sie die Logging-Ebene über Umgebungsvariablen:
const LOG_LEVEL = process.env.LOG_LEVEL || 'info';const logger = winston.createLogger({ level: LOG_LEVEL });Setzen Sie in der Entwicklung debug, in der Produktion info.
```