如何在Next.js中为Pino Logger配置多管道分级别日志
在Next.js中使用Pino Logger按级别分文件写入并转换日志
你的代码核心问题是重复定义了transport.pipeline属性,JavaScript对象中重复的键会被后续值覆盖,因此只有最后一个error相关的管道生效,导致info.log无内容;同时全局日志级别设为info,所有info及以上级别的日志都会进入这个唯一管道,而pino/file的level配置不会自动过滤日志,所以error.log会同时包含info和error级别的内容。
以下是两种可行的解决方案:
方案一:使用@pinojs/multi-stream实现分流与转换
这种方式灵活性更高,适合需要自定义转换逻辑的场景:
- 安装依赖:
npm install @pinojs/multi-stream pino
- 配置Logger(示例文件:
logger.js):
const pino = require('pino'); const { multistream } = require('@pinojs/multi-stream'); const fs = require('fs'); const { Transform } = require('stream'); // Info级别日志转换流 const infoTransform = new Transform({ objectMode: true, transform(chunk, encoding, callback) { // 编写info日志转换逻辑,比如添加处理时间字段 chunk.processedAt = new Date().toISOString(); callback(null, chunk); } }); // Error级别日志转换流 const errorTransform = new Transform({ objectMode: true, transform(chunk, encoding, callback) { // 编写error日志转换逻辑,比如补充错误上下文 chunk.errorContext = chunk.stack || '无堆栈信息'; callback(null, chunk); } }); // 创建文件写入流 const infoFileStream = fs.createWriteStream('./logs/info.log', { flags: 'a' }); const errorFileStream = fs.createWriteStream('./logs/error.log', { flags: 'a' }); // 组合转换流与文件流 const infoPipeline = infoTransform.pipe(pino.destination({ dest: infoFileStream, sync: false })); const errorPipeline = errorTransform.pipe(pino.destination({ dest: errorFileStream, sync: false })); module.exports = pino({ level: 'info' // 全局捕获info及以上级别日志 }, multistream([ // 仅将info级别日志发送到info管道 { stream: infoPipeline, filter: (log) => log.level === pino.levels.values.info }, // 将error及以上级别日志发送到error管道 { stream: errorPipeline, level: 'error' } ]));
方案二:使用Pino v8+的多Transport配置
如果你的Pino版本是v8及以上,可以直接配置多个transport管道,每个管道对应一个级别和转换逻辑:
const pino = require('pino'); module.exports = pino({ level: 'info' }, { transports: [ // Info级别日志管道 { pipeline: [ { target: './info-transform-transport.mjs' }, // 自定义转换transport { target: 'pino/file', options: { destination: './logs/info.log' }, // 过滤仅保留info级别日志 filter: (log) => log.level === pino.levels.values.info } ] }, // Error级别日志管道 { pipeline: [ { target: './error-transform-transport.mjs' }, // 自定义转换transport { target: 'pino/file', options: { destination: './logs/error.log' }, level: 'error' } ] } ] });
自定义转换Transport示例(info-transform-transport.mjs)
确保自定义transport符合Pino要求,导出一个返回转换流的函数:
import { Transform } from 'stream'; export default function (options) { return new Transform({ objectMode: true, transform(chunk, enc, cb) { // 编写你的转换逻辑 chunk.transformedBy = 'info-transform'; cb(null, chunk); } }); }
内容的提问来源于stack exchange,提问作者Himanshu
相关产品推荐
相关产品推荐

