【问题标题】:How to log JavaScript objects and arrays in winston as console.log does?如何像 console.log 一样在 winston 中记录 JavaScript 对象和数组?
【发布时间】:2016-01-14 12:39:35
【问题描述】:

我正在查看顶级节点日志记录系统:npmloglog4jsbunyanwinston,并决定使用 winston 来获得最多的 npm 每月下载量。

我要设置的是自定义记录器,我将能够使用logger.debug(...) 在开发环境中使用它,它不会在生产环境中记录任何内容。这对我有帮助,所以当我在开发环境中时,我不需要写任何东西,因为我会看到所有的输出。

这就是我现在拥有的:

var level = 'debug';
if (process.env.NODE_ENV !== 'development'){
  level = 'production'; // this will never be logged!
}

var logger = new winston.Logger({
  transports: [
    // some other loggings
    new winston.transports.Console({
      name: 'debug-console',
      level: level,
      prettyPrint: true,
      handleExceptions: true,
      json: false,
      colorize: true
    })

  ],
  exitOnError: false // don't crush no error
});

当我尝试记录 JavaScript Object 或 Javascript Array 时出现问题。对于Object,我需要使用toJSON(),对于Array,我首先需要JSON.stringify(),然后是JSON.parse()

一直写这些方法并不好,只是为了记录我想要的东西。此外,它甚至对资源都不友好,因为这些格式化方法需要在 logger.debug() 意识到它在生产中并且它不应该首先记录它之前执行(基本上,它是在函数调用之前评估参数)。我只是喜欢老式的 console.log() 记录 JavaScript 对象和数组。

现在,当我写这个问题时,我发现有一种方法可以为每个winston transports 对象描述custom format。是这样做的方式,还是有其他的方式?

【问题讨论】:

    标签: javascript arrays node.js logging winston


    【解决方案1】:

    尝试对对象使用 util.inspect。它也正确处理循环引用。 @radon-rosborough 已经给出了这个答案,但我想添加一个例子。请看下文

    const customTransports = [
        new winston.transports.Console({
            format: combine(
                timestamp({
                    format: 'DD-MMM-YYYY HH:MM:SS'
                }),
                label({
                    label: file
                }),
                prettyPrint(),
                format.splat(),
                simple(),
                printf( (msg)=> {
                    let message = msg.message;
    
                    return colorize().colorize(msg.level, `${ msg.level } :  ${msg.timestamp} :  ${ msg.label } : \n`) + `${ util.inspect(message,{
                        depth: 2,
                        compact:true,
                        colors: true,
                    } )}`;
                })
            )
        })
    ] 
    

    【讨论】:

      【解决方案2】:

      在 Winston > 3 你可以使用

      logger.log('%o', { lol: 123 }')
      

      无论如何... 无法接受我必须始终使用 %o 并提出了这个简单的解决方案:

      const prettyJson = format.printf(info => {
        if (info.message.constructor === Object) {
          info.message = JSON.stringify(info.message, null, 4)
        }
        return `${info.level}: ${info.message}`
      })
      
      const logger = createLogger({
        level: 'info',
        format: format.combine(
          format.colorize(),
          format.prettyPrint(),
          format.splat(),
          format.simple(),
          prettyJson,
        ),
        transports: [
          new transports.Console({})
        ],
      })
      

      所以这个记录器....

        logger.info({ hi: 123 })
      

      ...在控制台中转换为 this

      info: {
          "hi": 123
      }
      

      【讨论】:

      • 很遗憾,您的答案不适用于:log.silly(`Ok: ${{ lol: 123 }}`); :(
      • @K-ToxicityinSOisgrowth。你找到解决办法了吗?
      • @FabZbi 我创建了自己的日志库:github.com/langurama/log
      【解决方案3】:

      而不是做

      prettyPrint: function ( object ){
          return JSON.stringify(object)
      }
      

      最好使用utils-deep-clone

      // initialize package on the top
      const { toJSON } = require('utils-deep-clone')
      
      
      // and now in your `prettyPrint` parameter do this
      prettyPrint: function ( object ){
          return toJSON(object)
      }
      
      

      如果您选择JSON.stringify,您将无法打印错误

      console.log(JSON.stringify(new Error('some error')))
      // output will '{}'
      

      【讨论】:

        【解决方案4】:

        正如 Leo 在他的 answer 中已经指出的那样,Winston 使用了 util.format 提供的 String Interpolation

        const winston = require("winston");
        常量记录器=新的winston.Logger({
          运输:[
            // 其他一些日志
            新的winston.transsports.Console({
              名称:“调试控制台”,
              级别:process.env.LOGLEVEL || “信息”,
              漂亮打印:是的,
              处理异常:真,
              json: 假的,
              着色:真
            })
          ],
          exitOnError: false // 不粉碎没有错误
        });
        
        常量嵌套对象 = {
          富:{
            酒吧: {
              baz:“示例”
            }
          }
        };
        
        const myString = "foo";
        
        logger.log("info", "我的嵌套对象:%j。我的字符串:%s", nestedObj, myString);
        

        当调用logger.log 时,您可以定义将被适当替换的占位符。 %j 将替换为 JSON.stringify(nestedObj) 的等效项

        【讨论】:

          【解决方案5】:
          logger.log("info", "Starting up with config %j", config);
          

          Winstons 使用内置的 utils.format 库。 https://nodejs.org/dist/latest/docs/api/util.html#util_util_format_format_args

          【讨论】:

          • 提供一些解释来解释为什么它会这样工作或 OP 做错了什么。只是这样的代码粘贴会被标记。
          • 我在这里看到的最佳解决方案。使用现有的记录器 api 并漂亮地打印所有内容。
          • 提醒一下,您需要启用 format.splat()。否则它不起作用。
          【解决方案6】:

          使用内置的 Node.js 函数 util.format 将对象转换为字符串,方法与 console.log 相同。

          【讨论】:

            【解决方案7】:

            尝试将 prettyPrint 参数更改为

            prettyPrint: function ( object ){
                return JSON.stringify(object);
            }
            

            【讨论】:

            • 有趣的事实,你也可以这样做prettyPrint: JSON.stringify
            • 如果object 有循环引用会不会失败?
            • 是的,它绝对会在循环 JSON 中失败。我添加了一个答案,通过使用 util.format 函数解决了问题。
            【解决方案8】:

            我的建议是在 winston 之上编写您自己的抽象,该抽象具有打印对象以进行调试的便捷方法。

            您也可以查看此回复以了解如何开发该方法。

            https://stackoverflow.com/a/12620543/2211743

            【讨论】:

              猜你喜欢
              • 2013-04-06
              • 2019-09-29
              • 2013-01-28
              • 1970-01-01
              • 1970-01-01
              • 2015-11-24
              • 1970-01-01
              • 1970-01-01
              • 2021-12-13
              相关资源
              最近更新 更多