在 winston 日志条目中添加模块名称

Posted

技术标签:

【中文标题】在 winston 日志条目中添加模块名称【英文标题】:Add module name in winston log entries 【发布时间】:2017-08-09 01:46:31 【问题描述】:

是否有可能保存当前模块名称以便在以后调用它们时自动打印在winston 日志条目中?

目前,当我想在日志中打印模块名称时,我必须手动添加:

var logHeader = 'mymodule'

log.info(logHeader + 'Hello')

例如,使用debug,您可以这样做(暂时忽略日志格式功能%s):

var debug = require('debug')('http')
  , name = 'My App'

debug('booting %s', name);

这将在日志前打印http 前缀:

http 启动我的应用程序

这可以在温斯顿完成吗?我在文档中进行了搜索,但找不到任何相关内容。

【问题讨论】:

【参考方案1】:

您可以使用 Winston 指定custom log format -

var moduleName = 'myModule';

var logger = new (winston.Logger)(
  transports: [
    new (winston.transports.Console)(
      formatter: function(options) 
        // Return string will be passed to logger. 
        return moduleName + ' - ' + (options.message ? options.message : '')
      
    )
  ]
);


logger.info('This is a log message');

这将打印 -

myModule - This is a log message

因此您的模块名称将附加到每个日志消息中。

【讨论】:

如果我理解正确,这将在所有日志消息中附加一个字符串。我问的是附加模块名称以记录来自该模块的消息。 是的,因此您需要为每个模块实例化一个唯一的记录器,类似于您为 debug 模块所做的方式。 为每个模块实例化一个记录器从来都不是一个好主意。而是第一个答案更好。【参考方案2】:

我找到了更好的方法。

我在winston 记录器上添加了一个附加层,在本例中是一个函数,它为需要记录器的每个模块保留模块名称。因此,当一个模块requires 我的新记录器时,它实际上使用模块名称调用导出的函数,在本例中为__filename

log.js

var winston = require('winston')

var winstonLogger = new (winston.Logger)(
    transports: [
        new (winston.transports.File) (
            filename: 'MyLogs.txt',
            handleExceptions: true,
            humanReadableUnhandledException: true,
            level: 'info',
            timestamp: true,
            json: false
        ),
        new (winston.transports.Console) (
            level: 'info',
            prettyPrint: true,
            colorize: true,
            timestamp: true
        )
    ]
)

module.exports = function(fileName)     
    var myLogger = 
        error: function(text) 
            winstonLogger.error(fileName + ': ' + text)
        ,
        info: function(text) 
            winstonLogger.info(fileName + ': ' + text)
        
    

    return myLogger

module1.js

var log = require('log')(__filename)

log.info('Info log example')

信息:C:\Users\user1\project\module1.js:信息日志示例

module2.js

var log = require('log')(__filename)

log.error('Error log example')

错误:C:\Users\user1\project\module2.js:错误日志示例

另外,这样一来,我提交文本日志的方式就无需更改任何地方; log.info('text') 和以前一样。

【讨论】:

谢谢。我考虑了这个解决方案,并试图找出是否有其他人这样做,您的解决方案比我想象的要好得多。【参考方案3】:

使用 winston v3.3.3,您可以使用 winston.format.label 和自定义 winston.format.printf 来做到这一点:

const winston = require('winston');

const logger = winston.createLogger(
  format: winston.format.combine(
    winston.format.label(label: 'mymodule'),
    winston.format.printf((label, message) => 
      return `$label: $message`;
    )
  ),
  transports: [
    new winston.transports.Console(),
  ],
);

logger.info('Hello, World!'); // prints "mymodule: Hello, World!"

【讨论】:

【参考方案4】:

这就是 Child Loggers 的用途。当被问到这个问题时,它们可能不可用,但为了将来参考,您可以创建主记录器实例,然后导出一个函数,该函数创建具有一些默认选项的子记录器。

// logging.js
const winston = require('winston') 

const logger = winston.createLogger(
  transports: [
    new winston.transports.Console(
      format: winston.format.printf(options => 
        // you can pass any custom variable in options by calling
        // logger.log(level: 'debug', message: 'hi', moduleName: 'my_module' )
        return `[$options.moduleName] $options.level: $options.message$`;
      )
    )
  ]
);

module.exports = function(name) 
  // set the default moduleName of the child
  return logger.child(moduleName: name);

然后在每个模块的顶部,使用以下命令导入子项:

// my_module.js
const logger = require('./logging.js')('my_module_name');

logger.error('computer says no');
// output:
// [my_module_name] error: computer says no

【讨论】:

您还可以导出其他记录器,然后单独导入。 export const databaseLogger = logger.child( label: 'database' );

以上是关于在 winston 日志条目中添加模块名称的主要内容,如果未能解决你的问题,请参考以下文章

运行单元测试时禁用winston日志记录?

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

如何更改 winston 日志格式?

找不到模块“温斯顿”

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

纱线在构建中找不到模块'logform'winston