javascript - Pino 格式化程序和序列化程序之间的差异

标签 javascript pinojs

我试图更好地理解如何在不同情况下正确使用 Pino JS 添加动态上下文,并且我一直在查看文档,并发现了一些我需要澄清的事情。

pino 记录器可以配置两者FormattterSerializer,并且描述相似,但我想它们有每个的特定用途和意图。这是我在文档中找到的内容:

formatters (Object)

An object containing functions for formatting the shape of the log lines. These functions should return a JSONifiable object and should never throw. These functions allow for full customization of the resulting log lines. For example, they can be used to change the level key name or to enrich the default metadata.

serializers (Object)

Default: {err: pino.stdSerializers.err}

An object containing functions for custom serialization of objects. These functions should return an JSONifiable object and they should never throw. When logging an object, each top-level property matching the exact key of a serializer will be serialized using the defined serializer.

The serializers are applied when a property in the logged object matches a property in the serializers. The only exception is the err serializer as it is also applied in case the object is an instance of Error, e.g. logger.info(new Error('kaboom')). See errorKey option to change err namespace.

我不清楚为什么我会使用其中一个而不是另一个,因为它们在功能上似乎非常相似。格式化程序确实提到“默认元数据”作为示例,但这还不足以澄清...任何人都有一些见解,或者知道库如何不同地使用它们,有什么区别?

最佳答案

当记录的对象上存在要记录的数据的子集时,序列化程序仅修改该数据。如果特定日志属性与序列化程序键匹配,则序列化程序将修改该数据子集。如果不是,则跳过。 格式化程序始终会被处理,并处理整个日志数据对象、绑定(bind)对象或级别对象(如文档中所定义)。

虽然您可以通过修改日志对象来完成格式化程序中序列化程序的工作,但序列化程序允许更细粒度的控制和逻辑分离,并且仅在存在要修改的数据时运行。这使得序列化器成为一种更灵活的方法,可以使用小型集中函数而不是单个数据处理器来修改日志数据。随着应用程序的复杂性规模扩大,这一点的重要性也随之增加。

这是我为了突出差异而编写的一个简单示例。

const pino = require("pino")

let loggerDefault = pino({}, "./log.log")

let loggerFormatter = pino({
  formatters: {
    log (data) {
      console.log("formatters ", data)
      return {
        ...data,
        timeString: new Date().toISOString(),
        timeData: {
          ms: Date.now(),
          sec: Date.now() / 1000
        }
      }
    }
  },
}, "./log.log")

let loggerSerializer = pino({
  serializers: {
    timeData (data) {
      console.log("serializer ", data)
      return {
        ms: Date.now(),
        sec: Date.now() / 1000
      }
    }
  }
}, "./log.log")

let logNoTimeData = {
  msg: "Log With No Time Data",
  timeString: "-",
  id: "myId",
}

let logWithTimeData = {
  msg: "Log With Time Data",
  timeString: "-",
  timeData: {
    ms: 0,
    sec: 0
  },
  id: "myId",
}

loggerDefault.info(logNoTimeData)
loggerFormatter.info(logNoTimeData)
loggerSerializer.info(logNoTimeData)

loggerDefault.info(logWithTimeData)
loggerFormatter.info(logWithTimeData)
loggerSerializer.info(logWithTimeData)

在节点中运行此代码,并注意使用格式化程序进行日志记录如何修改与序列化程序相同的数据,但每次都会运行,但序列化程序仅运行第二次。您可以看到控制台输出:

formatters  { msg: 'Log With No Time Data', timeString: '-', id: 'myId' }
formatters  {
  msg: 'Log With Time Data',
  timeString: '-',
  timeData: { ms: 0, sec: 0 },
  id: 'myId'
}
serializer  { ms: 0, sec: 0 }

显示格式化程序在两个对象上运行,但序列化程序仅运行一次。将其与记录的输出进行比较(带注释):

default:
{"level":30,"time":1704959633972,"msg":"Log With No Time Data","timeString":"-","id":"myId"}
with formatter:
{"level":30,"time":1704959633972,"msg":"Log With No Time Data","timeString":"2024-01-11T07:53:53.976Z","id":"myId","modifiedBy":"formatter","timeData":{"ms":1704959633976,"sec":1704959633.976}}
with serializer:
{"level":30,"time":1704959633977,"msg":"Log With No Time Data","timeString":"-","id":"myId"}

default:
{"level":30,"time":1704959633977,"msg":"Log With Time Data","timeString":"-","timeData":{"ms":0,"sec":0},"id":"myId"}
with formatter:
{"level":30,"time":1704959633977,"msg":"Log With Time Data","timeString":"2024-01-11T07:53:53.977Z","timeData":{"ms":1704959633977,"sec":1704959633.977},"id":"myId","modifiedBy":"formatter"}
with serializer:
{"level":30,"time":1704959633977,"msg":"Log With Time Data","timeString":"-","timeData":{"modifiedBy":"serializer","ms":1704959633977,"sec":1704959633.977},"id":"myId"}

总结一下:

当您想要修改每个日志对象时,请使用格式化程序。 当您想要修改特定日志数据(如果存在)时,请使用序列化程序。

关于javascript - Pino 格式化程序和序列化程序之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77419510/

相关文章:

javascript - Foreach 循环仅从数据库中回显一行

javascript - Json 循环不运行

javascript - Facebook 应用程序和动画加载 Gif

javascript - 使用新的 JS SDK 的 Facebook Connect 是获得 "App on Facebook"的方法吗?

node.js - 我如何使用 pino 作为记录器?

javascript - 如何在 pino.js 记录器中旋转日志文件

javascript - JavaScript 中的 .replace 方法和重复的字符