WEBKT

NestJS 日志进阶:Winston & winston-daily-rotate-file 打造可扩展日志模块

7 0 0 0

NestJS 日志进阶:Winston & winston-daily-rotate-file 打造可扩展日志模块

为什么选择 Winston?

动手实践:搭建基础日志模块

进阶:自定义传输器

进阶:日志过滤器

进阶:错误追踪集成

总结

NestJS 日志进阶:Winston & winston-daily-rotate-file 打造可扩展日志模块

嗨,各位高级开发者们!相信你们在构建 NestJS 应用时,一定深知日志系统的重要性。一个好的日志系统不仅能帮你快速定位问题,还能让你洞察应用的运行状态。今天,咱们就来聊聊如何在 NestJS 中使用 winstonwinston-daily-rotate-file 打造一个可扩展的日志模块,让你的日志系统更上一层楼。

为什么选择 Winston?

在 Node.js 的世界里,winston 绝对是日志库中的佼佼者。它灵活、强大,拥有丰富的特性,能满足各种复杂的日志需求。而且,winston 的社区非常活跃,这意味着你能找到大量的资源和帮助。

winston-daily-rotate-filewinston 的一个传输器(Transport),它能按日期自动分割日志文件,避免单个日志文件过大,方便日志管理和归档。

动手实践:搭建基础日志模块

  1. 安装依赖

首先,咱们需要安装 winstonwinston-daily-rotate-file

npm install winston winston-daily-rotate-file
  1. 创建日志模块

在 NestJS 中,咱们通常会创建一个独立的模块来管理日志。创建一个 logger.module.ts 文件:

import { Module } from '@nestjs/common';
import { LoggerService } from './logger.service';
@Module({
providers: [LoggerService],
exports: [LoggerService],
})
export class LoggerModule {}
  1. 创建日志服务

接下来,创建一个 logger.service.ts 文件,这是咱们日志模块的核心:

import { Injectable, LoggerService as NestLoggerService } from '@nestjs/common';
import * as winston from 'winston';
import 'winston-daily-rotate-file';
@Injectable()
export class LoggerService implements NestLoggerService {
private readonly logger: winston.Logger;
constructor() {
this.logger = winston.createLogger({
level: 'info', // 设置日志级别
format: winston.format.combine(
winston.format.timestamp(), // 添加时间戳
winston.format.json() // 使用 JSON 格式
),
transports: [
new winston.transports.Console(), // 输出到控制台
new winston.transports.DailyRotateFile({
filename: 'logs/application-%DATE%.log', // 文件名格式
datePattern: 'YYYY-MM-DD', // 日期格式
zippedArchive: true, // 是否压缩
maxSize: '20m', // 最大文件大小
maxFiles: '14d', // 最多保留天数
}),
],
});
}
log(message: string, context?: string) {
this.logger.info(message, { context });
}
error(message: string, trace?: string, context?: string) {
this.logger.error(message, { trace, context });
}
warn(message: string, context?: string) {
this.logger.warn(message, { context });
}
debug(message: string, context?: string) {
this.logger.debug(message, { context });
}
verbose(message: string, context?: string) {
this.logger.verbose(message, { context });
}
}

在这个服务中,咱们:

  • 实现了 NestJS 的 LoggerService 接口,这样就能在 NestJS 的其他地方注入并使用咱们的日志服务了。
  • 使用 winston.createLogger 创建了一个 winston 实例。
  • 设置了日志级别为 info,这意味着 infowarnerror 级别的日志都会被记录。
  • 使用了 winston.format.combine 组合了多个格式化器:
    * winston.format.timestamp 添加时间戳。
    * winston.format.json 将日志格式化为 JSON。
  • 配置了两个传输器:
    * winston.transports.Console 将日志输出到控制台。
    * winston.transports.DailyRotateFile 将日志按日期分割保存到文件中。
  • 定义了 logerrorwarndebugverbose 方法,分别对应不同的日志级别。
  1. 使用日志服务

现在,咱们可以在其他模块中使用这个日志服务了。例如,在 app.controller.ts 中:

import { Controller, Get } from '@nestjs/common';
import { LoggerService } from './logger/logger.service';
@Controller()
export class AppController {
constructor(private readonly logger: LoggerService) {}
@Get()
getHello(): string {
this.logger.log('访问了首页', AppController.name);
return 'Hello World!';
}
}

这样,每次访问首页,咱们的日志系统就会记录一条 info 级别的日志。

进阶:自定义传输器

winston 的强大之处在于它的可扩展性。你可以自定义传输器,将日志发送到任何你想发送的地方,比如数据库、消息队列、第三方日志服务等。

下面是一个简单的自定义传输器示例,它将日志输出到一个名为 custom.log 的文件中:

import * as Transport from 'winston-transport';
import * as fs from 'fs';
export class CustomTransport extends Transport {
constructor(opts?) {
super(opts);
}
log(info: any, callback: () => void) {
setImmediate(() => {
this.emit('logged', info);
});
fs.appendFile('custom.log', JSON.stringify(info) + '\n', (err) => {
if (err) {
console.error('写入日志文件失败:', err);
}
});
callback();
}
}

然后,在logger.service.ts中添加这个自定义的transport:

// ... 其他代码
constructor() {
this.logger = winston.createLogger({
// ... 其他配置
transports: [
new winston.transports.Console(),
new winston.transports.DailyRotateFile({
// ... DailyRotateFile 配置
}),
new CustomTransport(), // 添加自定义传输器
],
});
}
// ... 其他代码

进阶:日志过滤器

有时候,你可能只想记录特定类型的日志。这时,你可以使用日志过滤器。

winston 本身并没有提供专门的过滤器功能,但你可以通过自定义格式化器来实现。

下面是一个简单的日志过滤器示例,它只记录包含特定上下文的日志:

import { format } from 'winston';
const contextFilter = format((info, opts) => {
if (info.context === opts.context) {
return info;
}
return false; // 过滤掉不符合条件的日志
});

然后,在 logger.service.ts 中使用这个过滤器:

// ... 其他代码
this.logger = winston.createLogger({
// ... 其他配置
format: winston.format.combine(
contextFilter({ context: 'AppController' }), // 只记录 context 为 AppController 的日志
winston.format.timestamp(),
winston.format.json()
),
// ... 其他配置
});
// ... 其他代码

进阶:错误追踪集成

当应用发生错误时,你可能希望将错误信息发送到错误追踪服务,比如 Sentry、Bugsnag 等。

以 Sentry 为例,你可以这样做:

  1. 安装 Sentry SDK
npm install @sentry/node @sentry/tracing
  1. 初始化 Sentry

在你的应用入口文件(通常是 main.ts)中初始化 Sentry:

import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
Sentry.init({
dsn: 'YOUR_SENTRY_DSN', // 替换为你的 Sentry DSN
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
new Tracing.Integrations.Express({ app }), // 如果你使用了 Express
],
tracesSampleRate: 1.0, // 采样率
});
  1. 在日志服务中捕获错误

logger.service.ts 中,修改 error 方法:

error(message: string, trace?: string, context?: string) {
this.logger.error(message, { trace, context });
Sentry.captureException(new Error(message), { // 捕获错误并发送到 Sentry
contexts:{
trace: trace,
context: context
}
});
}

现在当程序发生错误,sentry也能同时收到错误信息,方便追踪和管理

总结

通过本文,相信你已经掌握了如何在 NestJS 中使用 winstonwinston-daily-rotate-file 打造一个可扩展的日志模块。记住,日志系统是应用的重要组成部分,一个好的日志系统能让你事半功倍。希望这些内容对你有所帮助,让你的 NestJS 应用更上一层楼!

如果你有任何问题或想法,欢迎在评论区留言,咱们一起交流学习!

技术老兵 NestJS日志winston

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/7871