Node.js: registro / uso de morgan y winston

99

que usamos morganpara registrar nuestra transformación expresa:

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

Además, usamos winstonpara registrar nuestros otros registros:

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

¿Hay alguna forma de combinar los dos registradores? la situación ahora es que morganse escribe en mi salida estándar, cuando se winstonescribe en /var/log/log-file.log.

Deseo que el archivo del registrador se combine a partir de la información de transformación expresa y de la otra información que quiero ( logger.info()) ..

O Smith
fuente
¿Cuál es el punto de hacer esto? Quiero decir, ¿por qué necesitabas a Morgan al principio? ¿Por qué no escribir un middlewrare de Winston para Express?
Dimitri Kopriwa

Respuestas:

141

Este artículo hace un excelente trabajo para lo que quiere hacer.

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

Para su código específico, probablemente necesite algo como esto:

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

Esto configurará Winston para escribir un registro en la consola, así como un archivo. Luego, puede usar la última expresión para pasar la salida del middleware morgan a winston.

lindsaymacvean
fuente
¿Podemos usar una marca de tiempo en este proceso?
bombayquant
23
No parece que sea necesario anular logger.stream .. En mi caso, pude hacerloapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Devon Sams
17
Si está utilizando el método de @ DevonSams, obtendrá una línea vacía entre las líneas registradas porque tanto morgan como winston están agregando un salto de línea al final del mensaje registrado. Simplemente puede recortar el salto de línea del mensaje conlogger.info(message.trim())
Timo
2
¿Qué pasa si quiero usar logger.error en lugar de logger.info, si el servidor responde con 500?
Alendorff
3
Para winston: ^3.0.0usar en winston.createLoggerlugar denew winston.Logger
streof
21

En mecanografiado:

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
fuente
¿Por qué diminuto y no combinado?
An-droide
Ya no pude hacer que esto funcionara. Parece que los tipos de letra son incorrectos. stackoverflow.com/questions/50048193/…
jpetitte
7

Actualice la última línea para eliminar la advertencia

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

para TypeScript, otra forma de hacerlo, sin necesidad de crear una clase es

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

Esta solución se obtuvo de esta página de Github https://github.com/winstonjs/winston/issues/1385 . Sin embargo, es importante tener en cuenta que existe una ligera diferencia entre nuestros códigos. En vez de:

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

Yo suelo:

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

Esto me ayudó, ya que no soy demasiado bueno para crear clases.

Cris Shaki
fuente
1

Morgan tiene el mal hábito de terminar el mensaje con un \nasí que para hacer las cosas ordenadas, es posible que desee eliminarlo antes de escribirlo a winston.

Esto se puede hacer de muchas formas diferentes, como en el lado del formato en winston, o actualizando su flujo para no escribir el \n

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