如何像 console.log 一样在 winston 中记录 JavaScript 对象和数组?

Posted

技术标签:

【中文标题】如何像 console.log 一样在 winston 中记录 JavaScript 对象和数组?【英文标题】:How to log JavaScript objects and arrays in winston as console.log does? 【发布时间】: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。是这样做的方式,还是有其他的方式?

【问题讨论】:

【参考方案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://***.com/a/12620543/2211743

【讨论】:

以上是关于如何像 console.log 一样在 winston 中记录 JavaScript 对象和数组?的主要内容,如果未能解决你的问题,请参考以下文章

在 svelte 中,如何在变量更改时使用 `console.log('yes')`?

为啥“return”与“console.log()”不一样[重复]

ts常用数据类型

复制或合并map

js 属性getset

关于console.log