如何使用 Node.js 库 Winston 为日志添加时间戳?

Posted

技术标签:

【中文标题】如何使用 Node.js 库 Winston 为日志添加时间戳?【英文标题】:How can I add timestamp to logs using Node.js library Winston? 【发布时间】:2012-05-03 12:33:30 【问题描述】:

我想为日志添加时间戳。实现这一目标的最佳方法是什么?

【问题讨论】:

这仍然过于宽泛,因为您无法从客户端计算机执行此操作。 【参考方案1】:

我自己也在处理同样的问题。我有两种方法可以做到这一点。

当您包含 Winston 时,它通常默认添加控制台传输。为了让时间戳在这种默认情况下正常工作,我需要:

    删除控制台传输并使用时间戳选项再次添加。 创建您自己的 Logger 对象,并将时间戳选项设置为 true。

第一个:

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

第二个更简洁的选择:

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

控制台传输的其他一些选项可以在here找到:

level:此传输应记录的消息级别(默认为“调试”)。 silent:指示是否抑制输出的布尔标志(默认为 false)。 colorize:布尔标志,指示我们是否应该对输出进行着色(默认为 false)。 timestamp:布尔标志,指示我们是否应该在输出前加上时间戳(默认为 false)。如果指定了函数,则将使用其返回值而不是时间戳。

【讨论】:

既神奇又简单。谢谢! 这很棒。我通常将其包装在一个专用文件中,以便我可以轻松地从任何文件中获取我配置的记录器,即,我将上面的代码(选项 2)放在一个新文件 logger.js 中,然后是 module.exports = logger;然后从任何文件中执行 var logger = require('./logger.js') ,然后可以从任何文件中执行 logger.info('hello') 并获得相同的 Winston 配置。 TypeError:(中间值)不是函数 这似乎不适用于当前版本的 Winston。请尝试其他答案之一。【参考方案2】:

以上答案对我不起作用。如果您尝试使用最新版本的 Winston - 3.0.0-rc1 为日志添加时间戳,这就像魅力:

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

我使用了“format.combine()”。由于我的所有传输都需要时间戳,因此我在 createLogger 中添加了格式化选项,而不是在每个传输中。我在控制台和文件(activity.log)上的输出如下:

"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"

我们可以像往常一样在 'format.combine()' 中为这个时间戳添加格式:

format.timestamp(format:'MM-YY-DD')

【讨论】:

请注意,format.timestamp 必须出现在 format.json 之前(如果您使用的是后者) @marvinIsSacul 不正确,我已经将它们交换了,但它仍然有效! mhhh 好吧@OtaconKiko 不知道为什么它不在我身边:想想【参考方案3】:

我们也可以这样做

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;

【讨论】:

这是否也适用于logger.info('Message', someObject)?我使用 combine 设置了自定义格式,但我似乎无法将 someObject 包含在日志消息中。 通过使用以下 printf 语句 $info.timestamp [$info.level.toUpperCase()]: $info.message $JSON.stringify(info),我能够获得 someObject。它包括我想我可以删除的级别、时间戳和消息。【参考方案4】:

您可以使用内置的util 和forever 为您的nodejs 服务器实现带时间戳的日志记录。 当您启动服务器时,将日志输出添加为参数的一部分:

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

然后你可以在你的 server.js 中编写 util

server.js

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

输出在 out.log 文件中看起来像这样:

out.log

15 Mar 15:09:28 - something with timestamp

【讨论】:

不幸的是,util.error() 跳过了输出时间戳。【参考方案5】:

虽然我不知道温斯顿,但这是一个建议。我使用log4js 进行日志记录,默认情况下我的日志如下所示

[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'

开发是我的节点进程的环境&[INFO|FATAL]是日志级别

在 log4js 中可以维护不同的日志配置文件。我有开发和生产资料。还有一些记录器类型,如滚动文件附加器、控制台附加器等。作为插件,您的日志文件将根据日志级别 [Trace、Info、Debug、Error、Fatal] 呈现出丰富多彩的颜色;)

log4js 会覆盖你的console.log它现在是0.5+中的一个可配置参数

【讨论】:

仅供参考:较新版本的 log4js-node (0.5+) 不会自动覆盖 console.log。 @jeffhiltz 是的,你是对的 :) 现在它是一个可配置的参数【参考方案6】:

我接受了 Biswadev 的回答并创建了一个字符串化的 JSON 对象。这样,如果我以后需要处理日志,它将采用结构良好的格式。

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,
;

用法:

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

输出:

info.log 文件:

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

控制台:

info:    app is running on port 3001

【讨论】:

喜欢...复制粘贴解决方案!!【参考方案7】:

我们可以使用 console-stamp 将时间戳和日志级别添加到现有控制台:require('console-stamp')(console, '[yyyy-mm-dd HH:MM:ss.l]')

详情请见https://github.com/starak/node-console-stamp

【讨论】:

除非它不向文件传输添加时间戳。【参考方案8】:

有时默认的时间戳格式对您来说并不方便。 你可以用你的实现覆盖它。

代替

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

你可以写

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

详情请见https://github.com/winstonjs/winston#custom-log-format

【讨论】:

【参考方案9】:

另一种解决方案是将记录器包装到一个文件中,该文件导出一些函数,如 logger.info()、logger.error() 等。然后您只需传递一个额外的密钥以在每个消息日志上发送。

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

whatever-file.js

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

logger.info('Hello World!')

你的日志.log

"timestamp":"2019-08-21 06:42:27","message":"Hello World!","level":"info"

【讨论】:

以上是关于如何使用 Node.js 库 Winston 为日志添加时间戳?的主要内容,如果未能解决你的问题,请参考以下文章

Winston/Node.js 如何只为特定环境添加传输?

Node.js - 记录 / 使用 morgan 和 winston

如何让 Winston 使用 Webpack?

温斯顿:如何更改时间戳格式

Winston 的多个日志文件?

NPM酷库:log4js JavaScript日志框架