WEBKT

NestJS 日志管理:winston-daily-rotate-file 实现日志按天滚动归档

11 0 0 0

NestJS 日志管理:winston-daily-rotate-file 实现日志按天滚动归档

为什么需要日志轮转?

准备工作:安装依赖

创建日志服务 (Logger Service)

代码解析

在其他模块中使用日志服务

测试日志记录

更多配置选项

处理未捕获的异常和 Promise 拒绝

总结

NestJS 日志管理:winston-daily-rotate-file 实现日志按天滚动归档

对于长期运行的 NestJS 应用,日志管理至关重要。一个好的日志系统不仅能帮助你快速定位问题,还能让你了解应用的运行状态。winston 是 Node.js 社区中最流行的日志库之一,而 winston-daily-rotate-file 则是 winston 的一个传输器(Transport),它可以实现日志文件按日期自动轮转,避免单个日志文件过大,方便日志归档和管理。这篇教程将详细介绍如何在 NestJS 中配置和使用 winston-daily-rotate-file

为什么需要日志轮转?

想象一下,你的应用每天产生大量的日志,如果不进行轮转,所有的日志都写入同一个文件,这个文件会越来越大,最终可能达到几个 GB 甚至几十 GB。这将带来以下问题:

  1. 难以打开和查看: 大文件打开速度慢,甚至可能导致编辑器崩溃。
  2. 难以检索: 在巨大的日志文件中查找特定信息如同大海捞针。
  3. 磁盘空间不足: 日志文件不断增长,最终可能耗尽磁盘空间。
  4. 难以归档和备份: 大文件备份和恢复都需要更长的时间。

winston-daily-rotate-file 通过每天(或每小时、每分钟等)创建一个新的日志文件来解决这些问题,旧的日志文件可以被压缩、归档或删除,保持日志目录的整洁。

准备工作:安装依赖

首先,确保你的 NestJS 项目已经创建。如果没有,可以使用 Nest CLI 创建一个新项目:

nest new my-nestjs-app
cd my-nestjs-app

然后,安装 winstonwinston-daily-rotate-file

npm install winston winston-daily-rotate-file

创建日志服务 (Logger Service)

在 NestJS 中,推荐的做法是创建一个自定义的日志服务,而不是直接在各个模块中使用 winston。这样可以更好地控制日志配置,并方便后续的扩展和维护。

  1. 创建 logger.service.ts 文件:
// src/logger/logger.service.ts
import { Injectable, LoggerService } from '@nestjs/common';
import * as winston from 'winston';
import 'winston-daily-rotate-file';
@Injectable()
export class MyLogger implements LoggerService {
private logger: winston.Logger;
constructor() {
this.logger = winston.createLogger({
level: 'info', // 默认日志级别
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // 添加时间戳
winston.format.printf(({ timestamp, level, message, context }) => {
return `${timestamp} [${context}] ${level}: ${message}`;
})
),
transports: [
new winston.transports.Console(), // 输出到控制台
new winston.transports.DailyRotateFile({
filename: 'logs/application-%DATE%.log', // 日志文件名,%DATE% 会被替换为日期
datePattern: 'YYYY-MM-DD', // 日期格式
zippedArchive: true, // 是否压缩归档的日志文件
maxSize: '20m', // 每个日志文件的最大大小
maxFiles: '14d', // 保留的日志文件数量(天数)
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
)
}),
],
});
}
log(message: string, context?: string) {
this.logger.log('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 });
}
}
  1. 创建 logger.module.ts 文件:
// src/logger/logger.module.ts
import { Module } from '@nestjs/common';
import { MyLogger } from './logger.service';
@Module({
providers: [MyLogger],
exports: [MyLogger], // 导出 LoggerService,以便其他模块使用
})
export class LoggerModule {}

代码解析

  • winston.createLogger(): 创建 winston 日志实例。
  • level: 设置日志级别。低于此级别的日志消息将被忽略。常见的日志级别有(从低到高):sillydebugverboseinfowarnerror
  • format: 定义日志消息的格式。这里使用了 combine 方法组合了多个格式化器:
    • winston.format.timestamp(): 添加时间戳。
    • winston.format.printf(): 自定义输出格式。
    • winston.format.json(): 将日志消息格式化为 JSON。
  • transports: 配置日志输出目标。这里配置了两个传输器:
    • winston.transports.Console: 将日志输出到控制台。
    • winston.transports.DailyRotateFile: 将日志写入按日期轮转的文件。
      • filename: 日志文件名。%DATE% 是一个占位符,会被替换为实际的日期。
      • datePattern: 日期格式,用于生成日志文件名。
      • zippedArchive: 是否压缩归档的日志文件(.gz)。
      • maxSize: 每个日志文件的最大大小。超过这个大小后,会创建一个新的文件。
      • maxFiles: 最多保留多少个日志文件。超过这个数量后,旧的文件会被删除。
  • MyLogger 类实现了 LoggerService 接口: NestJS 内置的日志接口,定义了 logerrorwarndebugverbose 等方法。

在其他模块中使用日志服务

  1. AppModule 中导入 LoggerModule
// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerModule } from './logger/logger.module';
@Module({
imports: [LoggerModule], // 导入 LoggerModule
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
  1. 在需要使用日志的模块中注入 MyLogger
// src/app.service.ts
import { Injectable } from '@nestjs/common';
import { MyLogger } from './logger/logger.service';
@Injectable()
export class AppService {
constructor(private readonly logger: MyLogger) {}
getHello(): string {
this.logger.log('处理 getHello 请求', AppService.name); // 记录日志
return 'Hello World!';
}
}

测试日志记录

启动你的 NestJS 应用:

npm run start:dev

访问你的应用(例如,http://localhost:3000),然后在你的项目根目录下找到 logs 文件夹,你应该会看到类似 application-2023-10-27.log 这样的日志文件。

更多配置选项

winston-daily-rotate-file 提供了许多配置选项,可以根据你的需求进行调整。以下是一些常用的选项:

  • frequency: 轮转频率。例如,'hourly' 表示每小时轮转一次,'daily' 表示每天轮转一次(默认值)。
  • auditFile: 审计文件的路径。审计文件包含有关日志文件轮转的信息,可以用于调试。
  • utc: 是否使用 UTC 时间。默认为 false,使用本地时间。
  • extension: 文件扩展名,默认为空。
  • createSymlink: 创建软连接,默认为false
  • symlinkName: 软连接名称, 默认为current.log

你可以在 winston-daily-rotate-file 的文档中找到完整的配置选项列表:https://github.com/winstonjs/winston-daily-rotate-file

处理未捕获的异常和 Promise 拒绝

为了确保应用在发生未捕获的异常或 Promise 拒绝时也能记录日志,你可以在 winston 中配置 exceptionHandlersrejectionHandlers

// logger.service.ts
import { Injectable, LoggerService } from '@nestjs/common';
import * as winston from 'winston';
import 'winston-daily-rotate-file';
@Injectable()
export class MyLogger implements LoggerService {
private logger: winston.Logger;
constructor() {
const dailyRotateFileTransport = new winston.transports.DailyRotateFile({
filename: 'logs/application-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
)
});
this.logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.printf(({ timestamp, level, message, context, trace }) => {
return `${timestamp} [${context}] ${level}: ${message} ${trace ? `\n${trace}` : ''}`;
})
),
transports: [
new winston.transports.Console(),
dailyRotateFileTransport
],
exceptionHandlers: [
dailyRotateFileTransport,
new winston.transports.Console()
],
rejectionHandlers: [
dailyRotateFileTransport,
new winston.transports.Console()
]
});
}
// ... 其他方法 ...
}

总结

通过本教程,你学习了如何在 NestJS 中使用 winston-daily-rotate-file 实现日志的按天滚动归档。这对于长期运行的 NestJS 应用至关重要,可以有效避免单个日志文件过大,方便日志的查看、检索、归档和管理。记得根据你的实际需求调整配置选项,例如日志级别、轮转频率、文件大小限制等。一个良好的日志系统是应用稳定运行的基石,希望这篇教程能帮助你构建更健壮的 NestJS 应用!

技术老兵 NestJS日志管理winston

评论点评

打赏赞助
sponsor

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

分享

QRcode

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