如何使用PINO同时将日志写入文件与控制台?
如何使用PINO同时将日志写入文件与控制台?
当然可以做到!Pino 自带多流输出的能力,完美适配你既想把日志写入文件、又想在控制台优雅输出的需求,还能彻底替代零散杂乱的console.log()~
先对应你的环境版本:
- Node Version: 21.6.1
- Typescript Version: 5.3.3
- Pino Version: 8.18.0
- Pino Pretty Version: 10.3.1
下面是修改后的完整实现代码,我会标注关键改动点:
import pino from 'pino'; import { getEnvConfig } from "config/env"; import fs from 'fs'; import path from 'path'; const envConfig = getEnvConfig(); const logdir: string = envConfig.log_dir; // 提前校验并创建日志目录,避免写入失败 if (!fs.existsSync(logdir)) { fs.mkdirSync(logdir, { recursive: true }); } const logfile: string = path.join(logdir, `appName-${new Date(Date.now()).toISOString().split('T')[0]}.log`); // 配置控制台的美化输出流 const consoleStream = pino.transport({ target: 'pino-pretty', options: { colorize: true, // 控制台日志按级别区分颜色 translateTime: 'HH:MM:ss Z', // 自定义控制台显示的时间格式 ignore: 'pid,host,node_version' // 可以隐藏控制台不需要的字段 } }); // 创建文件写入流 const fileStream = pino.destination(logfile); export const logger = pino({ level: envConfig.log_level ?? "info", formatters: { bindings: (bindings) => { return { pid: bindings.pid, host: bindings.hostname, node_version: process.version }; }, level: (label: string) => { return { level: label.toUpperCase() }; }, }, timestamp: () => `,"time":"${new Date(Date.now()).toISOString()}"` }, pino.multistream([ { stream: fileStream }, // 输出到日志文件 { stream: consoleStream } // 输出到控制台 ]));
关键说明:
- 多流组合:通过
pino.multistream把文件流和控制台流绑定到一起,实现一次日志调用同时输出到两个目标 - 目录兜底:新增了日志目录的存在校验,用递归创建目录的方式避免因目录不存在导致的写入异常
- 控制台美化:用
pino.transport配置pino-pretty,让控制台日志更易读,还能通过options自定义样式、过滤字段 - 格式复用:你原有的格式器配置可以完全保留,保证文件日志的结构完整,控制台则可以按需隐藏冗余字段
之后直接调用logger.info('业务日志')、logger.error(new Error('异常信息'))等方法即可,既会写入每日生成的日志文件,也会在控制台输出整洁的日志,彻底告别console.log()的混乱~
备注:内容来源于stack exchange,提问作者Ranjeet




