2 분 소요

winston? 💯

winston : 기본적으로 자바스크립트에서는 console 객체의 log(), error() 메서드 등으로 로그를 출력할 수 있다. 그런데 프로그램 크기가 커지면, 로그의 양도 많아지고, 로그를 보관했다가 이후 확인할 일이 생기기도 한다. 따라서 다양한 방식으로 로그를 남기기 위해 외부의 다양한 모듈을 사용할 수 있다. winston은 multiple transports를 지원하는 비동기 로깅 라이브러리다.
  • winston은 simple하고 universal한 logging 라이브러리로 다중전송을 지원한다.

  • 각 winston logger에는 여러 레벨로 구성된 다중 전송이 있을 수 있다.

  • 예를 들어 오류 로그를 데이터비이스와 콘솔 또는 로컬 파일에 동시에 저장, 출력할 수 있다

const levels = {
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  verbose: 4,
  debug: 5,
  silly: 6,
}

RFC5454에서 정한 심각한 정도에 따라 분류

숫자가 클수록 더 많은것을 기록함

ex) info = error,warn,info모두 기록 , error = error만 기록

morgan? 💯

morgan : client에 요청한 메소드나 응답으로 어떤 상태 코드를 보내주었는지 보여주는 로그를 남겨주는 모듈이다.
  • morgan(format, options)

  • format은 로그를 어떤형태로 찍을것이다를 설정하는것이다.

  • options에는 크게 3가지로 stream, skip, immediate 가 있다.

  • immediate : 찍히는 로그가 request기준인지 response를 기준인지를 true, fasle로 지정해준다.(default === response)

  • skip : 로깅을 필터해주는 것으로 function(request, response)형식의 함수로 설정해준다.

  • stream : 로그가 출력되는 위치를 지정해준다.(default === process.stdout)

이번페이지에서는 stream을 통해 winston과 함께 사용할 것이다.


사용해보기

import winston, { format } from 'winston';
import winstonDaily from 'winston-daily-rotate-file';
import winstonMongodb from 'winston-mongodb';
import dotenv from 'dotenv';

dotenv.config();

const logFormat = format.printf(({ timestamp, label, level, message }) => {
  return `${timestamp} [${label}] ${level} : ${message}`;
});

winston = logger만들기 위해 필요

winston-daily-rotate-file = logger파일을 원하는 이름과 위치, 보관날짜까지 정해줄 수 있음

winston-mongodb = 생성되는 log들을 mongoDB와 연동하여 저장 할 수 있음.

format.printf를 통해 출력될 로그를 customize할 수 있다.

나의 경우 ${timestamp} [${label}] ${level} : ${message}이렇게 지정 해주었다.

const combineLogFormat = {
  MongoDb: format.combine(
    format.label({ label: 'Vling' }),
    format.timestamp({
      format: 'YYYY-MM-DD HH:mm:dd',
    }),
    logFormat
  ),
  console: format.combine(
    format.colorize(),
    format.label({ label: 'Vling' }),
    format.timestamp({
      format: 'YYYY-MM-DD HH:mm:dd',
    }),
    logFormat
  ),
};

const opts = (level, format) => {
  if (format === 'MongoDb') {
    return new winston.transports.MongoDB({
      level: `${level}`,
      db: process.env.mongodb_atlas_uri,
      collection: 'logs',
      format: combineLogFormat.MongoDb,
    });
  }
  if (format === 'Console') {
    return new winston.transports.Console({
      level: `${level}`,
      format: combineLogFormat.console,
    });
  }
};

format.combine을 통해 형식을 하나로 합치고

그렇게 만들어진 format을 transports에 넣는다.

const logger = winston.createLogger({
  transports: [opts('verbose', 'MongoDb')],
});

if (process.env.NODE_ENV !== 'production') {
  logger.add(opts('verbose', 'Console'));
}

logger.stream = {
  write: message => logger.http(message),
};

verbose level로 mongoDB에 넣을 transtorts를 넣어주고

만약 배포환경이 아니라면 console또한 찍히게하였다.

마지막으로 stream을 통해 morgan과 연결시켜주었다.

app.use(
  morgan(`${process.env.MORGAN_FORMAT}`, {
  stream: logger.stream,
  })
);

morgan은 주로 req,res log를 찍을때에 사용되는데

app.use로 미들웨어로 log를 찍는다.

MORGAN_FORMAT=:method :status :url 🔹 clientIp : :remote-addr 🔹 userAgent : :user-agent 🔹 elapsed : :response-time ms

stram을 통해 winston과 연결시켜주었고 위의 costomize형태로 출력된다.


winston-1
개발환경에서의 log출력



winston-2
mongoDB에 log수집


그런데 로그의 timestamp가 현재의 시간하고 달랐다..

우선 ec2의 시간대를 바꿔주고

sudo rm /etc/localtime

sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

바꾸기 성공.

moment.tz.setDefault('Asia/Seoul');
const timeStamp = () => moment().format('YYYY-MM-DD HH:mm:ss');

혹시몰라서 server의 timeStamp도 timze zone을 바꿔주었다.


winston-4
time zone 변경 완료


업데이트: