NestJS集成日志服务

NestJS集成日志服务

Tags
NestJS
NodeJS
Published
Jun 7, 2022
一个设计优良的线上应用服务,应该具备完整的日志打点功能。下面以NestJS为例,在Node端集成日志服务。

1、打开应用日志开关

const app = await NestFactory.create(AppModule, {
    logger: IS_DEV ? ['log', 'debug', 'warn', 'error'] : ['warn', 'error'],
})

2、新增日志类

使用第三方库 winston 为底层日志服务
//logger.service.ts
import { Injectable } from '@nestjs/common'
import * as winston from 'winston'
import * as DailyRotateFile from 'winston-daily-rotate-file'
import * as path from 'path'

const IS_DEV = process.env.NODE_ENV !== 'production'
const isObject = data => Object.is(Object.prototype.toString.call(data), '[object Object]')

@Injectable()
export class LoggerService {
  private logger: winston.Logger
  constructor(appName) {
    this.logger = winston.createLogger({
			//level : { error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 } 
      level: IS_DEV ? 'silly' : 'info',
      format: winston.format.combine(
        winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
        winston.format.colorize(),
				//自定义打印格式
        winston.format.printf(({ level, timestamp, message }) => {
          return `[${timestamp}] [${level}] [${appName}]: ${message}`
        }),
      ),
      transports: [
				//分包,当文件大于20M时会自动拆分
        new DailyRotateFile({
          filename: path.join(process.cwd(), 'logs/error-%DATE%.log'),
          datePattern: 'YYYY-MM-DD',
          zippedArchive: true,
          maxSize: '20m',
          maxFiles: '14d',
          level: 'error',
        }),
        new DailyRotateFile({
          filename: path.join(process.cwd(), 'logs/info-%DATE%.log'),
          datePattern: 'YYYY-MM-DD',
          zippedArchive: true,
          handleExceptions: true,
          maxSize: '20m',
          maxFiles: '14d',
          level: 'silly',
        }),
        IS_DEV ? new winston.transports.Console({}) : null,
      ].filter(t => !!t),
    })
  }

  private stringify(...args: any[]): string {
    return args.map(arg => (isObject(arg) ? JSON.stringify(arg) : arg)).join('')
  }

  public error(message: any, data?: any): void {
    this.logger.error(this.stringify(message, data))
  }

  public warn(message: any, data?: any): void {
    this.logger.warn(this.stringify(message, data))
  }

  public info(message: any, data?: any): void {
    this.logger.info(this.stringify(message, data))
  }

  public http(message: any, data?: any): void {
    this.logger.http(this.stringify(message, data))
  }

  public verbose(message: any, data?: any): void {
    this.logger.verbose(this.stringify(message, data))
  }

  public debug(message: any, data?: any): void {
    this.logger.debug(this.stringify(message, data))
  }

  public silly(message: any, data?: any): void {
    this.logger.silly(this.stringify(message, data))
  }
}

3、使用日志

import { Injectable } from '@nestjs/common'
import { LoggerService } from '@/shared/logger/logger.service'

@Injectable()
export class ArticleService {
  private readonly logger = new LoggerService(ArticleService.name)

  create() {
    this.logger.info('日志服务', 'create')
  }
}