如何刷新winston日志?

Posted

技术标签:

【中文标题】如何刷新winston日志?【英文标题】:How to flush winston logs? 【发布时间】:2013-09-17 06:41:54 【问题描述】:

我想在 之前 process.exit 刷新winston 记录器。

process.on('uncaughtException', function(err)
    logger.error('Fatal uncaught exception crashed cluster', err);
    logger.flush(function() // <-
        process.exit(1);
    );
);

有类似logger.flush 的东西吗?除了有人抱怨 winston 没有得到非常积极的维护之外,我找不到任何关于它的信息。

作为替代方案,是否有任何流行的(积极维护的)多传输日志框架提供刷新功能?

【问题讨论】:

Winston 也有这个问题 - 出现致命异常时文件记录器不会刷新到磁盘。 其他人已经为您的问题提供了解决方案。但您的实际问题的答案似乎是否定的:没有办法刷新 winston 记录器。 【参考方案1】:

Winston 实际上允许您传入一个回调,该回调会在所有传输都被记录后执行:

process.on('uncaughtException', function(err) 
    logger.log('error', 'Fatal uncaught exception crashed cluster', err, function(err, level, msg, meta) 
        process.exit(1);
    );
);

文档:https://github.com/flatiron/winston#events-and-callbacks-in-winston

【讨论】:

正确,这让我等待'fatal exception' 消息,如果我想刷新所有这些怎么办?也许正在记录其他一些消息,并且它使用的传输需要更长的时间才能完成。 没有什么是不刷新的。默认的 winston FileTransport 仅在第一次尝试打开底层文件时缓冲日志。 github.com/flatiron/winston/blob/master/lib/winston/transports/… 否则,如果数据没有立即写入底层文件描述符,我们将等待“drain”事件:github.com/flatiron/winston/blob/master/lib/winston/transports/… @indexzero 说我记录了一个错误,该错误通过 HTTP 传输或存储在数据库中,然后我记录了一条调试消息,该消息只发送到控制台,然后等待该消息,然后出口。错误消息是否总是被记录? @indexzero 如果我设置了控制台记录器和文件记录器,记录一些文本,然后使用 ctrl+c 退出,控制台记录器会显示所有记录的文本,而文件记录器只会显示其中的一部分。 真的不清楚 FileTransport 是否缓冲它的写入,遵循这条评论线索。缓冲是否只委托给文件系统?【参考方案2】:

Winston 有更好的方法来处理这种异常。

var logger = new (winston.Logger)(
    transports: [
      new winston.transports.File( filename: 'path/to/all-logs.log' )
    ],
    handleExceptions: true,
    exceptionHandlers: [
      new winston.transports.File( filename: 'path/to/exceptions.log' )
    ]
  );

【讨论】:

你还没有解释这是如何回答这个问题的。【参考方案3】:

像 Thomas Heymann 建议的那样在日志回调中调用 process.exit 并不能确保日志确实被刷新,尤其是在使用 File-transport 时。

我会让记录器在刷新日志后调用process.exit,而不是直接调用 process.exit:

logger.js:

var winston = require('winston');

winston.loggers.add('my-logger', 
    console: 
        level: 'debug',
        colorize: true,
        timestamp: true,
        handleExceptions: true
    ,
    file: 
        level: 'info',
        colorize: false,
        timestamp: true,
        filename: file,
        handleExceptions: true
    
);

var logger = winston.loggers.get('my-logger');


/* ******* *
 * EXPORTS
 * ******* */

exports.exitAfterFlush = function(code) 
    logger.transports.file.on('flush', function() 
        process.exit(code);
    );
;

exports.info = function() 
    logger.info.apply(this, arguments);
;

exports.warn = function() 
    logger.info.apply(this, arguments);
;

exports.error = function() 
    logger.info.apply(this, arguments);
;

在你的代码中:

var logger = require('./logger.js');
logger.exitAfterFlush(0);
info('Done!');

在 NodeJS v4.1.2 和 winston 1.1.0 上测试

【讨论】:

我认为这已经停止在 NodeJS 10.x 和 winston 3.2.1 上运行【参考方案4】:

不幸的是,Winston 有时会在传输有机会刷新之前调用日志记录回调,因此接受的答案仍然可能导致未保存的日志消息(尤其是在事件循环的第一轮)。在winston-log-and-exit 包/补丁中实现了更好的解决方案。

【讨论】:

【参考方案5】:

这可能对某人有所帮助。 logger 是 winston.createLogger 的一个实例,它定义了两个传输(控制台和文件)。退出代码反映在 shell 中。

const logger = require('../library/log');

function exitAfterFlush() 
    logger.on('finish', function () 
        logger.end();
    );
;
  
process.on('exit', (code) => 
    console.log(`About to exit with code: $code`);
);

logger.info(`Started with PID:$process.pid`);
logger.error(`*****`);
process.exitCode = 11;
exitAfterFlush();

【讨论】:

以上是关于如何刷新winston日志?的主要内容,如果未能解决你的问题,请参考以下文章

除第一天外,如何使用 Winston 每天轮换日志

如何在 Winston/Node.js 中设置日志级别

如何使用winston在子目录而不是根目录中设置日志?

如何将 Winston 限制为每个日志文件只有 1 个文件描述符

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

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