Node, Nest, Deno/🚀 Node.js (+ Express)

winston으로 로깅을 해보자

DarrenKwonDev 2021. 2. 27. 16:34

로그를 수집하고, 일정 날자가 지나면 압축하고, 너무 오래된 로그는 삭제하는 등의 log rotate 세팅은 중요합니다.

그런데 morgan은 http 메서드로 특정 URL을 방문할 때만 로깅을 합니다.

서버가 시작되었을 때, 에러가 발생했을 때 등에 대한 로깅은 winston을 사용해야 합니다.

 

사용법은 간단합니다.

 

(1) 포맷과 winstonDaily 구성을 하여 로거를 생성하고,

(2) 추가적인 세팅을 한 다음,

(3) logger.error("...") 꼴로 사용하면 됩니다.

 

 

- winton 포매팅

 

공식문서에 따른 기본 내용은 다음과 같습니다.

const logger = winston.createLogger({
  // 로거의 포맷을 세팅합니다.
  format: winston.format.json(),
})

// 출력
{"message":"NODE_ENV : development, server on : http://localhost:5000","level":"info"}

 

좀 더 알아보기 쉽게 다음과 같이 구성할 수 있습니다.

// winston format
const { combine, timestamp, printf } = winston.format;

// Define log format
// 타임스탬프, level(info, error, warn...), 메세지 순으로 출력됩니다.
const logFormat = printf(({ timestamp, level, message }) => `${timestamp} ${level}: ${message}`);

// 로거를 생성합니다.
const logger = winston.createLogger({
  // 로거의 포맷을 세팅합니다.
  format: combine(
    timestamp({
      format: 'YYYY-MM-DD HH:mm:ss',
    }),
    logFormat,
  ),
  ... 중략
})


// 출력
// 2021-02-27 16:07:44 info: NODE_ENV : development, server on : http://localhost:5000

 

- winston-daily-rotate-file

 

하루 간격으로 로그 파일을 저장하기 위한 방법이다.

www.npmjs.com/package/winston-daily-rotate-file

level의 위계는 info ~ warn ~ error이다. 아래의 경우 warn을 지정하지 않았기 때문에 info에 들어가게 된다.

그러나 대개는 info와 error만 사용하게 된다.

// 로거를 생성합니다.
const logger = winston.createLogger({
  ... 포맷 관련 설정 생략
  
  // 하루 간격 로그 파일
  transports: [
    // info log setting
    new winstonDaily({
      level: 'info', // info 레벨의 경우
      datePattern: 'YYYY-MM-DD',
      dirname: logDir + '/info', // 로그 파일이 저장될 경로
      filename: `%DATE%.log`, // 생성될 파일 이름
      maxFiles: 30, // 30 Days saved
      json: false,
      zippedArchive: true,
    }),
    // error log setting
    new winstonDaily({
      level: 'error',
      datePattern: 'YYYY-MM-DD',
      dirname: logDir + '/error', // 로그 파일이 저장될 경로
      filename: `%DATE%.error.log`, // 생성될 파일 이름
      maxFiles: 30, // 30 Days saved
      handleExceptions: true,
      json: false,
      zippedArchive: true,
    }),
  ],
});

 

- logger 사용법

 

winston 로거는 다음과 같이 사용하면 됩니다.

logger.[method](message) 꼴이고, logger를 생성할 때 지정한 포맷대로 로깅됩니다.

logger.info(`NODE_ENV : ${this.env}, server on : http://localhost:${this.port}`);
logger.error('anyhing');
logger.warn('warning');

오늘 날짜로 생성된 /logs/error/xxxx.error.log를 열어보면, error가 발생한 부분이 가지런히 정리된 것을 확인할 수 있습니다.

 

2021-02-27 15:49:49 error: anyhing
2021-02-27 15:50:15 error: anyhing
2021-02-27 15:51:01 error: anyhing

 

- logger 추가적인 작업

 

transport를 추가하거나, 지울 수 있습니다.

logger
  .clear()          // Remove all transports
  .add(console)     // Add console transport
  .add(files)       // Add file transport
  .remove(console); // Remove console transport

 

콘솔에 컬러를 하고, 다듬는 등의 작업을 해줄 수 있습니다.

logger.add(
  new winston.transports.Console({
    format: winston.format.combine(winston.format.splat(), winston.format.colorize(), winston.format.simple()),
  }),
);

 

- morgan과 같이 사용하기

// winston
const stream = {
  write: (message: string) => {
    logger.info(message.substring(0, message.lastIndexOf('\n')));
  },
};
// morgan
this.app.use(morgan('dev', { stream }));

 

morgan의 두번 째 인자로 stream을 넘길 수 있습니다.

Output stream for writing log lines, defaults to process.stdout.

www.npmjs.com/package/morgan#stream

// 기본 출력
GET /v1/ 304 4.908 ms - -

// winston 포맷으로 
info: GET /v1/ 304 8.683 ms - - {"timestamp":"2021-02-27 16:39:59"}