Die erste Aufgabe, mit der Entwickler am häufigsten konfrontiert sind, wenn sie mit der Programmierung in JavaScript beginnen, ist das Protokollieren von Ereignissen im Konsolenprotokoll mithilfe der Methode
console.log
. Auf der Suche nach Informationen zum Debuggen von JavaScript-Code finden Sie Hunderte von Blog-Artikeln sowie Anweisungen zu StackOverflow, in denen Sie aufgefordert werden, Daten über die
console.log
Methode „einfach“ an die Konsole
console.log
. Dies ist eine so übliche Praxis, dass ich Regeln für die Codequalitätskontrolle einführen musste, z. B.
no-console
, um keine zufälligen Protokolleinträge im Produktionscode zu hinterlassen. Was aber, wenn Sie eine Veranstaltung speziell registrieren müssen, um zusätzliche Informationen bereitzustellen?
Dieser Artikel beschreibt verschiedene Situationen, in denen Sie Protokolle verwalten müssen. Es zeigt den Unterschied zwischen den Methoden
console.log
und
console.error
in Node.js und zeigt, wie die Protokollierungsfunktion an Bibliotheken übergeben wird, ohne die Benutzerkonsole zu überlasten.

Theoretische Grundlagen der Arbeit mit Node.js.
Die Methoden
console.log
und
console.error
können sowohl im Browser als auch in Node.js verwendet werden. Bei der Verwendung von Node.js ist jedoch eines zu beachten. Wenn Sie den folgenden Code in Node.js mit einer Datei namens
index.js
,

und führen Sie es dann im Terminal mit dem
node index.js
. Die Ergebnisse der Befehlsausführung befinden sich übereinander:

Trotz der Tatsache, dass sie ähnlich erscheinen, verarbeitet das System sie unterschiedlich. Wenn Sie sich den Abschnitt über den
console
in der
Node.js-Dokumentation console.log
, stellt sich heraus, dass
console.log
das Ergebnis über
stdout
und
console.error
über
stderr
druckt.
Jeder Prozess kann standardmäßig mit drei Streams (
stream
) arbeiten:
stdin
,
stdout
und
stderr
. Der
stdin
Stream verarbeitet Eingaben für einen Prozess, z. B. Tastenklicks oder umgeleitete Ausgaben (mehr dazu weiter unten). Der Standard-Standardausgabestream dient zur Ausgabe von Anwendungsdaten. Schließlich ist der Standard-
stderr
Fehlerstrom so ausgelegt, dass Fehlermeldungen angezeigt werden. Wenn Sie herausfinden
stderr
, wofür
stderr
und wann Sie es verwenden sollen, lesen Sie
diesen Artikel .
Kurz gesagt, es kann verwendet werden, um die Operatoren Umleitung (
>
) und Pipeline (
|
) zu verwenden, um mit Fehlern und Diagnoseinformationen getrennt von den tatsächlichen Ergebnissen der Anwendung zu arbeiten. Wenn Sie mit dem Operator
>
die Ausgabe des Befehlsergebnisses in eine Datei umleiten können, können Sie mit dem Operator
2>
die Ausgabe des
stderr
Fehlerstroms in eine Datei umleiten. Dieser Befehl sendet beispielsweise
Hello an die Datei
hello.log
und
Bye bye an die Datei
error.log
.


Wann muss ich Ereignisse in das Protokoll schreiben?
Nachdem wir die technischen Aspekte der Protokollierung überprüft haben, gehen wir zu verschiedenen Szenarien über, in denen Sie Ereignisse registrieren müssen. In der Regel fallen diese Szenarien in eine von mehreren Kategorien:
Dieser Artikel beschreibt nur die letzten drei Szenarien, die auf Node.js basieren.
Protokollierung für Serveranwendungen
Es gibt mehrere Gründe für die Protokollierung von Ereignissen, die auf dem Server auftreten. Wenn Sie beispielsweise eingehende Anforderungen protokollieren, können Sie Statistiken darüber abrufen, wie oft Benutzer auf 404-Fehler stoßen, was der Grund dafür sein könnte oder welche
User-Agent
Clientanwendung verwendet wird. Sie können auch den Zeitpunkt und die Ursache des Fehlers ermitteln.
Um mit dem in diesem Teil des Artikels angegebenen Material zu experimentieren, müssen Sie einen neuen Katalog für das Projekt erstellen. Erstellen
index.js
im Projektverzeichnis
index.js
für den zu verwendenden Code und führen Sie die folgenden Befehle aus, um das Projekt zu starten und
express
installieren:

Wir haben einen Server mit Middleware eingerichtet, der jede Anforderung in der Konsole mithilfe der
console.log
Methode
console.log
. Wir
index.js
die folgenden Zeilen in die Datei
index.js
:

Dies verwendet
console.log('%O', req)
, um das gesamte Objekt im Protokoll zu protokollieren. Aus Sicht der internen Struktur verwendet die Methode
util.forma
t, das neben
%O
auch andere Platzhalter unterstützt. Informationen dazu finden Sie in der
Dokumentation zu Node.js.Wenn Sie den
node index.js
ausführen, um den Server zu starten und zu
localhost : 3000 zu wechseln, zeigt die Konsole viele unnötige Informationen an:

Wenn Sie stattdessen
console.log('%s', req)
, um das Objekt nicht vollständig anzuzeigen, erhalten Sie nicht viele Informationen:

Sie können Ihre eigene Protokollierungsfunktion schreiben, die nur die erforderlichen Daten ausgibt. Zunächst müssen Sie jedoch entscheiden, welche Informationen benötigt werden. Trotz der Tatsache, dass der Fokus normalerweise auf dem Inhalt der Nachricht liegt, ist es in der Realität häufig erforderlich, zusätzliche Informationen zu erhalten, darunter:
- Zeitstempel - um zu wissen, wann Ereignisse aufgetreten sind;
- Computer- / Servername - wenn ein verteiltes System ausgeführt wird;
- Prozesskennung - wenn mehrere
pm2
ausgeführt werden, z. B. pm2
; - Nachricht - eine tatsächliche Nachricht mit einigen Inhalten;
- Stack-Trace - wenn ein Fehler protokolliert wird;
- zusätzliche Variablen / Informationen.
Da in jedem Fall alles in die Streams
stdout
und
stderr
ausgegeben wird, muss ein Journal auf verschiedenen Ebenen geführt und Journaleinträge je nach Ebene konfiguriert und gefiltert werden.
Dies kann erreicht werden, indem Sie Zugriff auf verschiedene Teile des
process
und mehrere Codezeilen in JavaScript schreiben. Node.js ist jedoch insofern bemerkenswert, als es bereits über ein
npm
Ökosystem und mehrere Bibliotheken verfügt, die für diese Zwecke verwendet werden können. Dazu gehören:
pino
;winston
;- brüllen ;
- bunyan (diese Bibliothek wurde seit zwei Jahren nicht mehr aktualisiert).
Pino wird oft bevorzugt, weil es schnell ist und ein eigenes Ökosystem hat. Mal sehen, wie
pino
bei der Protokollierung helfen kann. Ein weiterer Vorteil dieser Bibliothek ist das
express-pino-logger
Paket, mit dem Sie Anforderungen registrieren können.
Installieren Sie
pino
und
express-pino-logger
:

Danach aktualisieren wir die Datei
index.js
, um den Ereignisprotokollierer und die Middleware zu verwenden:

In diesem Fragment haben wir eine Instanz des Ereignisprotokollierers für
pino
und an
express-pino-logger
, um eine neue plattformübergreifende Ereignisprotokollierungssoftware zu erstellen, mit der Sie
app.use
aufrufen
app.use
. Außerdem wurde
console.log
bei
logger.info
durch
logger.info
und
logger.debug
zur Route hinzugefügt, um verschiedene Ebenen des Protokolls anzuzeigen.
Wenn Sie den Server durch wiederholtes Ausführen von
node index.js
, erhalten Sie an der Ausgabe ein anderes Ergebnis, bei dem jede Zeile / Zeile im JSON-Format ausgegeben wird. Gehen Sie erneut zu
localhost : 3000, um eine weitere neue Zeile im JSON-Format anzuzeigen.

Unter den Daten im JSON-Format finden Sie die zuvor genannten Informationen, z. B. einen Zeitstempel. Beachten Sie auch, dass die Meldung
logger.debug
nicht angezeigt wurde. Um es sichtbar zu machen, müssen Sie die Standardprotokollstufe ändern. Nach dem Erstellen einer Instanz der Logger-Ereignisregistrierung wurde der Wert
process.env.LOG_LEVEL
festgelegt. Dies bedeutet, dass Sie den Wert ändern oder den Standardinfowert akzeptieren können.
LOG_LEVEL=debug node index.js
Ausführen von
LOG_LEVEL=debug node index.js
ändern wir die Protokollstufe.
Zuvor muss das Problem des Ausgabeformats gelöst werden, das derzeit für die Wahrnehmung nicht sehr praktisch ist. Dieser Schritt ist beabsichtigt. Gemäß der
pino
Philosophie ist es aus Leistungsgründen erforderlich, die Verarbeitung von Journaleinträgen in einen separaten Prozess zu übertragen und die Ausgabe (unter Verwendung des Operators
|
) zu übergeben. Der Prozess umfasst das Übersetzen der Ausgabe in ein für die menschliche Wahrnehmung geeigneteres Format oder das Hochladen in die Cloud. Diese Aufgabe wird von Transferwerkzeugen ausgeführt, die als
transports
. Lesen Sie in der
Dokumentation zum
transports
Toolkit nach, warum
pino
Fehler nicht über
stderr
ausgegeben werden.
Verwenden Sie das
pino-pretty
Tool, um eine besser lesbare Version des Magazins anzuzeigen. Im Terminal ausführen:

Alle Protokolleinträge werden mit dem
|
zur Verfügung von
pino-pretty
, wodurch die Ausgabe "gelöscht" wird, die nur wichtige Informationen enthält, die in verschiedenen Farben angezeigt werden. Wenn Sie
localhost : 3000 erneut abfragen, sollte eine
debug
Debugging-Meldung angezeigt werden.

Um Journaleinträge besser lesbar zu machen oder zu konvertieren, gibt es viele Übertragungswerkzeuge. Sie können sogar mit Emojis mit
pino-colada
angezeigt werden. Diese Tools sind nützlich für die lokale Entwicklung. Wenn der Server in Produktion ist, müssen Sie möglicherweise Protokolldaten mit
einem anderen Tool übertragen , zur weiteren Verarbeitung mit
>
auf die Festplatte schreiben oder zwei Vorgänge gleichzeitig mit einem bestimmten Befehl ausführen, z. B.
tee
.
Das
Dokument behandelt auch das Drehen von Protokolldateien, das Filtern und Schreiben von Protokolldaten in andere Dateien.
Bibliotheksjournal
Indem Sie nach Möglichkeiten suchen, die Protokollierung für Serveranwendungen effizient zu organisieren, können Sie dieselbe Technologie für Ihre eigenen Bibliotheken verwenden.
Das Problem ist, dass Sie im Fall der Bibliothek möglicherweise ein Protokoll für Debugging-Zwecke führen müssen, ohne die Client-Anwendung zu laden. Im Gegenteil, der Client sollte in der Lage sein, das Protokoll zu aktivieren, wenn ein Debugging erforderlich ist. Standardmäßig sollte die Bibliothek keine Ausgabe aufzeichnen, wodurch der Benutzer dieses Recht erhält.
Ein gutes Beispiel hierfür ist das
express
Framework. Viele Prozesse finden in der internen Struktur des
express
Frameworks statt, was das Interesse wecken kann, es während des Debuggens von Anwendungen eingehender zu untersuchen. In der
Dokumentation zum express
Framework heißt es, dass Sie
DEBUG=express:*
am Anfang des Befehls wie folgt hinzufügen können:

Wenn Sie diesen Befehl auf eine vorhandene Anwendung anwenden, werden viele zusätzliche Ausgaben angezeigt, die beim Debuggen hilfreich sind:

Diese Informationen können nur angezeigt werden, wenn das Debug-Protokoll aktiviert ist.
debug
gibt es ein
debug
Paket. Es kann verwendet werden, um Nachrichten in den "Namespace" zu schreiben. Wenn der Bibliotheksbenutzer diesen Namespace oder einen Platzhalter, der mit ihm übereinstimmt, in seine
DEBUG
Umgebungsvariable einfügt , werden die Nachrichten angezeigt. Zuerst müssen Sie die
debug
Bibliothek installieren:

Erstellen Sie eine neue Datei mit dem Namen
random-id.j
s, die die Bibliothek simuliert, und
random-id.j
den folgenden Code ein:

Als Ergebnis wird ein neuer
debug
Ereignisprotokollierer mit dem
mylib:randomid
, in dem dann zwei Nachrichten registriert werden. Wir verwenden es in
index.js
aus dem vorherigen Abschnitt:

Wenn Sie den Server erneut starten und diesmal
DEBUG=mylib:randomid node index.js
, werden die Debug-Protokolleinträge für unsere "Bibliothek" angezeigt:

Wenn Bibliotheksbenutzer Debug-Informationen in
pino
Protokolleinträge
pino
möchten, können sie eine vom Befehl
pino-debug
erstellte Bibliothek namens
pino-debug
, um diese Einträge korrekt zu formatieren.
Installieren Sie die Bibliothek:

Vor der ersten Verwendung von
debug
muss
pino-debug
initialisiert werden. Der einfachste Weg, dies zu tun, besteht darin, die
Flags -r
oder --require
zu verwenden, um ein Modul anzufordern, bevor das Skript ausgeführt wird. Wir starten den Server mit dem Befehl neu (vorausgesetzt,
pino-colada
installiert):

Infolgedessen werden die Debug-Protokolleinträge der Bibliothek auf dieselbe Weise wie im Anwendungsprotokoll angezeigt:

Ausgabe der Befehlszeilenschnittstelle (CLI)
Der letzte Fall, den dieser Artikel behandelt, ist die Protokollierung für die Befehlszeilenschnittstelle. Vorzugsweise wird das Protokoll, das Ereignisse im Zusammenhang mit der Programmlogik aufzeichnet, vom Protokoll zum Registrieren von Befehlszeilenschnittstellendaten getrennt gehalten. Um Ereignisse im Zusammenhang mit der Programmlogik aufzuzeichnen, müssen Sie eine bestimmte Bibliothek verwenden, z. B.
debug
. In diesem Fall können Sie die Programmlogik über die Befehlszeilenschnittstelle wiederverwenden, ohne auf ein Szenario beschränkt zu sein.
Durch Erstellen einer Befehlszeilenschnittstelle mit Node.js können Sie verschiedene Farben, Blöcke mit variablen Werten oder Formatierungswerkzeuge hinzufügen, um der Benutzeroberfläche ein optisch ansprechendes Aussehen zu verleihen. Sie müssen jedoch mehrere Szenarien berücksichtigen.
Einer von ihnen zufolge kann die Schnittstelle im Kontext eines kontinuierlichen Integrationssystems (CI) verwendet werden. In diesem Fall ist es besser, auf die Farbformatierung und die visuell überlastete Darstellung der Ergebnisse zu verzichten. Bei einigen kontinuierlichen Integrationssystemen ist das
CI
Flag gesetzt. Mit dem
is-ci
Paket, das mehrere solcher Systeme unterstützt, können Sie überprüfen, ob Sie sich in einem kontinuierlichen Integrationssystem befinden.
Einige Bibliotheken, wie z. B.
chalk
, definieren kontinuierliche Integrationssysteme und überschreiben die Ausgabe von farbigem Text an die Konsole. Mal sehen, wie es funktioniert.
Installieren Sie
chalk
mit dem
install chalk
npm
install chalk
cli.js
und erstellen Sie eine Datei mit dem Namen
cli.js
Fügen Sie die folgenden Zeilen in die Datei ein:

Wenn Sie dieses Skript jetzt mit dem
node cli.js
, werden die Ergebnisse in verschiedenen Farben dargestellt:

Wenn Sie das Skript jedoch mit
CI=true node cli.js
, wird die Farbformatierung der Texte abgebrochen:

In einem anderen denkwürdigen Szenario wird
stdout
im Terminalmodus ausgeführt, d. H. Daten werden an das Terminal ausgegeben. In diesem Fall können die Ergebnisse mit
boxen
gut angezeigt werden. Andernfalls wird die Ausgabe höchstwahrscheinlich in eine Datei oder an eine andere Stelle umgeleitet.
Sie können den Betrieb von
stdin
,
stdout
oder
stderr
Streams im Terminalmodus überprüfen, indem Sie sich das
isTTY
Attribut des entsprechenden Streams
isTTY
. Zum Beispiel
process.stdout.isTTY
.
TTY
bedeutet "Teletypewriter" und ist in diesem Fall speziell für das Terminal konzipiert.
Die Werte können für jeden der drei Threads variieren, je nachdem, wie die Node.js-Prozesse gestartet wurden. Detaillierte Informationen hierzu finden Sie in der
Node.js-Dokumentation im Abschnitt „Eingabe / Ausgabe von Prozessen“ .
Mal sehen, wie sich der Wert von
process.stdout.isTTY
in verschiedenen Situationen
process.stdout.isTTY
.
cli.js
Datei
cli.js
, um sie zu überprüfen:

Führen Sie nun den
node cli.js
im Terminal aus und sehen Sie das Wort
true
node cli.js
die Nachricht in farbiger Schrift angezeigt:

Danach führen wir den Befehl erneut aus, leiten die Ausgabe jedoch in eine Datei um und zeigen dann den Inhalt an:

Dieses Mal wurde das
undefined
Wort im Terminal angezeigt, gefolgt von einer Meldung in farbloser Schrift, da der
stdout
Stream es aus dem Terminalmodus umgeleitet hat. Hier verwendet
chalk
das
isTTY
supports-color
Tool, das aus Sicht der internen Struktur die
isTTY
entsprechenden Streams überprüft.

Werkzeuge wie
chalk
erledigen diese Dinge selbstständig. Wenn Sie jedoch eine Befehlszeilenschnittstelle entwickeln, sollten Sie immer Situationen berücksichtigen, in denen die Schnittstelle in einem kontinuierlichen Integrationssystem funktioniert oder die Ausgabe umgeleitet wird. Mit diesen Tools können Sie die Befehlszeilenschnittstelle auf einer höheren Ebene verwenden. Beispielsweise können die Daten im Terminal strukturierter organisiert werden. Wenn
isTTY
undefined
, wechseln Sie zu einer einfacheren Analysemethode.
Fazit
Die Verwendung von JavaScript und die Eingabe der ersten Zeile in das Konsolenprotokoll mit
console.log
recht einfach. Bevor Sie den Code in der Produktion bereitstellen, sollten Sie jedoch verschiedene Aspekte der Verwendung des Protokolls berücksichtigen. Dieser Artikel ist nur eine Einführung in die verschiedenen Methoden und Lösungen, die beim Organisieren des Ereignisprotokolls verwendet werden. Es enthält nicht alles, was Sie wissen müssen. Daher wird empfohlen, auf erfolgreiche Open Source-Projekte zu achten und zu überwachen, wie sie das Protokollierungsproblem gelöst haben und welche Tools verwendet werden. Und jetzt versuchen Sie, sich zu protokollieren, ohne Daten an die Konsole auszugeben.
Wenn Sie andere erwähnenswerte Tools kennen, schreiben Sie in den Kommentaren darüber.