Como posso adicionar carimbo de data / hora aos logs usando a biblioteca Winston Node.js?

93

Quero adicionar carimbo de data / hora aos logs. Qual a melhor maneira de alcançar isto?

Kolrie
fonte
Isso permanece muito amplo porque você NÃO pode fazer isso na máquina cliente.
Joshua de

Respostas:

112

Eu mesmo estava lidando com o mesmo problema. Há duas maneiras de fazer isso.

Quando você inclui o Winston, geralmente o padrão é adicionar um transporte de console. Para fazer os carimbos de data / hora funcionarem neste caso padrão, eu precisava:

  1. Remova o transporte do console e adicione novamente com a opção de carimbo de data / hora.
  2. Crie seu próprio objeto Logger com a opção de carimbo de data / hora definida como true.

O primeiro:

var winston = require('winston');
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {'timestamp':true});

A segunda opção e mais limpa:

var winston = require('winston');
var logger = new (winston.Logger)({
    transports: [
      new (winston.transports.Console)({'timestamp':true})
    ]
});

Algumas das outras opções de transporte do console podem ser encontradas aqui :

  • level: Nível de mensagens que este transporte deve registrar (default 'debug').
  • silencioso: sinalizador booleano que indica se a saída deve ser suprimida (padrão falso).
  • colorize: Sinalizador booleano que indica se devemos colorir a saída (padrão falso).
  • timestamp: Sinalizador booleano que indica se devemos preceder a saída com carimbos de data / hora (padrão falso). Se a função for especificada, seu valor de retorno será usado em vez dos carimbos de data / hora.
imagreenplant
fonte
1
Incrível e simples ao mesmo tempo. Obrigado!
kolrie
7
Isso é ótimo. Normalmente, eu coloco isso em um arquivo dedicado para que possa facilmente obter meu logger configurado de qualquer arquivo, ou seja, coloco o código acima (opção 2) em um novo arquivo logger.js, seguido por module.exports = logger; então, a partir de qualquer arquivo, var logger = require ('./ logger.js') e posso fazer logger.info ('hello') de qualquer arquivo e obter a mesma configuração do Winston.
JHH
TypeError: (valor intermediário) não é uma função
Urasquirrel
80

As respostas acima não funcionaram para mim. Caso você esteja tentando adicionar um carimbo de data / hora aos seus logs usando a versão mais recente do Winston - 3.0.0-rc1, funcionou perfeitamente:

    const {transports, createLogger, format} = require('winston');

    const logger = createLogger({
        format: format.combine(
            format.timestamp(),
            format.json()
        ),
        transports: [
            new transports.Console(),
            new transports.File({filename: 'logs/error/error.log', level: 'error'}),
            new transports.File({filename: 'logs/activity/activity.log', level:'info'})
        ]
    });

Usei 'format.combine ()'. Como eu precisava de carimbo de data / hora em todos os meus transportes, adicionei a opção de formatação dentro do createLogger, em vez de dentro de cada transporte. Minha saída no console e no arquivo (activity.log) é a seguinte:

{"message":"Connected to mongodb","level":"info","timestamp":"2018-02-01T22:35:27.758Z"}
{"message":"Connected to mongodb","level":"info","timestamp":"2018-02-01T22:35:27.758Z"}

Podemos adicionar formatação a este carimbo de data / hora em 'format.combine ()' como de costume usando:

format.timestamp({format:'MM-YY-DD'})
Siva Kiran
fonte
14

Podemos fazer assim também

var winston = require('winston');
    const { createLogger, format, transports } = require('winston')
    var config = require('../configurations/envconfig.js');

    var loggerLevel = process.env.LOGGERLEVEL ||  config.get('LOGGERLEVEL');

    var logger = winston.createLogger({ format: format.combine(
            format.timestamp({
                format: 'YYYY-MM-DD HH:mm:ss'
            }),
            format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`+(info.splat!==undefined?`${info.splat}`:" "))
        ), 
        transports: [
            new (winston.transports.Console)({ level: loggerLevel }),
           ]
    });
    module.exports = logger;
Biswadev
fonte
Isso também funciona para logger.info('Message', someObject)? Eu configurei um formato personalizado usando combine e não consigo obter o someObjectincluído na mensagem de log.
Algo em
1
Consegui ser someObjectincluído usando a seguinte instrução printf ${info.timestamp} [${info.level.toUpperCase()}]: ${info.message} ${JSON.stringify(info)}. Inclui o nível, o carimbo de data / hora e a mensagem que acho que posso excluir.
Algo em
9

Você pode usar built-in util e sempre para conseguir o registo com timestap para o seu servidor nodejs. Ao iniciar um servidor, adicione a saída de registro como parte do parâmetro:

forever start -ao log/out.log server.js

E então você pode escrever util em seu server.js

server.js

var util = require('util');
util.log("something with timestamp");

A saída será semelhante a esta para o arquivo out.log:

out.log

15 Mar 15:09:28 - something with timestamp
KTU
fonte
1
Infelizmente, util.error()pula o registro de data e hora da saída.
Saran
4

Embora eu não saiba sobre o winston, esta é uma sugestão. Eu uso log4js para registrar e meus registros por padrão têm esta aparência

[2012-04-23 16:36:02.965] [INFO] Development - Node Application is running on port 8090
[2012-04-23 16:36:02.966] [FATAL] Development - Connection Terminated to  '127.0.0.1' '6379'

O desenvolvimento é o ambiente do meu processo de nó & [INFO | FATAL] é o nível de log

Manter perfis diferentes para registro é possível no log4js. Tenho perfis de Desenvolvimento e Produção. Também existem tipos de registradores como anexador de arquivo rolante, anexador de console, etc. Como um complemento, seus arquivos de log serão coloridos com base no nível de log [Trace, Info, Debug, Error, Fatal];)

log4js irá sobrescrever seu console.log É um parâmetro configurável agora em 0,5+

tâmil
fonte
Para sua informação: versões mais recentes de log4js-node (0.5+) não substituem console.log automaticamente.
Jeff Hiltz
@jeffhiltz Ya você está certo :) Agora é um parâmetro configurável
Tamil
2

Às vezes, o formato de carimbo de data / hora padrão pode não ser conveniente para você. Você pode substituí-lo por sua implementação.

Ao invés de

var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
  new (winston.transports.Console)({'timestamp':true})
]
});

você pode escrever

var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
  new (winston.transports.Console)({
     'timestamp': function() {
        return <write your custom formatted date here>;
     }
  })
]
});

Consulte https://github.com/winstonjs/winston#custom-log-format para os detalhes

walv
fonte
2

poderíamos usar o carimbo do console para adicionar carimbo de data / hora e nível de registro ao console existente: require('console-stamp')(console, '[yyyy-mm-dd HH:MM:ss.l]')

Consulte https://github.com/starak/node-console-stamp para obter os detalhes

khoi nguyen
fonte
0

Outra solução é agrupar o logger em um arquivo que exporta algumas funções como logger.info (), logger.error (), etc., então você apenas passa uma chave extra para ser enviada em cada log de mensagens.

loggerService.js

const logger = winston.createLogger({ ... })

function handleLog(message, level) {
  const logData = {
    timestamp: Date.now(),
    message,
  }

  return logger[level](logData)
}

function info(message) {
  handleLog(message, 'info')
}

function error(message) {
  handleLog(message, 'error')
}

function warn(message) {
  handleLog(message, 'warn')
}

module.exports = {
  info,
  error,
  warn
}

qualquer-arquivo.js

const logger = require('./services/loggerService')

logger.info('Hello World!')

seu-log.log

{"timestamp":"2019-08-21 06:42:27","message":"Hello World!","level":"info"}
Renan Coelho
fonte
0

Peguei a resposta de Biswadev e criei um objeto JSON stringificado. Dessa forma, se eu precisar processar os logs posteriormente, ele estará em um formato bem estruturado.

const winston = require('winston');
const { createLogger, format, transports } = require('winston');

const dotenv = require('dotenv');
dotenv.config();

var logger = createLogger({
    level: 'info',
    format: format.combine(
        format.timestamp({
            format: 'YYYY-MM-DD HH:mm:ss',
        }),
        format.printf((info) =>
            JSON.stringify({
                t: info.timestamp,
                l: info.level,
                m: info.message,
                s: info.splat !== undefined ? `${info.splat}` : '',
            }) + ','
        )
    ),
});

if (process.env.NODE_ENV !== 'PRODUCTION') {
    logger.add(new transports.Console({ format: winston.format.cli() }));

    // Turn these on to create logs as if it were production
    // logger.add(new transports.File({ filename: 'log/output/error.log', level: 'error' }));
    // logger.add(new transports.File({ filename: 'log/output/warn.log', level: 'warn' }));
    // logger.add(new transports.File({ filename: 'log/output/info.log', level: 'info' }));
} else {
    logger.add(new transports.File({ filename: 'log/output/error.log', level: 'error' }));
    logger.add(new transports.File({ filename: 'log/output/warn.log', level: 'warn' }));
    logger.add(new transports.File({ filename: 'log/output/info.log', level: 'info' }));
}

module.exports = {
    logger,
};

Uso:

app.listen(port, () => logger.info(`app is running on port ${port}`));

Resultado:

arquivo info.log:

{"t":"2020-08-06 08:02:05","l":"info","m":"app is running on port 3001","s":""},

Console:

info:    app is running on port 3001
Steve
fonte