nestjs日志系统winston配置学习

1,054 阅读2分钟
跳过nest内置日志系统主要是希望分类输出日志文件方便进行查询!

使用依赖nest-winston

main.ts文件里替换nest内置的logger

//  main.ts 文件
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

//  使用winston替代nest自带日志系统
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; // <-----

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // app.setGlobalPrefix('全局接口前缀')
  app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER))  // <-------
  await app.listen(3000);
}
bootstrap();

app.module.ts里配置自定义选项,分类输出日志文件

import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
import { format } from 'winston';
const { combine, timestamp, label, prettyPrint } = format;
//.......
@Module({
  imports: [
    WinstonModule.forRoot({
       //  输出格式
      // format: winston.format.json(),
      format: combine(
        label({ label: '测试' }),
        timestamp(),
        prettyPrint()
      ),
      transports: [  
        new winston.transports.Console({
          format: winston.format.combine(
            winston.format.timestamp(),
          ),
        }),
        // 输出文件
        new winston.transports.File({  //定义输出日志文件
          filename: 'logFile/combined.log',
          level: 'info',
          // format: winston.format.combine(
          //   winston.format.timestamp({
          //     format: 'YYYY-MM-DD HH:mm:ss',
          //   }),
          //   winston.format.json(),
          // ),
        }),
        new winston.transports.File({
          filename: 'logFile/errors.log',
          level: 'error'
        }),
        new winston.transports.File({
          filename: 'logFile/warning.log',
          level: 'warning'
        }),
      ],
      // 未捕获的异常
      exceptionHandlers: [
        new winston.transports.File({ filename: 'logFile/exceptions.log' })
      ]
    })
    ],
    controllers: [AppController],
    providers: [AppService],
    }]

主动输出日志需要到模块controller里inject

import { LoggerService } from '@nestjs/common';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';

@Controller() 
export class AppController {
  constructor(
    private readonly appService: AppService,
    @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: LoggerService
    ) {}
    
  @get()
  getData(){
    this.logger.warn( {message:'==========='})
    }
    }

滚动输出日志,需要用到依赖winston-daily-rotate-file,会每小时自动生成新的日志文件

和输出文件一样,配置在module的transport数组中, 既然使用了滚动,那上面的new winston.transports.File就可以注释不用了

//  实测使用typescript方式引入会报错
import  'winston-daily-rotate-file';
//。。。。。
        new winston.transports.DailyRotateFile({
          level: 'info',
          filename: 'logFile/info-%DATE%.log',
          datePattern: 'YYYY-MM-DD-HH',
          zippedArchive: true,
          maxSize: '10m',
          maxFiles: '14d'
        }),
        new winston.transports.DailyRotateFile({
          level: 'warn',
          filename: 'logFile/warn-%DATE%.log',
          datePattern: 'YYYY-MM-DD-HH',
          zippedArchive: true,
          maxSize: '10m',
          maxFiles: '30d'
        }),

滚动日志依赖默认没有时间戳,全局配置format会导致日志文件出现undefined的bug 原因是需要配置输出格式 此处参考大神解决方案

原因是forRoot里设置了全局format属性会覆写,所以在全局定义里要再定义下打印输出日志的内容,使用winston.format.printf()

WinstonModule.forRoot({
 format: combine(
        winston.format.timestamp({
          format: 'YYYY-MM-DD HH:mm:ss',
      }),
      winston.format.printf((info) => {   // 定义文件输出内容
        return `时间:${info.timestamp},日志类型:${info.level},${info?.context ? `运行背景: ${info.context}` : '' },日志信息: ${info.message}`
      })
})

至此一般运行和主动触发的日志就能自动写入文件里了,关于对请求接口进行日志记录和输出,请看这里

545645.JPG