Node.js - Protokollierung / Verwenden Sie Morgan und Winston

99

Wir verwenden morgan, um unsere Express-Transformation zu protokollieren:

var morgan  = require('morgan');
morgan('combined');
// a format string
morgan(':remote-addr :method :url :uuid');
// a custom function
morgan(function (req, res) {
  return req.method + ' ' + req.url + ' ' + req.uuid;
})

Außerdem verwenden wir, winstonum unsere andere Protokollierung zu protokollieren:

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
         new (winston.transports.Console)({ level: 'info' }),
          new (winston.transports.File)({ filename: '/var/log/log-file.log' })
  ]
});

Gibt es eine Möglichkeit, die beiden Logger miteinander zu kombinieren? die Situation jetzt ist , dass morganSchreiben in meinem Standard - Ausgabe ist, wenn winstonschreibt /var/log/log-file.log.

Ich wünsche mir, dass die Logger-Datei aus den Express-Transformationsinformationen und den anderen gewünschten Informationen ( logger.info()) kombiniert wird .

Oder Smith
quelle
Was bringt das, ich meine, warum brauchst du am Anfang Morgan, warum schreibst du nicht einfach eine Winston Middlewrare für Express?
Dimitri Kopriwa

Antworten:

141

Dieser Artikel leistet hervorragende Arbeit für das, was Sie tun möchten.

http://tostring.it/2014/06/23/advanced-logging-with-nodejs/

Für Ihren spezifischen Code benötigen Sie wahrscheinlich Folgendes:

var logger = new winston.Logger({
    transports: [
        new winston.transports.File({
            level: 'info',
            filename: './logs/all-logs.log',
            handleExceptions: true,
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        }),
        new winston.transports.Console({
            level: 'debug',
            handleExceptions: true,
            json: false,
            colorize: true
        })
    ],
    exitOnError: false
});

logger.stream = {
    write: function(message, encoding){
        logger.info(message);
    }
};

app.use(require("morgan")("combined", { "stream": logger.stream }));

Dadurch wird Winston so eingerichtet, dass er ein Protokoll sowie eine Datei in die Konsole schreibt. Dann können Sie den letzten Ausdruck verwenden, um die Ausgabe der Morgan Middleware an Winston zu übergeben.

Lindsaymacvean
quelle
Können wir in diesem Prozess einen Zeitstempel verwenden?
Bombayquant
23
Es scheint nicht notwendig zu sein, logger.stream zu überschreiben. In meinem Fall war ich in der Lageapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Devon Sams
17
Wenn Sie die Methode von @ DevonSams verwenden, wird zwischen den protokollierten Zeilen eine leere Zeile angezeigt, da sowohl Morgan als auch Winston am Ende der protokollierten Nachricht einen Zeilenumbruch hinzufügen. Sie können einfach den Zeilenumbruch aus der Nachricht mitlogger.info(message.trim())
Timo
2
Was ist, wenn ich logger.error anstelle von logger.info verwenden möchte, wenn der Server mit 500 antwortet?
Alendorff
3
Zur winston: ^3.0.0Verwendung winston.createLoggeranstelle vonnew winston.Logger
Streof
21

Im Typoskript:

let logger = new (winston.Logger)({
    exitOnError: false,
    level: 'info',
    transports: [
        new (winston.transports.Console)(),
        new (winston.transports.File)({ filename: 'app.log'})
    ]
})

class MyStream {
    write(text: string) {
        logger.info(text)
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
Mahyar SEPEHR
quelle
Warum winzig und nicht kombiniert?
An-Droide
Ich konnte das nicht mehr zum Laufen bringen. Es scheint, dass die Typisierungen falsch sind. stackoverflow.com/questions/50048193/…
jpetitte
7

Aktualisieren Sie die letzte Zeile, um die Warnung zu entfernen

app.use(require("morgan")("combined", { stream: logger.stream }));
Johnny
quelle
3

Für Typescript ist ein anderer Weg, dies zu tun, ohne eine Klasse erstellen zu müssen,

let logger = new (winston.Logger)({
    exitOnError: false,
    level: 'info',
    transports: [
        new (winston.transports.Console)(),
        new (winston.transports.File)({ filename: 'app.log'})
    ]
})

const myStream = {
    write: (text: string) => {
        logger.info(text)
    }
}

app.use(morgan('combined', { stream: myStream }));

Diese Lösung wurde von dieser Github-Seite https://github.com/winstonjs/winston/issues/1385 entfernt . Es ist jedoch wichtig zu beachten, dass es einen kleinen Unterschied zwischen unseren Codes gibt. Anstatt:

app.use(morgan('combined', { myStream }));

Ich benutze:

app.use(morgan('combined', { stream: myStream }));

Dies hat mir geholfen, da ich beim Erstellen von Klassen nicht zu groß bin.

Cris Shaki
quelle
1

Morgan hat die schlechte Angewohnheit, die Nachricht mit einem \nzu beenden , um die Dinge ordentlich zu machen. Vielleicht möchten Sie das entfernen, bevor Sie es an Winston schreiben.

Dies kann auf viele verschiedene Arten geschehen, beispielsweise auf der Formatseite in Winston oder durch Aktualisieren Ihres Streams, um das nicht zu schreiben \n

class MyStream {
    write(text: string) {
        logger.info(text.replace(/\n$/, ''));
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
user566245
quelle