Pino.js解决同时启用transport和stream的问题
今天在处理项目中一个 bug 时,发现
Pino.js
配置的transport
和stream
,只有transport
生效了,配置选项如下:/** pinoHttp的配置选项 */ const devOptions: Options = { /** 对每个请求/响应的自动日志设置上下文的值 */ customProps: (_req, _res) => ({ context: 'HTTP' }), transport: { target: 'pino-pretty', options: { translateTime: 'HH:MM:ss Z', }, }, stream: pino.destination(LOG_PATH + LOG_NAME), };
本意是要开发环境中,使用 pino-pretty 美化日志输出,方便定位问题,同时启用 stream 将日志写入到日志文件中。 但是现在,pino-pretty 是正常输出的 ,而日志文件中没有日志记录。
先问了问 ChatGPT,说两者冲突无法共存,又重复询问了几次,答案就开始冲突,陷入死循环了。
尝试喂了官方文档校正一下,逻辑还是前后矛盾……得了,还是自己来吧。
翻了翻官方文档,在 Transports 这个章节中,有提及
A transport is a module that exports a default function that returns a writable stream. 传输器是一个导出默认方法的模块,该方法返回一个可写流。
返回的是一个可写流……这样的话,将 transport 看作一个普通的流,直接使用
pino.multistream
方法配置不就行了嘛。修改如下:
/** pinoHttp的配置选项 */ const devOptions: Options = { /** 对每个请求/响应的自动日志设置上下文的值 */ customProps: (_req, _res) => ({ context: 'HTTP' }), stream: pino.multistream([ pino.transport({ target: 'pino-pretty' }), pino.destination(LOG_PATH + LOG_NAME), ]), };
再测试一下,控制台输出的是经过
pino-pretty
美化后的日志,文件中存储的是原始的 JSON 日志,符合预期的效果。很好,收工……了么?
然而没那么顺利,为了避免在生产服务器上留下
node_modules
这么一大坨依赖,我是使用ncc
将项目打包之后再进行部署的。按照上面的方式修改日志配置之后,项目运行后会提示
Error: Cannot find module 'real-require'。
经过一番定位之后,感觉问题应该出自
pino.transport({ target: 'pino-pretty' })
这里,查看 pino.js 源码后,大致判断是因为这种使用方式使用了ncc
不支持的动态导入。最简单的解决方式就是回退一下方案,毕竟现有的开发环境中其实没太大的必要保留日志文件……现在的 Options 之所以这么写,是因为这是从我的另一个爬虫项目复制过来的 = = ||。 爬虫嘛,除了测试过程中看看控制台输出,后续分析的时候主要还是靠翻找日志的。
但是回退会让我感觉这样很不爽继续折腾,机缘巧合之下,发现
pino-pretty
默认导出方法的类型定义是:
declare function PinoPretty(options?: PrettyOptions_): PinoPretty.PrettyStream;
啧,也是一个流,所以上面的选项我又改成了这样:
/** pinoHttp的配置选项 */ const devOptions: Options = { /** 对每个请求/响应的自动日志设置上下文的值 */ customProps: (_req, _res) => ({ context: 'HTTP' }), // 输出到控制台,或者设置成如下,同时输出到控制台和文件中: stream: pino.multistream([ pinoPretty({ translateTime: 'HH:MM:ss Z' }), pino.destination({ dest: LOG_PATH + LOG_NAME, minLength: 4096, sync: false, }), ]), };
ncc 再进行打包,测试后发现正常了。