【问题标题】:How to make a custom json formatter for winston@3 logger?如何为 winston@3 记录器制作自定义 json 格式化程序?
【发布时间】:2018-12-29 11:21:15
【问题描述】:

我正在尝试为 winston v3 制作自定义 json 格式化程序。

这是一个带有演示的文件:

const { createLogger, format, transports } = require("winston")
const { combine, timestamp, prettyPrint } = format

const logger = createLogger({
  format: combine(timestamp(), prettyPrint())
})

logger.add(new transports.Console())

logger.info("test message", { data: { a: 1, b: [1, 2, 3, 4], d: new Date() } })

try {
  throw new Error("I'm an error!")
} catch (err) {
  logger.error(err)
}

打印出来:

{ data: { a: 1, b: [ 1, 2, 3, 4 ], d: 2018-07-21T08:59:27.958Z },
  level: 'info',
  message: 'test message',
  timestamp: '2018-07-21T08:59:27.959Z',
  [Symbol(level)]: 'info',
  [Symbol(splat)]:
   [ { data: { a: 1, b: [ 1, 2, 3, 4 ], d: 2018-07-21T08:59:27.958Z } } ] }
{ Error: I'm an error!
    at Object.<anonymous> (/Users/max7z/projects/test/t32__test__winston__pretty-print_symbol/index.js:13:9)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:266:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3)
  level: 'error',
  timestamp: '2018-07-21T08:59:27.962Z',
  [Symbol(level)]: 'error' }

我希望得到几乎相同的输出,但没有某些字段:[Symbol(level)]、[Symbol(splat)]。

是否可以从 prettyPrint 格式化程序中删除 [Symbol] 字段?

或者我怎样才能制作我自己的自定义 json 格式化程序,并带有像 prettyPrint 一样的错误堆栈跟踪?

【问题讨论】:

    标签: node.js logging winston


    【解决方案1】:

    查看how to create custom formats。 然后以prettyPrintsource code 为基础,根据您的需要创建修改版本。

    Winstons 使用 triple-beam 来定义各种 Symbols,因此您也可以使用该软件包来删除它们。

    【讨论】:

    • 您能否举例说明如何从prettyPrint 输出中删除[Symbol] 字段?我已经阅读了您的链接,但我仍然不知道该怎么做。
    • 您删除这些字段就像使用 delete 的任何其他字段一样。
    • 我同意 @max7z 的文档非常混乱。我没有使用 splat,但我在一些 console.debug 调用中一直看到 splat,而且我似乎无法以我想要的格式将字段添加到输出中。作为最常用的记录器,这件事令人困惑:(
    【解决方案2】:

    参考Winston format

    require('winston-daily-rotate-file');
    const { createLogger, format, transports } = require('winston');
    const { combine, timestamp, label, printf, prettyPrint, splat, simple } = format;
    
    
    const myFormat = printf(info => {
        // you can get splat attribue here as info[Symbol.for("splat")]
        // if you custome splat please rem splat() into createLogger()
        return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`;
    });
    
    const logger = createLogger({
      format: combine(
        label({ label: 'keaz.co' }),
        timestamp(),
        splat(),
        myFormat
      ),
      transports: [
          new transports.Console(),
          new transports.File({
            filename: "info.log",
            level: 'info'
          }),
          new transports.File({
            filename: "error.log",
            level: 'error'
          })
        ]
    })
    
    logger.info("test message %o", { data: { a: 1, b: [1, 2, 3, 4], d: new Date() } });
    
    module.exports = logger;
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,并在here 中找到了解决方案。我正在使用 Node.js 和 Socket.IO,我在 Socket.IO 中使用过记录器。举个例子:

      Node.js

      io.on('connection',function(socket){
        var date = new Date();
        socket.on('',function(data){
          logger.log('info', {IP: ip, Date: date, Path: '', Data: data.req_data});
      

      Winston.js(记录器)

      const app_root = require('app-root-path');
      const { createLogger, format, transports } = require('winston');
      
      
      var logger = createLogger({
        level: 'info',
        format: format.combine(
          format(function(info, opts){
              console.log(`[${info.IP}]-[${info.Date}]-[${info.Path}]-[${info.Data}]`);
              return info;
          })(),
          format.json()
      
        ),
      
        transports: [
          new transports.File({filename: `${app_root}/logs/info.log`})
        ]
      });
      
      module.exports = logger;
      

      据我所知,我们可以根据需要使用随机变量(ip、日期、鸟、球等)。我认为经过一点安排后,您也可以将其用于错误。祝你好运!

      【讨论】:

        【解决方案4】:

        我使用 winston v3.3.3 测试了示例,并添加了一个自定义格式化程序来对 data 对象进行字符串化:

        const winston = require('winston');
        
        const myFormatter = winston.format((info) => {
          const {message} = info;
        
          if (info.data) {
            info.message = `${message} ${JSON.stringify(info.data)}`;
            delete info.data; // We added `data` to the message so we can delete it
          }
          
          return info;
        })();
        
        const logger = winston.createLogger({
          format: winston.format.combine(
            winston.format.timestamp({
              format: 'YYYY-MM-DD HH:mm:ss',
            }),
            myFormatter,
            winston.format.simple(),
          ),
          transports: [
            new winston.transports.Console(),
          ],
        });
        

        我运行了问题中的命令并得到了所需的输出。

        执行:

        logger.info('test message', {data: {a: 1, b: [1, 2, 3, 4], d: new Date()}});
        
        try {
          throw new Error(`I'm an error!`);
        } catch (err) {
          logger.error(err);
        }
        

        输出:

        信息:测试消息 {"a":1,"b":[1,2,3,4],"d":"2020-09-09T09:41:22.525Z"} {"timestamp": "2020-09-09 11:41:22"}

        错误:我是个错误! {"时间戳":"2020-09-09 11:41:22"}

        当使用winston.format.prettyPrint() 而不是winston.format.simple() 时,也可以使用制表符和换行符打印 JSON 对象。

        【讨论】:

          猜你喜欢
          • 2017-03-24
          • 2017-03-23
          • 2019-02-08
          • 2018-10-29
          • 1970-01-01
          • 1970-01-01
          • 2017-11-09
          • 2017-02-14
          • 2017-08-03
          相关资源
          最近更新 更多