Logging in TypeScript-Anwendungen: Best Practices und Tools

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Logging in TypeScript wichtig ist

Logging ist nicht einfach nur das Aufzeichnen von Ereignissen in einer Datei. In modernen TypeScript-Anwendungen bildet ein gut konfiguriertes Logging die Grundlage für Debugging, Monitoring und Leistungsanalyse. Ohne qualitativ hochwertige Logs verbringt der Entwickler Stunden mit der Reproduktion von Fehlern, und das Betriebsteam kann Engpässe nicht schnell identifizieren.

TypeScript als Erweiterung von JavaScript bietet strenge Typisierung, was die Erstellung vorhersagbarerer und sichererer Logging-Systeme ermöglicht. Die Verwendung von einfachem console.log() in der Produktion ist jedoch ein Antipattern, das zu Informationsrauschen und Datenverlust führt.

In diesem Artikel betrachten wir die besten Praktiken für das Logging in TypeScript: von der Bibliotheksauswahl bis zur Strukturierung von Logs und der Arbeit mit Kontext.



Auswahl einer Bibliothek für das Logging

Im TypeScript/Node.js-Ökosystem gibt es mehrere beliebte Bibliotheken. Wir betrachten drei Hauptoptionen:

  • Winston — die beliebteste Bibliothek mit flexibler Konfiguration von Transports (Ausgabe in Konsole, Datei, Datenbank). Unterstützt Log-Level und Formatierung.
  • Pino — eine moderne, auf Leistung ausgerichtete Bibliothek. Ideal für hochbelastete Systeme.
  • Bunyan — eine weniger beliebte, aber stabile Option. Alle Logger geben Daten im JSON-Format aus.

Für eine typische TypeScript-Anwendung empfehlen wir Winston oder Pino. Beispiel für die Konfiguration von Winston mit TypeScript:

import winston from 'winston';

const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'error.log', level: 'error' }), ],});

logger.info('Server gestartet', { port: 3000 });


Integration mit TypeScript: Typen und Interfaces

Um das Maximum aus der Typisierung herauszuholen, erstellen Sie einen Wrapper für den Logger unter Verwendung von Interfaces:

interface LoggerOptions {  level?: string;  service?: string;}

interface ILogger { info(message: string, meta?: unknown): void; error(message: string, error?: Error): void; warn(message: string, meta?: unknown): void;}

Dies ermöglicht es Ihnen, die Typen der übergebenen Daten streng zu kontrollieren und Fehler bereits zur Kompilierzeit zu vermeiden.



Log-Level und deren korrekte Verwendung

Standard-Log-Level (vom kritischsten zum geringsten): error, warn, info, debug, trace. Es ist wichtig, eine einheitliche Semantik beizubehalten:

  • error — nur für nicht behebbare Fehler, die die Aufmerksamkeit des Entwicklers erfordern.
  • warn — für potenziell problematische Situationen, die den Betrieb der Anwendung nicht beeinträchtigen.
  • info — für wichtige Ereignisse: Serverstart, Anfrageverarbeitung, erfolgreiche Authentifizierung.
  • debug — für das Debugging während der Entwicklung. Aktivieren Sie dieses Level nicht in der Produktion.

Beispiel für eine dynamische Änderung des Levels in Abhängigkeit von der Umgebung:

const logLevel = process.env.NODE_ENV === 'production' ? 'warn' : 'debug';const logger = winston.createLogger({ level: logLevel });


Strukturierte Logs und Kontext

Verwenden Sie anstelle von Textnachrichten strukturierte Logs im JSON-Format. Dies ermöglicht das einfache Parsen von Logs mit dem ELK-Stack (Elasticsearch, Logstash, Kibana) oder anderen Systemen.

Fügen Sie unbedingt Kontextinformationen hinzu: Anfrage-ID, Benutzername, Dienstname, Zeitstempel. Beispiel mit Pino:

import pino from 'pino';

const logger = pino({ level: 'info', mixin() { return { service: 'my-api' }; },});

// Hinzufügen von

Blogs

Buchempfehlungen