Node.js - registro / uso de morgan e winston

99

que usamos morganpara registrar nossa transformação expressa:

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

Além disso, usamos winstonpara registrar nossos outros 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' })
  ]
});

Existe alguma maneira de combinar os dois madeireiros juntos? a situação agora é que morgané gravar na minha saída padrão, quando winstongrava em /var/log/log-file.log.

Desejo que o arquivo logger se combine com as informações de transformação expressa e com as outras informações que desejo ( logger.info()) ..

Ou Smith
fonte
Qual é o objetivo de fazer isso, quero dizer, por que você precisava de Morgan no início, por que não apenas escrever um middlewrare winston para expresso?
Dimitri Kopriwa

Respostas:

141

Este artigo faz um excelente trabalho para o que você deseja fazer.

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

Para o seu código específico, você provavelmente precisará de algo assim:

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

Isso configurará o Winston para gravar um log no console, bem como um arquivo. Em seguida, você pode usar a última expressão para passar a saída do middleware Morgan para o winston.

lindsaymacvean
fonte
Podemos usar um carimbo de data / hora neste processo?
bombayquant
23
Não parece ser necessário substituir logger.stream .. No meu caso, eu consegui fazerapp.use(morgan("combined", { stream: { write: message => logger.info(message) }}));
Devon Sams
17
Se estiver usando o método de @DevonSams, você obterá uma linha vazia entre as linhas registradas porque tanto morgan quanto winston estão adicionando uma quebra de linha no final da mensagem registrada. Você pode simplesmente cortar a quebra de linha da mensagem comlogger.info(message.trim())
Timo
2
E se eu quiser usar logger.error em vez de logger.info, se o servidor responder com 500?
Alendorff de
3
Para winston: ^3.0.0usar em winston.createLoggervez denew winston.Logger
streof de
21

No texto datilografado:

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
fonte
Por que minúsculo e não combinado?
An-droid
Eu não conseguia mais fazer isso funcionar. Parece que a digitação está incorreta. stackoverflow.com/questions/50048193/…
jpetitte
7

Atualize a última linha para remover o aviso

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

para o Typescript, outra maneira de fazer isso, sem a necessidade de criar uma 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 }));

Esta solução foi obtida desta página do Github https://github.com/winstonjs/winston/issues/1385 . No entanto, é importante notar que há uma pequena diferença entre nossos códigos. Ao invés de:

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

Eu uso:

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

Isso me ajudou, pois não sou muito fã de criar classes.

Cris Shaki
fonte
1

Morgan tem o mau hábito de terminar a mensagem com um \n , para deixar as coisas em ordem, você pode querer removê-lo antes de escrever para o winston.

Isso pode ser feito de muitas maneiras diferentes, como no lado do formato no winston, ou atualizando seu fluxo para não escrever o \n

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