在 NextJS 中使用 Pino 日志

Published on 22 August 2024
5 min read
Node
NextJS
在 NextJS 中使用 Pino 日志

安装

pnpm add pino

在项目中合适的位置新建一个 logger/index.ts 文件

typescript
import pino from 'pino';

const logger = pino({});

export default logger;

现在就可以开始使用了,在服务器组件中使用

tsx
import logger from '@/services/logger';

logger.info('App is rendering');
logger.warn('App is rendering');
logger.error('App is rendering');

控制台输出: CleanShot 2024-10-12 at 14.36.11@2x.png 上面的输出,它采用 JSON 结构化和格式化,这是结构化日志记录的流行行业标准。除了日志消息 msg 之外,日志信息中还存在以下字段:

  • level指示所记录事件的严重性的日志
  • 事件的时间time
  • hostname运行该程序的机器
  • pid正在执行的 Node.js 程序的进程 ID

目前的日志虽然比使用 console.log 已经好了很多了,但是日志多了的情况看起来依然不太方便,没有颜色等,你可以使用 pino 团队提供的 pino-pretty,它是用来美化 pino 日志的,将原始日志进行换行和添加颜色。 官方提供的示例 demo 展示 image.png

添加 pino-pretty 依赖:

bash
pnpm add pino-pretty -D

修改 next.config.js 配置

js
experimental: {
	serverComponentsExternalPackages: ['pino', 'pino-pretty'];
}
注意,不要再生产环境中使用 `pino-pretty`, 将 `pino-pretty` 作为开发依赖安装,并且再生产环境中关闭

修改 logger/index.ts 文件:

ts
import pino from 'pino';

const isProduction = process.env.NODE_ENV === 'production';

const logger = isProduction
	? pino({})
	: pino({
			transport: {
				target: 'pino-pretty',
				options: {
					colorize: true
				}
			}
	  });

export default logger;

再次查看控制台日志输出 CleanShot 2024-10-12 at 14.52.35@2x.png

输出换行后的对象日志

tsx
const obj = {
	name: '123',
	info: {
		age: 123
	}
};

console.log(obj);
logger.info(obj);

对比结果 CleanShot 2024-10-12 at 14.57.20@2x.png

日志级别

pino 中的默认日志级别从最低到最严重依次为

  • trace - 10
  • debug - 20
  • info - 30
  • warn - 40
  • error - 50
  • fatal - 60

当你在代码中添加下面的 log

ts
logger.trace('Trace');
logger.debug('Debug');
logger.info('Info');
logger.warn('Warning');
logger.error('Error');
logger.fatal('Fatal');

会发现控制台的输出只有四条

bash
[15:09:54.736] INFO (95497): Info
[15:09:54.736] WARN (95497): Warning
[15:09:54.736] ERROR (95497): Error
[15:09:54.736] FATAL (95497): Fatal

这是因为 pino 的默认最低日志级别是 info,所以低于 info 等级的日志不会输出出来,修改下 pino 默认最低日志级别看看

tsx
import pino from 'pino';

const isProduction = process.env.NODE_ENV === 'production';

const logger = isProduction
	? pino({
			level: 'warn'
	  })
	: pino({
			level: 'trace',
			transport: {
				target: 'pino-pretty',
				options: {
					colorize: true
				}
			}
	  });

export default logger;

查看控制台输出,可以看到六条日志

bash
[15:12:41.983] TRACE (95497): Trace
[15:12:41.983] DEBUG (95497): Debug
[15:12:41.983] INFO (95497): Info
[15:12:41.983] WARN (95497): Warning
[15:12:41.983] ERROR (95497): Error
[15:12:41.983] FATAL (95497): Fatal

建议在开发阶段设置最低日志 trace 或者 debug,在生产中最低日志设置为 info 或者 warn

在浏览器中使用

pino 除了支持在 Node 环境中使用之外,也支持在浏览器中使用,你可以通过添加

ts
browser: {
	asObject: true;
}

来创建一个类似与服务器的 pino 日志对象,而不是将所有参数传递给控制台方法

json
{
	"time": "2024-10-12T07:42:35.405Z",
	"level": 30,
	"module": "Auth Login",
	"msg": "Auth Login Module"
}

一些使用技巧

1. 设置日志 module

在文件或者模块的上下文中设置 logger 所属 module,实现该文件下所有日志与其他地方的日志区分开,通过 logger.child 创建一个子记录器

tsx
import logger from '@/services/logger';

log.info('User Module');

const log = logger.child({ module: 'User Module' });

输出

bash
[15:27:07.182] INFO (95497): User Module
    module: "User"