Ein Logger für fast alles.
Weitere Informationen finden Sie im Upgrade-Handbuch. Fehlerberichte und PRs willkommen!
[email protected]
? Bitte beachten Sie, dass die folgende Dokumentation für winston@3
gilt. Lesen Sie die Dokumentation [email protected]
.
winston
ist als einfache und universelle Protokollierungsbibliothek mit Unterstützung für mehrere Transporte konzipiert. Ein Transporter ist im Wesentlichen ein Speichergerät für Ihre Protokolle. Für jeden winston
-Logger können mehrere Transporte (siehe: Transporte) auf verschiedenen Ebenen konfiguriert sein (siehe: Protokollierungsebenen). Beispielsweise möchte man möglicherweise, dass Fehlerprotokolle an einem dauerhaften Remote-Speicherort (z. B. einer Datenbank) gespeichert werden, alle Protokolle jedoch an die Konsole oder eine lokale Datei ausgegeben werden.
winston
zielt darauf ab, Teile des Protokollierungsprozesses zu entkoppeln, um ihn flexibler und erweiterbarer zu machen. Es wird darauf geachtet, Flexibilität bei der Protokollformatierung (siehe: Formate) und Ebenen (siehe: Verwenden benutzerdefinierter Protokollierungsebenen) zu unterstützen und sicherzustellen, dass diese APIs von der Implementierung der Transportprotokollierung entkoppelt sind (d. h. wie die Protokolle gespeichert/indiziert werden, siehe: Hinzufügen von benutzerdefinierten Protokollen). Transporte) an die API weiterleiten, die sie dem Programmierer zugänglich gemacht haben.
TL;DR? Schauen Sie sich das Schnellstartbeispiel in ./examples/
an. Es gibt eine Reihe weiterer Beispiele in ./examples/*.js
. Sehen Sie kein Beispiel, das Ihrer Meinung nach dort sein sollte? Senden Sie eine Pull-Anfrage, um es hinzuzufügen!
Die empfohlene Methode zur Verwendung winston
besteht darin, einen eigenen Logger zu erstellen. Der einfachste Weg, dies zu tun, ist die Verwendung von winston.createLogger
:
const winston = require('winston');const logger = winston.createLogger({ level: 'info', format: winston.format.json(), defaultMeta: { service: 'user-service' }, transports: [ / // – Alle Protokolle mit der Wichtigkeitsstufe „error“ oder höher in „error.log“ schreiben // (d. h. Fehler, schwerwiegend, aber keine anderen Stufen) // new winston.transports.File({ filename: 'error.log', level: 'error' }), // // – Schreiben Sie alle Protokolle mit der Wichtigkeitsstufe „info“ oder höher in „combined.log“ // (d. h. schwerwiegend, Fehler, Warnung und Info). , aber keine Spur) // new winston.transports.File({ filename: 'combined.log' }), ],});//// Wenn wir nicht in der Produktion sind, melden Sie sich mit dem bei der „Konsole“ an Format:// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `//if (process.env.NODE_ENV !== 'produktion') { logger.add(new winston. transports.Console({ format: winston.format.simple(), }));}
Sie können auch direkt über den von require('winston')
bereitgestellten Standard-Logger protokollieren, dieser ist jedoch lediglich als praktischer gemeinsamer Logger gedacht, den Sie bei Bedarf in Ihrer gesamten Anwendung verwenden können. Beachten Sie, dass der Standard-Logger standardmäßig keine Transporte hat. Sie müssen Transporte selbst hinzufügen. Wenn Sie den Standard-Logger ohne Transporte belassen, kann dies zu einem Problem mit der hohen Speicherauslastung führen.
Motivation
Schnellstart
Verwendung
Inhaltsverzeichnis
Protokollierung
Erstellen Sie Ihren Logger
Streams, objectMode
und info
-Objekte
Formate
Formate kombinieren
String-Interpolation
info
filtern
Erstellen benutzerdefinierter Formate
Protokollierungsstufen
Protokollierungsstufen verwenden
Verwenden benutzerdefinierter Protokollierungsstufen
Transporte
Mehrere Transporte desselben Typs
Benutzerdefinierte Transporte hinzufügen
Gemeinsame Transportmöglichkeiten
Ausnahmen
Umgang mit nicht abgefangenen Ausnahmen mit Winston
Aussteigen oder nicht aussteigen
Ablehnungen
Umgang mit nicht erfassten Ablehnungen von Versprechen mit Winston
Profilierung
Streaming-Protokolle
Protokolle abfragen
Weiterführende Literatur
Verwendung des Standard-Loggers
Warten auf das Schreiben von Protokollen in winston
Arbeiten mit mehreren Loggern in winston
Leitet Konsolentransportnachrichten an die Konsole statt an stdout und stderr weiter
Installation
Führen Sie Tests durch
Die Protokollierungsstufen in winston
entsprechen der in RFC5424 festgelegten Schweregradreihenfolge: Es wird davon ausgegangen, dass der Schweregrad aller Stufen numerisch aufsteigend ist, von der wichtigsten zur unwichtigsten.
const Levels = { Fehler: 0, Warnung: 1, Info: 2, http: 3, ausführlich: 4, Debug: 5, albern: 6};
Sie beginnen mit der Erstellung eines Loggers mit winston.createLogger
:
const logger = winston.createLogger({ transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'combined.log' }) ]});
Ein Logger akzeptiert die folgenden Parameter:
Name | Standard | Beschreibung |
---|---|---|
level | 'info' | Nur protokollieren, wenn info.level kleiner oder gleich diesem Level ist |
levels | winston.config.npm.levels | Ebenen (und Farben), die Protokollprioritäten darstellen |
format | winston.format.json | Formatierung für info (siehe: Formate) |
transports | [] (Keine Transporte) | Satz von Protokollierungszielen für info |
exitOnError | true | Bei „false“ führen behandelte Ausnahmen nicht zu process.exit |
silent | false | Bei „true“ werden alle Protokolle unterdrückt |
Die für createLogger
bereitgestellten Ebenen werden als praktische Methoden für den zurückgegebenen logger
definiert.
//// Protokollierung//logger.log({ level: 'info', message: 'Hallo verteilte Protokolldateien!'});logger.info('Hallo nochmal verteilte Protokolle');
Sie können dem logger
Transporte hinzufügen oder daraus entfernen, sobald er Ihnen von winston.createLogger
bereitgestellt wurde:
const files = new winston.transports.File({ filename: 'combined.log' });const console = new winston.transports.Console();logger .clear() // Alle Transporte entfernen .add(console) // Konsolentransport hinzufügen .add(files) // Dateitransport hinzufügen .remove(console); // Konsolentransport entfernen
Sie können eine winston.Logger
-Instanz auch umfassend neu konfigurieren, indem Sie die Methode configure
verwenden:
const logger = winston.createLogger({ level: 'info', transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'combined.log' }) ]});/// / Ersetzt die vorherigen Transporte durch diejenigen in der// neuen Konfiguration wholesale.//const DailyRotateFile = require('winston-daily-rotate-file');logger.configure({ level: 'verbose', transportiert: [ new DailyRotateFile(opts) ]});
Sie können untergeordnete Logger aus vorhandenen Loggern erstellen, um Metadatenüberschreibungen zu übergeben:
const logger = winston.createLogger({ transports: [ new winston.transports.Console(), ]});const childLogger = logger.child({ requestId: '451' });
.child
ist wahrscheinlich fehlerhaft, wenn Sie auch dieLogger
-Klasse erweitern, da einige Implementierungsdetails dazu führen, dassthis
Schlüsselwort auf unerwartete Dinge verweist. Mit Vorsicht verwenden.
objectMode
und info
-Objekte In winston
werden sowohl Logger
als auch Transport
als objectMode
Streams behandelt, die ein info
Objekt akzeptieren.
Der für ein bestimmtes Format bereitgestellte info
Parameter stellt eine einzelne Protokollnachricht dar. Das Objekt selbst ist veränderlich. Jede info
muss mindestens die level
und message
haben:
const info = { level: 'info', // Level der Protokollierungsnachricht message: 'Hey! Etwas protokollieren?' // Beschreibende Nachricht, die protokolliert wird.};
Eigenschaften außer Level und Nachricht werden als „ meta
“ betrachtet. dh:
const { level, message, ...meta } = info;
Mehrere der Formate in logform
selbst fügen zusätzliche Eigenschaften hinzu:
Eigentum | Format hinzugefügt von | Beschreibung |
---|---|---|
splat | splat() | String-Interpolations-Splat für Nachrichten %d %s -Stil. |
timestamp | timestamp() | Zeitstempel, mit dem die Nachricht empfangen wurde. |
label | label() | Benutzerdefiniertes Etikett, das jeder Nachricht zugeordnet ist. |
ms | ms() | Anzahl der Millisekunden seit der vorherigen Protokollmeldung. |
Als Verbraucher können Sie beliebige Eigenschaften hinzufügen – der interne Status wird durch Symbol
verwaltet:
Symbol.for('level')
(schreibgeschützt) : entspricht der level
Eigenschaft. Wird von allen Codes als unveränderlich behandelt.
Symbol.for('message'):
vollständige Zeichenfolgennachricht, die durch „Finalisieren von Formaten“ festgelegt wurde:
json
logstash
printf
prettyPrint
simple
Symbol.for('splat')
: zusätzliche String-Interpolationsargumente. Wird ausschließlich vom splat()
Format verwendet.
Diese Symbole werden in einem anderen Paket gespeichert: triple-beam
sodass alle Verbraucher von logform
dieselbe Symbolreferenz haben können. dh:
const { LEVEL, MESSAGE, SPLAT } = require('triple-beam');console.log(LEVEL === Symbol.for('level'));// trueconsole.log(MESSAGE === Symbol.for( 'message'));// trueconsole.log(SPLAT === Symbol.for('splat'));// true
HINWEIS: Jede
{ message }
-Eigenschaft in einem bereitgestelltenmeta
wird automatisch mit jeder bereits bereitgestelltenmsg
verkettet: Im Folgenden wird beispielsweise „world“ mit „hello“ verkettet:logger.log('error', 'hello', { message: 'world' });logger.info('hello', { message: 'world' });
Auf Formate in winston
kann über winston.format
zugegriffen werden. Sie werden in logform
implementiert, einem separaten Modul von winston
. Dies ermöglicht Flexibilität beim Schreiben Ihrer eigenen Transporte, falls Sie Ihrem Transport ein Standardformat hinzufügen möchten.
In modernen Versionen von node
sind sie sehr leistungsfähig und werden für die meisten Endbenutzerformatierungen empfohlen. Wenn Sie Ihre Protokolle individuell formatieren möchten, ist winston.format.printf
genau das Richtige für Sie:
const { createLogger, format, transports } = require('winston');const { combine, timestamp, label, printf } = format;const myFormat = printf(({ level, message, label, timestamp }) => { return ` ${timestamp} [${label}] ${level}: ${message}`;});const logger = createLogger({ format: kombinieren( label({ label: 'right miau!' }), timestamp(), myFormat ), transports: [new transports.Console()]});
Informationen zu den verfügbaren integrierten Formaten und zum Erstellen eigener benutzerdefinierter Protokollierungsformate finden Sie unter logform
.
Mit format.combine
können beliebig viele Formate zu einem einzigen Format kombiniert werden. Da format.combine
keine opts
benötigt, gibt es der Einfachheit halber eine vorab erstellte Instanz des kombinierten Formats zurück.
const { createLogger, format, transports } = require('winston');const { Combine, Timestamp, Label, PrettyPrint } = Format;const logger = createLogger({ Format: Combine( Label({ Label: 'Right Meow!' } ), timestamp(), PrettyPrint() ), transports: [new transports.Console()]})logger.log({ level: 'info', message: 'Um wie viel Uhr findet der Test statt?'});// Outputs:// { level: 'info',// message: 'Um wie viel Uhr findet der Test statt?',// label: 'Richtig miau!',// timestamp: '2017-09-30T03:57:26.875Z ' }
Die log
stellt die Zeichenfolgeninterpolation mithilfe von util.format bereit. Es muss mit format.splat()
aktiviert werden.
Unten sehen Sie ein Beispiel, das ein Format mit String-Interpolation von Nachrichten mithilfe von format.splat
definiert und dann die gesamte info
Nachricht mithilfe von format.simple
serialisiert.
const { createLogger, format, transports } = require('winston');const logger = createLogger({ format: format.combine( format.splat(), format.simple() ), transports: [new transports.Console() ]});// info: test message my string {}logger.log('info', 'test message %s', 'my string');// info: test message 123 {}logger.log('info ', 'test message %d', 123);// info: test message first second {number: 123}logger.log('info', 'test message %s, %s', 'first', 'second', { Nummer: 123 });
info
filtern Wenn Sie ein bestimmtes info
Objekt bei der Protokollierung vollständig herausfiltern möchten, geben Sie einfach einen falschen Wert zurück.
const { createLogger, format, transports } = require('winston');// Protokollnachrichten ignorieren, wenn sie { private: true }constignorePrivate = format((info, opts) => { if (info.private) { return false; } return info;});const logger = createLogger({ format: format.combine(ignorePrivate(), format.json() ), transports: [new transports.Console()]});// Ausgaben: {"level": "error", "message": "Öffentlicher Fehler zum Teilen"}logger.log({ level: 'error', message: 'Öffentlicher Fehler an share'});// Nachrichten mit { private: true } werden nicht geschrieben, wenn loggt.logger.log({ private: true, level: 'error', message: 'This is supersecret – hide it.'}) ;
Durch die Verwendung von format.combine
werden alle zurückgegebenen falschen Werte berücksichtigt und die Auswertung späterer Formate in der Serie gestoppt. Zum Beispiel:
const { format } = require('winston');const { combinate, timestamp, label } = format;const willNeverThrow = format.combine( format(info => { return false })(), // Ignoriert alles format(info => { throw new Error('Nie erreicht') })());
Formate sind prototypische Objekte (d. h. Klasseninstanzen), die eine einzelne Methode definieren: transform(info, opts)
und die mutierte info
zurückgeben:
info
: ein Objekt, das die Protokollnachricht darstellt.
opts
: Einstellung speziell für die aktuelle Instanz des Formats.
Von ihnen wird erwartet, dass sie eines von zwei Dingen zurückgeben:
Ein info
Objekt, das das geänderte info
Argument darstellt. Objektverweise müssen nicht beibehalten werden, wenn Unveränderlichkeit bevorzugt wird. Alle aktuellen integrierten Formate betrachten info
als veränderbar, aber [immutablejs] wird für zukünftige Versionen in Betracht gezogen.
Ein falscher Wert, der angibt, dass das info
-Argument vom Aufrufer ignoriert werden soll. (Siehe: info
filtern) unten.
winston.format
ist so einfach wie möglich gestaltet. Um ein neues Format zu definieren, übergeben Sie ihm einfach eine transform(info, opts)
-Funktion, um ein neues Format
zu erhalten.
Das zurückgegebene benannte Format
kann verwendet werden, um beliebig viele Kopien des angegebenen Format
zu erstellen:
const { format } = require('winston');const volume = format((info, opts) => { if (opts.yell) { info.message = info.message.toUpperCase(); } else if (opts. whisper) { info.message = info.message.toLowerCase(); } return info;});// `volume` ist jetzt eine Funktion, die Instanzen des Formats zurückgibt.const Scream = volume({ yell: true });console.dir(scream.transform({ level: 'info', message: `Es tut mir leid, dass du in deinem Kopf geschrien hast!`},cream.options));// {// level: 'info'// message: 'Tut mir leid, dass ich dich in deinem Kopf zum Schreien gebracht habe!'// }// `volume` kann mehrfach verwendet werden, um verschiedene Formate zu erstellen.const whisper = volume({ whisper: true });console.dir(whisper.transform({ level: 'info', message: `Warum bringen sie uns so sehr zum Schreien!`}, whisper.options));// {// level: ' info'// Nachricht: 'Warum bringen sie uns so viel zum Schreien!'// }
Die Protokollierungsstufen in winston
entsprechen der in RFC5424 festgelegten Schweregradreihenfolge: Es wird davon ausgegangen, dass der Schweregrad aller Stufen numerisch aufsteigend ist, von der wichtigsten zur unwichtigsten.
Jeder level
wird eine bestimmte ganzzahlige Priorität zugewiesen. Je höher die Priorität, desto wichtiger wird die Nachricht eingeschätzt und desto niedriger ist die entsprechende ganzzahlige Priorität. Beispielsweise werden die syslog
-Ebenen, wie in RFC5424 genau festgelegt, von 0 bis 7 (von der höchsten zur niedrigsten) priorisiert.
{Emerg: 0, Alert: 1, Crit: 2, Error: 3, Warning: 4, Notice: 5, Info: 6, Debug: 7}
In ähnlicher Weise werden npm
Protokollierungsstufen von 0 bis 6 (von der höchsten zur niedrigsten) priorisiert:
{ Fehler: 0, Warnung: 1, Info: 2, http: 3, ausführlich: 4, Debug: 5, albern: 6}
Wenn Sie die Ebenen, die winston
verwenden soll, nicht explizit definieren, werden die oben genannten npm
Ebenen verwendet.
Das Festlegen der Ebene für Ihre Protokollierungsnachricht kann auf zwei Arten erfolgen. Sie können eine Zeichenfolge, die die Protokollierungsebene darstellt, an die log()-Methode übergeben oder die auf der Ebene angegebenen Methoden verwenden, die in jedem Winston-Logger definiert sind.
//// Beliebige Logger-Instanz//logger.log('silly', "127.0.0.1 - there's no place like home");logger.log('debug', "127.0.0.1 - there's no place like home") ;logger.log('verbose', "127.0.0.1 - Es gibt keinen Ort wie zu Hause");logger.log('info', "127.0.0.1 - Es gibt keinen Ort wie ein Zuhause");logger.log('warn', "127.0.0.1 - Es gibt keinen Ort wie ein Zuhause");logger.log('error', "127.0.0.1 - Es gibt keinen Ort wie ein Zuhause"); logger.info("127.0.0.1 - Es gibt keinen Ort wie zu Hause");logger.warn("127.0.0.1 - Es gibt keinen Ort wie zu Hause home");logger.error("127.0.0.1 - Es gibt keinen Ort wie ein Zuhause");//// Default logger//winston.log('info', "127.0.0.1 - Es gibt keinen Ort wie ein Zuhause"); winston.info("127.0.0.1 - Es gibt keinen Ort wie zu Hause");
winston
können Sie für jeden Transport eine level
definieren, die die maximale Nachrichtenebene angibt, die ein Transport protokollieren soll. Mithilfe der syslog
Ebenen könnten Sie beispielsweise nur error
in der Konsole und alle info
und darunter in einer Datei protokollieren (die error
enthält):
const logger = winston.createLogger({levels: winston.config.syslog.levels, transports: [ new winston.transports.Console({ level: 'error' }), new winston.transports.File({ filename: 'combined. log', Ebene: 'info' }) ]});
Sie können die Protokollebene eines Transports auch dynamisch ändern:
const transports = { console: new winston.transports.Console({ level: 'warn' }), file: new winston.transports.File({ filename: 'combined.log', level: 'error' })};const logger = winston.createLogger({ transports: [ transports.console, transports.file ]});logger.info('Wird in keinem Transport angemeldet!');transports.console.level = 'info';transports.file.level = 'info';logger.info('Wird in beiden Transporten protokolliert!');
winston
unterstützt anpassbare Protokollierungsstufen und verwendet standardmäßig Protokollierungsstufen im NPM-Stil. Die Ebenen müssen zum Zeitpunkt der Erstellung Ihres Loggers angegeben werden.
Zusätzlich zu den vordefinierten npm
, syslog
und cli
-Ebenen, die in winston
verfügbar sind, können Sie auch Ihre eigenen definieren:
const myCustomLevels = { Ebenen: { foo: 0, bar: 1, baz: 2, foobar: 3 }, Farben: { foo: 'blau', bar: 'grün', baz: 'gelb', foobar: 'rot' }};const customLevelLogger = winston.createLogger({levels: myCustomLevels.levels});customLevelLogger.foobar('some foobar level-ed Nachricht');
Obwohl es in dieser Datenstruktur leichte Wiederholungen gibt, ermöglicht sie eine einfache Kapselung, wenn Sie keine Farben wünschen. Wenn Sie Farben wünschen, müssen Sie Winston zusätzlich zur Übergabe der Ebenen an den Logger selbst darüber informieren:
winston.addColors(myCustomLevels.colors);
Dadurch können Logger, die den colorize
-Formatierer verwenden, die Ausgabe benutzerdefinierter Ebenen entsprechend einfärben und formatieren.
Darüber hinaus können Sie auch die Hintergrundfarbe und den Schriftstil ändern. Zum Beispiel,
baz: 'kursiv gelb',foobar: 'fett rot cyanBG'
Mögliche Optionen finden Sie unten.
Schriftstile: bold
, dim
, italic
, underline
, inverse
, hidden
, strikethrough
.
Vordergrundfarben der Schriftart: black
, red
, green
, yellow
, blue
, magenta
, cyan
, white
, gray
, grey
.
Hintergrundfarben: blackBG
, redBG
, greenBG
, yellowBG
, blueBG
, magentaBG
, cyanBG
, whiteBG
Um die Standardprotokollierungsebene einzufärben, fügen Sie Folgendes hinzu:
winston.format.combine( winston.format.colorize(), winston.format.simple());
Dabei steht winston.format.simple()
für den anderen Formatierer, den Sie verwenden möchten. Der Formatierer colorize
muss vor allen Formatierern stehen, die Text hinzufügen, den Sie einfärben möchten.
Um die gesamte Protokollzeile mit dem JSON-Formatierer einzufärben, können Sie Folgendes anwenden
winston.format.combine( winston.format.json(), winston.format.colorize({ all: true }));
In winston
sind mehrere Kerntransporte enthalten, die das integrierte Netzwerk und die Datei-E/A nutzen, die der Node.js-Kern bietet. Darüber hinaus gibt es zusätzliche Transporte, die von Mitgliedern der Community geschrieben wurden.
Es ist möglich, beim Erstellen des Transports mehrere Transporte desselben Typs zu verwenden, z. B. winston.transports.File
.
const logger = winston.createLogger({ transports: [ new winston.transports.File({ filename: 'combined.log', level: 'info' }), new winston.transports.File({ filename: 'errors.log' , Ebene: 'Fehler' }) ]});
Wenn Sie später eines dieser Transportmittel entfernen möchten, können Sie dies tun, indem Sie das Transportmittel selbst verwenden. z.B:
const CombinedLogs = logger.transports.find(transport => { return transport.filename === 'combined.log'});logger.remove(combinedLogs);
Das Hinzufügen eines benutzerdefinierten Transportmittels ist einfach. Sie müssen lediglich alle benötigten Optionen akzeptieren, eine log()-Methode implementieren und diese mit winston
nutzen.
const Transport = require('winston-transport');const util = require('util');//// Von „winston-transport“ erben, damit Sie die Basisfunktionalität und „.Exceptions.handle“ nutzen können ()`.//module.exports = class YourCustomTransport erweitert Transport { constructionor(opts) { super(opts); // // Nutzen Sie hier alle benutzerdefinierten Optionen. zB: // - Verbindungsinformationen für Datenbanken // - Authentifizierungsinformationen für APIs (z. B. loggly, papertrail, // logentries usw.). // } log(info, callback) { setImmediate(() => { this.emit('logged', info); }); // Führen Sie das Schreiben in den Remote-Dienst durch callback(); }};
Da jeder Transport von winston-transport erbt, ist es möglich, für jeden Transport separat ein benutzerdefiniertes Format und eine benutzerdefinierte Protokollebene festzulegen:
const logger = winston.createLogger({ transports: [ new winston.transports.File({ filename: 'error.log', level: 'error', format: winston.format.json() }), new winston.transports. Http({ level: 'warn', format: winston.format.json() }), new winston.transports.Console({ level: 'info', format: winston.format.combine( winston.format.colorize(), winston.format.simple() ) }) ]});
Mit winston
ist es möglich, uncaughtException
Ereignisse aus Ihrem Prozess abzufangen und zu protokollieren. Mit Ihrer eigenen Logger-Instanz können Sie dieses Verhalten bei der Erstellung oder später im Lebenszyklus Ihrer Anwendung aktivieren:
const { createLogger, transports } = require('winston');// Ausnahmebehandlung aktivieren, wenn Sie Ihren Logger erstellen.const logger = createLogger({ transports: [ new transports.File({ filename: 'combined.log' }) ] ,ExceptionHandlers: [ new transports.File({ filename: 'Exceptions.log' }) ]});// Oder aktivieren Sie es später, indem Sie einen Transport hinzufügen oder verwenden `.Exceptions.handle`const logger = createLogger({ transports: [ new transports.File({ filename: 'combined.log' }) ]});// Ausnahmen.handle mit einem Transport aufrufen, um Ausnahmenlogger.Exceptions.handle zu behandeln ( new transports.File({ filename: 'Exceptions.log' }));
Wenn Sie diese Funktion mit dem Standard-Logger verwenden möchten, rufen Sie einfach .exceptions.handle()
mit einer Transportinstanz auf.
//// Sie können einen separaten Ausnahme-Logger hinzufügen, indem Sie ihn an „.Exceptions.handle“ übergeben//winston.Exceptions.handle( new winston.transports.File({ filename: 'path/to/Exceptions.log' }) );//// Alternativ können Sie „handleExceptions“ auf true setzen, wenn Sie transports// zu winston hinzufügen.//winston.add(new winston.transports.File({ filename: 'path/to/combined.log', handleExceptions: true}));
Standardmäßig wird Winston beendet, nachdem eine uncaughtException protokolliert wurde. Wenn dies nicht das gewünschte Verhalten ist, setzen Sie exitOnError = false
const logger = winston.createLogger({ exitOnError: false });//// oder, wie folgt:://logger.exitOnError = false;
Wenn Sie mit benutzerdefinierten Logger-Instanzen arbeiten, können Sie separate Transporte an die Eigenschaft exceptionHandlers
übergeben oder handleExceptions
für jeden Transport festlegen.
const logger = winston.createLogger({ transports: [ new winston.transports.File({ filename: 'path/to/combined.log' }) ],ExceptionHandlers: [ new winston.transports.File({ filename: 'path/ to/Exceptions.log' }) ]});
const logger = winston.createLogger({ transports: [ new winston.transports.Console({ handleExceptions: true }) ], exitOnError: false});
Die Option exitOnError
kann auch eine Funktion sein, um das Beenden nur bei bestimmten Fehlertypen zu verhindern:
functionignoreEpipe(err) { return err.code !== 'EPIPE';}const logger = winston.createLogger({exitOnError:ignoreEpipe });//// oder, so://logger.exitOnError =ignoreEpipe;
Mit winston
ist es möglich, unhandledRejection
-Ereignisse aus Ihrem Prozess abzufangen und zu protokollieren. Mit Ihrer eigenen Logger-Instanz können Sie dieses Verhalten bei der Erstellung oder später im Lebenszyklus Ihrer Anwendung aktivieren:
const { createLogger, transports } = require('winston');// Ablehnungsbehandlung aktivieren, wenn Sie Ihren Logger erstellen.const logger = createLogger({ transports: [ new transports.File({ filename: 'combined.log' }) ] , RejectionHandlers: [ new transports.File({ filename: 'rejections.log' }) ]});// Oder aktivieren Sie es später, indem Sie einen Transport hinzufügen oder verwenden `.rejections.handle`const logger = createLogger({ transports: [ new transports.File({ filename: 'combined.log' }) ]});// Rejections.handle mit einem Transport aufrufen, um Rejectionslogger.rejections.handle zu verarbeiten ( new transports.File({ filename: 'rejections.log' }));
Wenn Sie diese Funktion mit dem Standard-Logger verwenden möchten, rufen Sie einfach .rejections.handle()
mit einer Transportinstanz auf.
//// Sie können einen separaten Ablehnungslogger hinzufügen, indem Sie ihn an „.rejections.handle“ übergeben//winston.rejections.handle( new winston.transports.File({ filename: 'path/to/rejections.log' }) );//// Alternativ können Sie „handleRejections“ auf true setzen, wenn Sie transports// zu winston hinzufügen.//winston.add(new winston.transports.File({ filename: 'path/to/combined.log', handleRejections: true}));
Neben der Protokollierung von Nachrichten und Metadaten verfügt winston
auch über einen einfachen Profilierungsmechanismus, der für jeden Logger implementiert ist:
//// Profil von 'test' starten//logger.profile('test');setTimeout(function () { // // Profil von 'test' stoppen. Die Protokollierung findet nun statt: // '17 Jan 21 :00:00 - Info: Testdauer=1000ms' // logger.profile('test');}, 1000);
Sie können auch einen Timer starten und eine Referenz behalten, für die Sie .done()
aufrufen können:
// Gibt ein Objekt zurück, das einem bestimmten Zeitpunkt entspricht. Wenn done // aufgerufen wird, wird der Timer beendet und die Dauer protokolliert. zB: // const Profiler = logger.startTimer(); setTimeout(function () { Profiler.done({ message: 'Logging message' }); }, 1000);
Alle Profilnachrichten sind standardmäßig auf die Ebene „Info“ eingestellt und sowohl Nachrichten als auch Metadaten sind optional. Für einzelne Profilmeldungen können Sie die Standardprotokollebene überschreiben, indem Sie ein Metadatenobjekt mit einer level
bereitstellen:
logger.profile('test', { level: 'debug' });
winston
unterstützt die Abfrage von Protokollen mit Loggly-ähnlichen Optionen. Siehe Loggly Search API. Konkret: File
, Couchdb
, Redis
, Loggly
, Nssocket
und Http
.
const-Optionen = { von: neues Datum() - (24 * 60 * 60 * 1000), bis: neues Datum(), Grenze: 10, Start: 0, Reihenfolge: 'desc', Felder: ['Nachricht']} ;//// Elemente finden, die zwischen heute und gestern protokolliert wurden.//logger.query(options, function (err, results) { if (err) { /* TODO: handle me */ throw err; } console.log(Ergebnisse);});
Mit Streaming können Sie Ihre Protokolle von dem von Ihnen gewählten Transportmittel zurückstreamen.
//// Am Ende beginnen.//winston.stream({ start: -1 }).on('log', function(log) { console.log(log);});
Auf den Standard-Logger kann direkt über das winston
-Modul zugegriffen werden. Jede Methode, die Sie für eine Instanz eines Loggers aufrufen können, ist im Standard-Logger verfügbar:
const winston = require('winston');winston.log('info', 'Hallo verteilte Protokolldateien!');winston.info('Hallo nochmal verteilte Protokolle');winston.level = 'debug';winston.log („debug“, „Jetzt werden meine Debug-Meldungen auf die Konsole geschrieben!“);
Standardmäßig sind für den Standard-Logger keine Transporte festgelegt. Sie müssen Transporte über die Methoden add()
und remove()
hinzufügen oder entfernen:
const files = new winston.transports.File({ filename: 'combined.log' });const console = new winston.transports.Console();winston.add(console);winston.add(files);winston.remove (Konsole);
Oder machen Sie es mit einem Aufruf von configure():
winston.configure({ transports: [ new winston.transports.File({ filename: 'somefile.log' }) ]});
Weitere Dokumentation zur Arbeit mit jedem einzelnen von winston
unterstützten Transport finden Sie im Dokument winston
Transports“.
winston
Oft ist es sinnvoll, zu warten, bis Ihre Protokolle geschrieben wurden, bevor Sie den Vorgang beenden. Jede Instanz von winston.Logger
ist auch ein [Node.js-Stream]. Ein finish
-Ereignis wird ausgelöst, wenn nach Beendigung des Streams alle Protokolle an alle Transporte geleert wurden.
const transport = new winston.transports.Console();const logger = winston.createLogger({ transports: [transport]});logger.on('finish', function (info) { // Alle „Info“-Protokollnachrichten haben wurde jetzt protokolliert});logger.info('CHILL WINSTON!', { im Ernst: true });logger.end();
Erwähnenswert ist auch, dass der Logger auch ein „Fehler“-Ereignis ausgibt, wenn im Logger selbst ein Fehler auftritt, den Sie behandeln oder unterdrücken sollten, wenn Sie keine unbehandelten Ausnahmen wünschen:
//// Behandeln Sie Fehler, die im Logger selbst entstehen//logger.on('error', function (err) { /* Do Something */ });
In größeren, komplexeren Anwendungen ist es häufig erforderlich, mehrere Logger-Instanzen mit unterschiedlichen Einstellungen zu haben. Jeder Logger ist für einen anderen Funktionsbereich (oder eine andere Kategorie) verantwortlich. Dies wird in winston
auf zwei Arten offengelegt: durch winston.loggers
und Instanzen von winston.Container
. Tatsächlich ist winston.loggers
nur eine vordefinierte Instanz von winston.Container
:
const winston = require('winston');const { format } = winston;const { combine, label, json } = format;//// Konfigurieren Sie den Logger für „category1“//winston.loggers.add('category1' , { format: combine( label({ label: 'category one' }), json() ), transports: [ new winston.transports.Console({ level: 'silly' }), new winston.transports.File({ filename: 'somefile.log' }) ]});//// Konfigurieren Sie den Logger für „category2“//winston.loggers.add('category2', { format: combine( label ({ label: 'category two' }), json() ), transports: [ new winston.transports.Http({ host: 'localhost', port:8080 }) ]});
Nachdem Ihre Logger nun eingerichtet sind, können Sie Winston in jeder Datei Ihrer Anwendung anfordern und auf diese vorkonfigurierten Logger zugreifen:
const winston = require('winston');//// Schnappen Sie sich Ihre vorkonfigurierten Logger//const Category1 = winston.loggers.get('category1');const Category2 = winston.loggers.get('category2');category1. info('Protokollierung zu Datei- und Konsolentransporten');category2.info('Protokollierung zu HTTP-Transport');
Wenn Sie den Container
lieber selbst verwalten möchten, können Sie einfach einen instanziieren:
const winston = require('winston');const { format } = winston;const { kombinieren, label, json } = format;const container = new winston.Container();container.add('category1', { format: kombinieren ( label({ label: 'category one' }), json() ), transports: [ new winston.transports.Console({ level: 'silly' }), new winston.transports.File({ filename: 'somefile.log' }) ]});const Category1 = container.get('category1');category1.info('logging to file and console transports');
Standardmäßig sendet der Transport winston.transports.Console
Nachrichten an stdout
und stderr
. Das ist in den meisten Situationen in Ordnung; Es gibt jedoch einige Fälle, in denen dies nicht wünschenswert ist, darunter:
Debuggen mit VSCode und Anhängen an einen Node.js-Prozess, anstatt ihn zu starten
Schreiben von Nachrichten im JSON-Format in AWS Lambda
Protokollierung während Jest-Tests mit der Option --silent
Damit das Transportprotokoll stattdessen console.log()
, console.warn()
und console.error()
verwendet, setzen Sie die Option forceConsole
auf true
:
const logger = winston.createLogger({ level: 'info', transports: [new winston.transports.Console({ forceConsole: true })]});
NPM Winston installieren
Garn hinzufügen Winston
Alle Winston-Tests sind mit mocha
, nyc
und assume
geschrieben. Sie können mit npm
ausgeführt werden.
NPM-Test