Alle Projekte

Arbeit · 2026

jsDevLogging

Logging für Browser und Node ohne Laufzeitabhängigkeiten, per Script-Tag auch in PHP-Projekten nutzbar.

Auf einen Blick

  • Keine Laufzeitabhängigkeiten, 17 KB minifiziert als Browser-Bundle
  • Transports für Console, HTTP, WebSocket, localStorage und Datei
  • Puffert Einträge offline und sendet sie nach, sobald die Verbindung steht
  • Middleware-Pipeline zum Anreichern, Filtern und Samplen von Einträgen
  • Sub-Path-Exports, damit ungenutzte Transports nie im Bundle landen
  • 152 Tests, ESM und CJS nebeneinander, vollständige Typdefinitionen

Warum noch eine Logging-Bibliothek

Es gibt pino, winston, consola und ein Dutzend weiterer Bibliotheken. Über den Funktionsumfang lässt sich da wenig gewinnen. Alle setzen allerdings einen Bundler voraus.

Eine klassische PHP-Seite hat keinen. Dort gibt es ein Template mit einem Script-Tag, und wenn im Browser etwas schiefgeht, erfährt der Server nichts davon. Für diesen Fall gibt es ein IIFE-Bundle mit 17 KB: Script-Tag einbinden, den HttpTransport auf ein selbst geschriebenes logs.php zeigen lassen, und die Fehler aus dem Browser landen dort, wo man sie auch sieht.

<script src="/assets/browser.min.js"></script>
<script>
  const logger = jsDevLogging.createLogger({
    transports: [new jsDevLogging.HttpTransport({ url: '/api/logs.php' })],
  });

  logger.error('Checkout fehlgeschlagen', { orderId: 4711 });
</script>

Keine Abhängigkeiten

dependencies ist ein leeres Objekt. Was die Bibliothek braucht, steht auch in der Bibliothek, inklusive eines kleinen Event-Emitters mit genau den drei Methoden, die der ConfigManager verwendet.

Der Grund dafür ist praktisch: Ein Logger läuft in jedem Request und vor allem dann noch, wenn anderes schon nicht mehr funktioniert. Eine transitive Abhängigkeit, die nie jemand gelesen hat, ist an dieser Stelle besonders unangenehm.

Offline-Verhalten

Logs braucht man am dringendsten, wenn etwas nicht funktioniert, und im Browser heißt das oft: Die Verbindung ist weg. Ein Transport, der genau dann seine Einträge verwirft, hilft in dieser Situation wenig.

Der BufferedTransport hört deshalb auf die Offline-Events des Browsers, sammelt weiter im Puffer statt zu senden und schickt alles nach, sobald die Verbindung wieder steht. Der HTTP-Transport fasst Einträge ohnehin zu Batches zusammen und wiederholt fehlgeschlagene Sendungen mit wachsendem Abstand.

Sub-Path-Exports

Transports, Formatter und Middleware liegen hinter eigenen Sub-Path-Exports. Wer nur in die Konsole schreibt, importiert den WebSocket-Transport nie und hat ihn damit auch nicht im Bundle, ganz ohne Tree-Shaking.

Dazu kommen ESM und CJS nebeneinander, vollständige .d.ts-Typen und 152 Tests, die vor jedem npm publish durchlaufen.