NestJs + Winston logging 해보기

juni·2023년 9월 4일

Nestjs

목록 보기
2/2

개요

프로젝트를 진행하면서 터지는 버그나, 프론트가 테스트하면서 보내는 로그를 들어가서 매번 직접 확인하는 것은 능률이 매우 떨어지며... 비효율적인 방법이다.

로깅의 필요성?

  1. 우리 서비스의 예상 유저는 약 천 명 이상이었다.
  2. 적지 않은 기능 구현이 되어 있었고
  3. AWS S3등의 외부 모듈을 사용

때문에 우리 서비스의 동작 과정, 서비스 기록, 에러 기록을 위한 로깅이 필수적이었다.
프로젝트의 규모가 커질수록 에러가 난 코드를 추적하는 것은 어려우며, 시간과 노력이 많이 든다


모듈 설치

먼저 필요한 모듈을 설치해준다.
moment-timezone : 한국 시간으로 로그를 찍기 위해

npm ci moment-timezone winston-daily-rotate-file winston

winston.confing.ts

로깅 설정을 해둔다.
로그 파일이 저장될 폴더를 지정해주었다.
로그가 찍히는 시간을 아시아/서울로 지정해주었다.

import * as winston from 'winston';
import { utilities as nestWinstonModuleUtilities } from 'nest-winston';
import * as winstonDaily from 'winston-daily-rotate-file';
import * as moment from 'moment-timezone';

const appendTimestamp = winston.format((info, opts) => {
  if (opts.tz) info.timestamp = moment().tz(opts.tz).format(' YYYY-MM-DD HH:mm:ss ||');
  return info;
});

export const winstonConfig = {
  transports: [
    new winston.transports.Console({
      level: process.env.NODE_ENV === 'production' ? 'info' : 'silly',
      format: winston.format.combine(
        appendTimestamp({ tz: 'Asia/Seoul' }),
        nestWinstonModuleUtilities.format.nestLike('MyApp', {
          prettyPrint: true,
        }),
      ),
    }),
    new winstonDaily({
      dirname: `./logs/`,
      format: winston.format.combine(
        appendTimestamp({ tz: 'Asia/Seoul' }),
        nestWinstonModuleUtilities.format.nestLike('Hy-fes', {
          prettyPrint: true,
        }),
      ),
    }),
  ],
};

app.module.ts

최상위 모듈에 winstonModul을 import한다

import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston';
import { winstonConfig } from './config/winston.config';

@Module({
  imports: [
    ...
    WinstonModule.forRoot(winstonConfig),
	...
  ],
  controllers: [AppController],
})
export class AppModule {}

사용하는 모듈에서 import하기 - module

import { WinstonModule } from 'nest-winston';

@Module({
  imports: [
    WinstonModule,
  ],
  providers: [UserService],
  controllers: [UserController],
})
export class UserModule {}

사용하는 모듈에서 import하기 - controller

import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger as WinstonLogger } from 'winston';

@ApiTags('User')
@Controller('user')
export class UserController {
	constructor(
    private readonly userService: UserService,
    @Inject(WINSTON_MODULE_PROVIDER)
    private readonly logger: WinstonLogger,
  ) {}
  
  @Get()
  async getHello(): Promise<GetClubOverviewDTO[]> {
    this.logger.info(`[User Controller - getHello]`);
    return await this.userService.getHello();
  }
}

사용하는 모듈에서 import 하기 - service

위 컨트롤러처럼 주입을 받아서 사용하면 된다.

로그 파일


이렇게 날짜 이름으로 로그 파일이 생성되며,

[MyApp] Info	 2023-09-02 19:49:06 || [User Controller - getHello]

로그 파일 내부에 로그가 찍혀있는 것을 확인할 수 있다.

앱의 필요에 따라, DTO의 핵심 정보 같은 것이나, 에러 메시지를 함께 출력하도록 하자.

profile
끄적끄적 성장 기록

0개의 댓글