NestJS 入门(五)保存 Log 为文件
NestJS 入门(五)保存 Log 为文件
前言
到这里,我们的后台项目的骨架就基本完成了,在最后我们需要给项目增加一点点“记忆”——将项目中的部分 log 信息保存到本地文件中。本章主要使用winston来将日志记录到文件中。
一般来说,为了方便排查问题,log 中会记录请求的信息,报错的信息,和服务器的返回信息,分别对应了 NestJS 中的中间件、过滤器和拦截器,因此我们主要改造这三个部分。
安装 winston
winston是 Node.js 中非常流行的日志记录库,可以通过配置将日志记录到控制台、文件、数据库等不同目标中。
安装:
| 1 |  | 
我们安装了三个包,一个是主角winston,一个是nest-winston,这个包将winston封装成了 NestJS 的 Module,就不需要我们二次封装了,还有一个是winston-daily-rotate-file,这个包主要是用来做日志文件的归档的,可以自动将日志按时间或日期等规则进行分割,避免日志都记录在一个巨大的文件中。
在项目中引入 winston
类似与 TypeORM 或 Redis,我们也需要在app.module.ts中注册winston。
| 1 |  | 
这里我们将 log 文件命名为%DATE%.log,并存储在根目录的logs中。%DATE%最终会被datePattern的值替换,也就是说,最后 log 文件会以logs/2023-08-01.log的形式保存,可以根据自己的需要自定义。
zippedArchive表示是否需要用 gzip 方式压缩文件,默认为false;
maxSize和maxFiles很好理解,设置单个日志文件最大为 20MB,日志文件最长保存 14 天。
此时保存并重启项目,可以看到logs目录已经生成了。
| 1 |  | 
添加中间件
我们需要记录每个请求的信息,比如请求的 IP,请求的 URL 等,我们可以通过中间件来实现这个功能。
新建一个中间件:
| 1 |  | 
编写我们的逻辑:
| 1 |  | 
这里我们从请求中取出了method, originalUrl, body, query, params, ip并记录在日志中,各位读者也可以根据自己的需要进行修改。
注意:在①处,@Inject()中别忘记传入WINSTON_MODULE_PROVIDER,同时后面的Logger也要引入winston包中的,因为 NestJS 自身也会导出一个Logger,注意区分。
创建了中间件之后,我们需要在app.module.ts中应用一下:
| 1 |  | 
这里我们将中间件LoggerMiddleware应用在*即所有路由上。
我们随便请求一个接口,然后打开logs目录下 log 文件查看:
| 1 |  | 
没有问题。
改造错误过滤器
废话少说,直接开改:
| 1 |  | 
从 22 行到 29 行的代码简单且重复,因此抽离出来封装成一个函数:
| 1 |  | 
然后重新修改错误过滤器:
| 1 |  | 
不要忘记中间件中的代码也可以用工具函数getInfoFromReq()进行精简:
| 1 |  | 
这时发现main.ts中引用HttpExceptionFilter的地方报错了:

我们删除该行代码,改为在app.module.ts中注册:
| 1 |  | 
| 1 |  | 
测试一下:
| 1 |  | 
响应:
| 1 |  | 
查看我们的 log:
| 1 |  | 
可以看到,错误也正确的记录了下来。
改造响应拦截器
废话少说,开改:
| 1 |  | 
同样的,我们也要将响应拦截器的注册位置从main.ts转移到app.module.ts中:
| 1 |  | 
| 1 |  | 
测试一下:
重新请求了登录接口,查看 log:
| 1 |  | 
可以看到这次请求的信息和响应的信息都符合预期的记录在了文件中。
美化 log
现在我们已经可以将一些重要日志记录在本地文件中,但是查看的时候很费劲,一坨一坨的数据辣眼睛,因此笔者决定对日志进行格式化,方便查看。
| 1 |  | 
winston在配置时可以接受一个format参数,自定义格式,通过winston包中自带的format可以进行很多操作,这里笔者就不展开了,大家可以根据自己的喜好,查阅文档,进行自定义。
查看一下效果:
| 1 |  | 
这样美化有利有弊,大家可以根据实际情况酌情选择。
后记
本系列文章到这里算是完结了,不论是 NestJS 还是本系列文章中提到的各种工具,都有着非常多的功能,笔者也只是一个初学者,也只是浅尝辄止的进行了学习,并分享给大家,后面笔者也会继续分享其他内容。如果有可以改进的地方,欢迎和我交流,如果有错误,还请大家斧正。