首页 Pino 速查表
10.3.1 2026-02-09 pinojs/pino 打开 Zread
340px

🚀 基础创建与级别 >>>

先确定实例创建、日志级别和对象日志写法,再扩展 transport 与上下文。
import pino from 'pino'

const logger = pino({
  level: process.env.LOG_LEVEL ?? 'info'
})

logger.info('service started')
logger.error({ err: new Error('boom') }, 'request failed')
logger.level = 'debug'

if (logger.isLevelEnabled('trace')) {
  logger.trace({ feature: 'search' }, 'trace message')
}
const auditLogger = pino({
  customLevels: {
    audit: 35,
    security: 45
  }
})

auditLogger.audit({ actor: 'admin' }, 'permission changed')

🧩 字段格式化与序列化 >>>

用 `formatters`、`serializers`、字段键名配置对接日志平台字段约定。
const logger = pino({
  messageKey: 'message',
  errorKey: 'error',
  nestedKey: 'payload',
  formatters: {
    level(label, number) {
      return { level: number, severity: label }
    },
    bindings(bindings) {
      return { pid: bindings.pid, host: bindings.hostname }
    }
  },
  serializers: {
    err: pino.stdSerializers.err
  }
})

🧵 Child Logger 与上下文 >>>

通过 `child()` 绑定请求、模块、租户等上下文,避免每次手写重复字段。
const rootLogger = pino({ level: 'info' })
const requestLogger = rootLogger.child({
  requestId: 'req-42',
  module: 'billing'
})

requestLogger.info('request accepted')
console.log(requestLogger.bindings())
requestLogger.setBindings({
  userId: 'u-1001'
})

requestLogger.warn({ retryable: true }, 'upstream timeout')

🔒 Redaction 脱敏 >>>

把口令、令牌、卡号等字段在输出前统一遮罩或直接移除。
const logger = pino({
  redact: {
    paths: [
      'req.headers.authorization',
      'user.password',
      'payment.card.cvv',
      'items[*].secret'
    ],
    censor: '[REDACTED]'
  }
})
const logger = pino({
  redact: {
    paths: ['token', 'profile.ssn'],
    remove: true
  }
})

🚚 Transport 与输出管道 >>>

生产环境优先用 `pino.transport()` 把格式化、分流、落盘放到 worker 线程。
const transport = pino.transport({
  targets: [
    {
      level: 'info',
      target: 'pino/file',
      options: { destination: './logs/app.log', mkdir: true }
    },
    {
      level: 'error',
      target: 'pino/file',
      options: { destination: './logs/error.log', mkdir: true }
    }
  ]
})

const logger = pino(transport)
const transport = pino.transport({
  pipeline: [
    { target: 'pino-pretty', options: { colorize: true } }
  ]
})

const logger = pino({ level: 'debug' }, transport)

💾 Destination 与 flush >>>

直接写文件时用 `destination()`,需要确保进程退出前适时 `flush()`。
const destination = pino.destination({
  dest: './logs/runtime.log',
  minLength: 4096,
  sync: false
})

const logger = pino(destination)
logger.info('queued')
logger.flush()

🌐 Browser 与前端转发 >>>

浏览器模式适合统一前后端日志接口,或将 warn/error 转发到远端采集端。
const logger = pino({
  browser: {
    asObject: true,
    transmit: {
      level: 'warn',
      send(level, logEvent) {
        navigator.sendBeacon('/log', JSON.stringify({ level, logEvent }))
      }
    }
  }
})

🌍 Web 框架接入 >>>

与 Fastify、`pino-http` 配合时,重点是请求日志、上下文继承和敏感字段脱敏。
import Fastify from 'fastify'

const app = Fastify({
  logger: {
    level: 'info',
    redact: ['req.headers.authorization']
  }
})

app.get('/health', async (request) => {
  request.log.info('health check')
  return { ok: true }
})
import express from 'express'
import pinoHttp from 'pino-http'

const app = express()
app.use(pinoHttp())

app.get('/', (req, res) => {
  req.log.info({ route: '/' }, 'handled')
  res.end('ok')
})

🧪 Diagnostics 与排障 >>>

诊断通道可以观测内部序列化阶段,适合调试格式化或性能问题。
import diagnosticsChannel from 'node:diagnostics_channel'

const start = diagnosticsChannel.channel('tracing:pino_asJson:start')
const end = diagnosticsChannel.channel('tracing:pino_asJson:end')

start.subscribe((message) => {
  console.log('serialize start', message.arguments)
})

end.subscribe((message) => {
  console.log('serialize end', message.result)
})

⚠️ 生产使用要点

JSON 原始日志保留给机器消费,开发态再接 `pino-pretty` 或专用 transport 做展示。
  • JSON.stringify()
  • requestId userId service
  • pino-pretty
  • 退出前如果使用异步 destination 或 transport,要确认日志已 flush。