Node.js - registrazione / Usa morgan e winston


99

usiamo morganper registrare la nostra trasformazione espressa:

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;
})

Inoltre, utilizziamo winstonper registrare le nostre altre registrazioni:

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' })
  ]
});

C'è un modo per combinare i due logger insieme? la situazione ora è che morganscrive sul mio output standard, quando winstonscrive su /var/log/log-file.log.

Vorrei che il file logger si combinasse dalle informazioni di trasformazione espressa e dalle altre informazioni che voglio ( logger.info()) ..


Che senso ha fare questo, voglio dire, perché avevi bisogno di Morgan all'inizio, perché non scrivere semplicemente un middlewrare Winston per Express?
Dimitri Kopriwa,

Risposte:


141

Questo articolo fa un ottimo lavoro per quello che vuoi fare.

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

Per il tuo codice specifico probabilmente avrai bisogno di qualcosa del genere:

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 }));

Questo imposterà Winston per scrivere un registro sulla console e un file. Quindi è possibile utilizzare l'ultima espressione per trasferire l'output dal middleware morgan a winston.


Possiamo usare un timestamp in questo processo?
bombayquant

23
Non sembra che sia necessario sovrascrivere logger.stream .. Nel mio caso, sono stato in grado di fareapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Devon Sams

17
Se stai usando il metodo di @ DevonSams, otterrai una riga vuota tra le righe registrate perché sia ​​morgan che winston aggiungono un'interruzione di riga alla fine del messaggio registrato. Puoi semplicemente ritagliare l'interruzione di riga dal messaggio conlogger.info(message.trim())
Timo

2
E se volessi usare logger.error invece di logger.info, se il server risponde con 500?
Alendorff

3
Da winston: ^3.0.0utilizzare al winston.createLoggerposto dinew winston.Logger
streof

21

In dattiloscritto:

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 }));

Perché minuscolo e non combinato?
An-droide

Non ero più in grado di farlo funzionare. Sembra che la digitazione non sia corretta. stackoverflow.com/questions/50048193/...
jpetitte

7

Aggiorna l'ultima riga per rimuovere l'avviso

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

3

per Typescript è un altro modo per farlo, senza la necessità di creare una classe

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 }));

Questa soluzione è stata ricavata da questa pagina Github https://github.com/winstonjs/winston/issues/1385 . Tuttavia, è importante notare che c'è una leggera differenza tra i nostri codici. Invece di:

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

Io uso:

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

Questo mi ha aiutato perché non sono troppo bravo a creare classi.


1

Morgan ha la cattiva abitudine di terminare il messaggio con un messaggio, \nquindi per rendere le cose in ordine potresti rimuoverlo prima di scriverlo a Winston.

Questo può essere fatto in molti modi diversi, come sul lato formato in Winston, o aggiornando il tuo stream per non scrivere il file \n

class MyStream {
    write(text: string) {
        logger.info(text.replace(/\n$/, ''));
    }
}
let myStream = new MyStream()
app.use(morgan('tiny', { stream: myStream }));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.