Fastify 日志

2020-02-06 15:38 更新

日志

日志默認(rèn)關(guān)閉,你可以在創(chuàng)建 Fastify 實例時傳入 { logger: true } 或者 { logger: { level: 'info' } } 選項來開啟它。要注意的是,日志無法在運(yùn)行時啟用。為此,我們使用了 abstract-logging。

Fastify 專注于性能,因此使用了 pino 作為日志工具。默認(rèn)的日志級別為 'info'。

開啟日志相當(dāng)簡單:

const fastify = require('fastify')({
  logger: true
})

fastify.get('/', options, function (request, reply) {
  request.log.info('Some info about the current request')
  reply.send({ hello: 'world' })
})

如果你想為日志配置選項,直接將選項傳遞給 Fastify 實例就可以了。 你可以在 Pino 的文檔中找到全部選項。如果你想指定文件地址,可以:

const fastify = require('fastify')({
  logger: {
    level: 'info',
    file: '/path/to/file' // 將調(diào)用 pino.destination()
  }
})
fastify.get('/', options, function (request, reply) {
  request.log.info('Some info about the current request')
  reply.send({ hello: 'world' })
})

如果需要向 Pino 傳送自定義流 (stream),僅需在 logger 對象中添加 stream 一項即可。

const split = require('split2')
const stream = split(JSON.parse)

const fastify = require('fastify')({
  logger: {
    level: 'info',
    stream: stream
  }
})

默認(rèn)情況下,F(xiàn)astify 給每個請求分配了一個 id 以便跟蹤。如果頭部存在 "request-id" 即使用該值,否則會生成一個新的增量 id。你可以通過 Fastify 工廠函數(shù)的 requestIdHeader 與 genReqId 來進(jìn)行自定義。

默認(rèn)的日志工具使用標(biāo)準(zhǔn)的序列化工具,生成包括 req、res 與 err 屬性在內(nèi)的序列化對象??梢越栌芍付ㄗ远x的序列化工具來改變這一行為。

const fastify = require('fastify')({
  logger: {
    serializers: {
      req: function (req) {
        return { url: req.url }
      }
    }
  }
})

響應(yīng)的 payload 與 header 可以按如下方式記錄日志 (即便這是不推薦的做法):

const fastify = require('fastify')({
  logger: {
    prettyPrint: true,
    serializers: {
      res(res) {
        // 默認(rèn)
        return {
          statusCode: res.statusCode
        }
      },
      req(req) {
        return {
          method: req.method,
          url: req.url,
          path: req.path,
          parameters: req.parameters,
          // 記錄 header 可能會觸犯隱私法律,例如 GDPR (譯注:General Data Protection Regulation)。你應(yīng)該用 "redact" 選項來移除敏感的字段。此外,驗證數(shù)據(jù)也可能在日志中泄露。
          headers: req.headers
        };
      }
    }
  }
});

注:在 req 方法中,body 無法被序列化。因為請求是在創(chuàng)建子日志時就序列化了,而此時 body 尚未被解析。

以下是記錄 req.body 的一個方法

app.addHook('preHandler', function (req, reply, done) {
  if (req.body) {
    req.log.info({ body: req.body }, 'parsed body')
  }
  done()
})

Pino 之外的日志工具會忽略該選項。

你還可以提供自定義的日志實例。直接將實例傳入,取代配置選項就能實現(xiàn)該功能。提供的示例必須實現(xiàn) Pino 的接口,換句話說,便是擁有下列方法: info、error、debug、fatal、warn、trace、child。

示例:

const log = require('pino')({ level: 'info' })
const fastify = require('fastify')({ logger: log })

log.info('does not have request information')

fastify.get('/', function (request, reply) {
  request.log.info('includes request information, but is the same logger instance as `log`')
  reply.send({ hello: 'world' })
})

當(dāng)前請求的日志實例在生命周期的各部分均可使用。

日志修訂

Pino 支持低開銷的日志修訂,以隱藏特定內(nèi)容。 舉例來說,出于安全方面的考慮,我們也許想在 HTTP header 的日志中隱藏 Authorization 這一個 header:

const fastify = Fastify({
  logger: {
    stream: stream,
    redact: ['req.headers.authorization'],
    level: 'info',
    serializers: {
      req (req) {
        return {
          method: req.method,
          url: req.url,
          headers: req.headers,
          hostname: req.hostname,
          remoteAddress: req.ip,
          remotePort: req.connection.remotePort
        }
      }
    }
  }
})

更多信息請看 https://getpino.io/#/docs/redaction。



以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號