NestJS日志系统集成

如何在NestJS项目中集成日志系统?目前使用默认的Logger感觉功能有限,想实现以下需求:

  1. 日志分级(DEBUG/INFO/WARN/ERROR);
  2. 日志持久化存储到文件;
  3. 自定义日志格式(包含时间戳、请求ID等)。
  4. 尝试过winston但配置时遇到类型冲突问题,请问有没有成熟的集成方案?最好能分享具体配置示例和常见问题解决方案。
3 回复

在NestJS中集成日志系统非常简单。默认使用@nestjs/common中的Logger类,它功能强大且易于使用。如果你想要更高级的日志管理,可以集成第三方库如winstonpino

首先安装winston

npm install winston

然后创建一个自定义日志服务来集成winston

import { Injectable } from '@nestjs/common';
import * as winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

@Injectable()
export class CustomLoggerService {
  log(message: string) {
    logger.log('info', message);
  }

  error(message: string, trace: string) {
    logger.error(message, trace);
  }

  warn(message: string) {
    logger.warn(message);
  }

  debug?(message: string) {
    logger.debug(message);
  }

  verbose?(message: string) {
    logger.verbose(message);
  }
}

在模块中注入并使用该服务:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomLoggerService } from './custom-logger.service';

@Module({
  controllers: [AppController],
  providers: [AppService, CustomLoggerService],
})
export class AppModule {}

这样你就有了一个可扩展的日志系统,适合生产环境使用。


在NestJS中集成日志系统非常简单。默认情况下,NestJS 使用 pino 作为其日志系统,它轻量且高效。

首先确保你已安装了 NestJS 的核心依赖:

npm install @nestjs/common @nestjs/core

然后你可以直接使用 Logger 类进行日志记录:

import { Controller, Get } from '@nestjs/common';
import { Logger } from '@nestjs/common';

@Controller()
export class AppController {
  private readonly logger = new Logger(AppController.name);

  @Get()
  getHello(): string {
    this.logger.log('Log example');
    this.logger.error('Error example');
    this.logger.warn('Warn example');
    return 'Hello World!';
  }
}

如果你想自定义日志格式,可以创建一个自定义的 Logger 并覆盖默认行为:

import { Injectable, Scope } from '@nestjs/common';
import { Request } from 'express';
import * as pino from 'pino';

@Injectable({ scope: Scope.TRANSIENT })
export class CustomLoggerService {
  private readonly logger: any;

  constructor() {
    this.logger = pino({
      transport: {
        target: 'pino-pretty',
      },
    });
  }

  log(message: any) {
    this.logger.info(message);
  }

  error(message: any, trace: string) {
    this.logger.error(message, trace);
  }

  warn(message: any) {
    this.logger.warn(message);
  }

  debug?(message: any) {
    this.logger.debug(message);
  }

  verbose?(message: any) {
    this.logger.verbose(message);
  }
}

最后,在你的模块文件中注入这个自定义的服务即可。

NestJS日志系统集成

NestJS提供了灵活的日志系统,可以轻松集成多种日志解决方案。下面介绍几种常见的集成方式:

1. 内置日志

NestJS自带简单日志功能:

import { Logger } from '@nestjs/common';

const logger = new Logger('MyService');
logger.log('Info message');
logger.error('Error message');
logger.warn('Warning message');

2. 使用Winston集成

Winston是最流行的Node.js日志库之一:

  1. 安装依赖:
npm install winston nest-winston winston-daily-rotate-file
  1. 配置winston:
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
import * as DailyRotateFile from 'winston-daily-rotate-file';

const loggerConfig = WinstonModule.createLogger({
  transports: [
    new winston.transports.Console(),
    new DailyRotateFile({
      filename: 'logs/application-%DATE%.log',
      datePattern: 'YYYY-MM-DD',
      zippedArchive: true,
      maxSize: '20m',
      maxFiles: '14d'
    })
  ]
});

// 在main.ts中使用
app.useLogger(loggerConfig);

3. 使用Pino集成

Pino是高性能日志库:

  1. 安装依赖:
npm install nestjs-pino pino-http
  1. 在app.module.ts中:
import { LoggerModule } from 'nestjs-pino';

@Module({
  imports: [
    LoggerModule.forRoot({
      pinoHttp: {
        level: 'info',
        transport: {
          target: 'pino-pretty'
        }
      }
    })
  ]
})
export class AppModule {}

4. 全局日志拦截器

创建全局日志拦截器:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Logger } from '@nestjs/common';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  private readonly logger = new Logger(LoggingInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const req = context.switchToHttp().getRequest();
    this.logger.log(`Request to ${req.method} ${req.path}`);

    return next.handle().pipe(
      tap(() => {
        this.logger.log(`Response from ${req.method} ${req.path}`);
      })
    );
  }
}

// 在main.ts中全局注册
app.useGlobalInterceptors(new LoggingInterceptor());

选择哪种日志方案取决于项目需求,Winston适合功能丰富的日志需求,Pino适合高性能场景,内置日志适合简单应用。

回到顶部