NestJS 로그 파일 관리

조형근·2023년 10월 26일
1

logger

목록 보기
2/2

이전글을 작성하고 나서 프로젝트를 같이 하는 형이 피드백을 주셨다.
지금 그대로라면 로그 파일은 서버의 pm2의 logs폴더 안에만 생기기 때문에 로그 관리가 필요 할것 같다고 하셨다.


처음에는 왜 따로 폴더링과 같은 관리를 해야하지 싶었지만 로그 파일 크기를 보고 정신을 차렸다...
몇일 안가서 저장공간이 부족할지도..? 그래서 따로 폴더링 및 로그파일을 삭제해주는 과정을 추가 하기로 했다.

처음에는 pm2 -log-rotate를 사용하려 했는데 마지막 업데이트가 7년 전에 깃헙 레포에 이슈가 무진장 많아서 이것 제외로 했다.
(앞으로는 npm다운로드 수나 issue가 많은지 마지막 업데이트 등을 확인 해야겠다...)


아무튼 대안으로 nest-winston을 찾았고(pino? 이친구도 있음)
많은 사람들이 nest-winston을 통해 NestJS에서 로그 관리를 한다고 한다.
nest-winston은 nest에서 winston을 이용한 로깅을 가능하게 해준다 + winston-daily-rotate-file을 통해 관리 까지 가능하다

nest-winston

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import cookieParser from 'cookie-parser';
import { ConfigService } from '@nestjs/config';
import { winstonLogger } from './logger/winston.config';
async function bootstrap() {
  const app = await NestFactory.create(AppModule, { logger: winstonLogger });// winstonLogger를 사용하도록 설정
  const configservice = app.get(ConfigService);
  const port = configservice.get('APP_PORT');
  app.enableCors({ origin: '*' }); // CORS 허용
  app.use(cookieParser()); // cookieParser 사용
  await app.listen(port);
}
bootstrap();

main.ts에서 NestFactory.create(AppModule, { logger: winstonLogger })를 통해 winston 로거를 사용하게 한다.

nest-winston + winston-daily-rotate-file

import { utilities, WinstonModule } from 'nest-winston';
import winstonDaily from 'winston-daily-rotate-file';
import winston from 'winston';
import moment from 'moment-timezone';
import appRoot from 'app-root-path';
const appendTimestamp = winston.format((info, opts) => {
  if (opts.tz) {
    info.timestamp = moment().tz(opts.tz).format();
  }
  return info;
});
// 로그 저장 파일 옵션
const dailyOptions = (level: string) => {
  return {
    level,
    datePattern: 'YYYY-MM-DD', // 날짜 포맷 지정
    dirname: `${appRoot.path}/logs` + `/${level}`, // 저장할 URL
    filename: `%DATE%.${level}.log`,
    maxFiles: 30, // 30일의 로그 저장
    zippedArchive: true, // 로그가 쌓였을 때 압축
    colorize: true,
    handleExceptions: true,
    json: false,
  };
};
// 로거 설정
export const winstonLogger = WinstonModule.createLogger({
  transports: [
    // 콘솔 출력 옵션 지정
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.colorize(),
        utilities.format.nestLike('MBTI_LENS', {
          prettyPrint: true, // 로그를 예쁘게 출력해줌
        }),
      ),
    }),
    // info, error, fatal 로그는 파일로 관리
    new winstonDaily(dailyOptions('info')),
    new winstonDaily(dailyOptions('error')),
    new winstonDaily(dailyOptions('fatal')),
  ],
  // 포멧 지정
  format: winston.format.combine(
    appendTimestamp({ tz: 'Asia/Seoul' }),
    winston.format.json(),
    winston.format.printf((info) => {
      return `${info.timestamp} - ${info.level} ${info.message}`;
    }),
  ),
});

위에서 로그 저장 파일 옵션을 함수로 설정하고 아래의 winstonLogger에서 로거 설정을 한다
시간대 설정을 명확히 하기위해 moment 라이브러리도 사용하였다.
이렇게 하면 AppRoot 바로 아래에 logs라는 폴더가 생기고 그아래에 info, error, fatal폴더 가 생긴다


이제는 로그를 찍으면 레벨에 따라 다른 폴더에 저장되고 dailyOptions을 통해 주기적으로 관리가 가능해졌다!

마치며

로깅을 무분별 하게 할 경우 성능적인 측면에서 많은 문제가 발생하고 관리하지 않고 쌓이기만 한다면 이것 또한 문제가 될 수 있음을 기억하길 바란다

profile
오늘보다 발전된 내일을 만들어요

0개의 댓글