01 · Problem
Wofür braucht man das?
Diagnose braucht konsistente Level, strukturierte Metadaten und austauschbare Ausgaben, ohne Geschäftslogik an process.stdout oder process.exit zu koppeln.
02 · Denkmodell
Das mentale Modell
Ein LogRecord ist Daten. Ein Formatter übersetzt ihn, ein Sink schreibt ihn; TTY-Animationen sind ein optionaler Renderer oberhalb dieses Kerns.
Logger ist ein beim Import initialisiertes Singleton mit Farben, Breadcrumbs, Profiling und Animationen. Levelauswertung und Filterrichtung sind fehlerhaft, Konfiguration kommt zu spät und der Puffer wächst unbegrenzt.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Level, Nachricht, Timestamp und Metadaten zu einem Record formen.
- Record vor Formatierung gegen eine klar geordnete Schwelle prüfen.
- Formatter erzeugt Text oder JSON ohne die Ursprungsdaten zu verändern.
- Ein injizierter Sink schreibt; Terminaleffekte laufen nur bei isTTY.
04 · Bauteile
Die entscheidenden Verträge
Logger.getInstance
Liefert das globale Singleton und soll Format, Level und Stream konfigurieren.
trace / debug / info / warn / error / fatal
Level-spezifische Schreibmethoden.
profile / profileSync
Misst Laufzeit und verbindet sie mit einer Terminalanimation.
addBreadcrumb / showBreadcrumbs
Speichert und zeigt vorherige Meldungen.
05 · Build it yourself
Selbst implementieren
Baue einen kleinen Logger ohne Globals; JSON, hübsche Konsole und Animationen können danach als getrennte Adapter folgen.
- Definiere eine monotone Levelreihenfolge und teste die Schwelle als reine Funktion.
- Injiziere Sink, Uhr und Formatter über den Konstruktor.
- Lass fatal nie im Kern den Prozess beenden; der Aufrufer entscheidet über Lifecycle.
type Level = 10 | 20 | 30 | 40 | 50;
type Record = { at: Date; level: Level; message: string; meta?: object };
class Logger {
constructor(
private threshold: Level,
private write: (record: Record) => void,
private now = () => new Date(),
) {}
log(level: Level, message: string, meta?: object) {
if (level < this.threshold) return;
this.write({ at: this.now(), level, message, meta });
}
}06 · Verifizieren
Was du testen solltest
- Für jede Schwelle werden exakt die erlaubten Level an den Sink weitergegeben.
- Metadaten bleiben strukturiert und Formatterfehler verändern den Record nicht.
- Nicht-TTY-Sinks starten keine Animation; Exceptions stoppen Timer zuverlässig.
07 · Grenzen
Kompromisse und Stolperfallen
- Synchrone Sinks sind einfach, können unter Last aber blockieren.
- Unbegrenzte Breadcrumbs und Metadaten können Speicher und sensible Daten akkumulieren.
- Terminalsteuerung ist plattform- und TTY-abhängig.
Logging-Level und fatal-Verhalten sind Betriebsverträge. Invertierte Filter oder ein verstecktes process.exit können Fehler genau dann unsichtbar machen, wenn sie am wichtigsten sind.
08 · Weiterdenken