GitHub
teilweisepackages/logger/src

Logger

@ralphschuler/logger

Formatiert Level, Kontext und Terminalausgabe und trennt idealerweise Logging von animierten TTY-Zeilen.

structured logsterminallevels

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.

Im Repository

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?

  1. Level, Nachricht, Timestamp und Metadaten zu einem Record formen.
  2. Record vor Formatierung gegen eine klar geordnete Schwelle prüfen.
  3. Formatter erzeugt Text oder JSON ohne die Ursprungsdaten zu verändern.
  4. 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.

  1. Definiere eine monotone Levelreihenfolge und teste die Schwelle als reine Funktion.
  2. Injiziere Sink, Uhr und Formatter über den Konstruktor.
  3. Lass fatal nie im Kern den Prozess beenden; der Aufrufer entscheidet über Lifecycle.
minimal.ts · unabhängig vom Package
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.
Wichtig

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

Quellcode und Nachbarn

Originalcode auf GitHub ansehen