티스토리 뷰

로직 개발을 진행이 어느정도 완료되고 나서 운영환경으로 이관하려고 하니 걸리는 것이 한두가지가 아닙니다.

그 중에 한가지, 에러 로그는 어떻게 할 것인가?

개발 할때야 console.log 로 터미널에서 아주 잘 보여주지만, 운영환경으로 넘어가면 그럴수 없죠.

 

지금 소개하려는 방법은 AWS 와 상관 없이 운영서버 디렉토리에 파일 형태로 저장하는 방법입니다.

(AWS 를 사용한다면 그냥 고민할 필요 없이 cloud watch 를 쓰면 되지만 세상일 어떻게 될지 모르니 :) ) 

 

1. 개요

winston 을 사용해 file 을 Logger.js 를 만든 뒤 로깅이 필요한 로직에서 호출하여 사용.

 

2. Logger.js

- 필요한 모듈 설치

npm install winston --save
npm install winston-daily-rotate-file --save

- 파일 작성

const appRoot = require('app-root-path') // root 경로를 가져오기 위해 사용
var winston = require('winston') // log 파일 작성
require('winston-daily-rotate-file') // log 파일을 일자별로 생성하기 위해 사용
var time = require('time') // 로그파일 제목에 일자를 표시하기 위해 사용

var transport = new (winston.transports.DailyRotateFile)({
  filename: `${appRoot}/logs/application-%DATE%.log`,
  maxsize: 1024,
  datePatten: 'YYYY-MM-DD-HH',
  timestamp: function () {
    var timezone = time.currentTimezone
    var now = new time.Date()
    now.setTimezone(timezone)
    return now.toString()
  }
});

var logger = winston.createLogger({
  transports: [
    transport
  ]
});


module.exports = logger

Logger.js 가 작성되었다면 다음 과 같은 형태로 사용하면 됩니다.

const logger = require('../Logger')

logger.log('info', '에러처리')

winston의 로그레벨은 

{ emerg: 0, alert: 1, crit: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7 }

로 8가지가 있고 위의 예제에서는 어떠한 레벨이든 모두 file 로 기록하도록 했지만 다음 과 같이 로그 레벨에 따라 다르게 동작하도록 변형할 수 있습니다.

const appRoot = require('app-root-path') // root 경로를 가져오기 위해 사용
var winston = require('winston') // log 파일 작성
require('winston-daily-rotate-file') // log 파일을 일자별로 생성하기 위해 사용
var time = require('time') // 로그파일 제목에 일자를 표시하기 위해 사용

var transport = new (winston.transports.DailyRotateFile)({
  new (winston.transports.Console)({
      level: 'info',
      colorize: false
    }),
  new (winston.transports.DailyRotateFile)({
    level: 'error',
    filename: `${appRoot}/logs/application-%DATE%.log`,
    maxsize: 1024,
    datePatten: 'YYYY-MM-DD-HH',
    timestamp: function () {
      var timezone = time.currentTimezone
      var now = new time.Date()
      now.setTimezone(timezone)
      return now.toString()
    }
  })
});

var logger = winston.createLogger({
  transports: [
    transport
  ]
});

module.exports = logger

3. Morgan 과 함께 사용하기

모건은 미들웨어 단에서 http 요청을 로깅할 수 있게 만들어 줍니다. 서버 에러 로깅이 목적이라면 위에서 처럼 필요한 모든곳에 logger 를 사용하는 대신 미들웨어 단에서 http return 코드가 에러 코드일때 로그를 자동으로 남기도록 하는 것이 더 편리합니다.

 

- logger.js 수정

const appRoot = require('app-root-path') // root 경로를 가져오기 위해 사용
var winston = require('winston') // log 파일 작성
require('winston-daily-rotate-file') // log 파일을 일자별로 생성하기 위해 사용
var time = require('time') // 로그파일 제목에 일자를 표시하기 위해 사용

var transport = new (winston.transports.DailyRotateFile)({
  filename: `${appRoot}/logs/application-%DATE%.log`,
  maxsize: 1024,
  datePatten: 'YYYY-MM-DD-HH',
  timestamp: function () {
    var timezone = time.currentTimezone
    var now = new time.Date()
    now.setTimezone(timezone)
    return now.toString()
  }
});

var logger = winston.createLogger({
  transports: [
    transport
  ]
});

logger.stream = {
  write: function (message, encoding) {
    logger.info(message)
  }
}

module.exports = logger

- app.js 수정

..
const morgan = require('morgan')
const logger = require('경로/logger')

app.use(
  morgan('combined', 
    {
      skip: function (req, res) { return res.statusCode < 400 }, // http return 이 에러일때만 출력
      stream: logger.stream // logger에서 morgan의 stream 을 받도록 추가
    }
  )
);

..

위와 같이 반영하면 app.js 에서는 morgan이 서버에서 리턴하는 http 상태 코드를 보고 정상 코드가 아닐때 logger에 message를 넘겨주게 되고,

logger 는 이 message 를 받아서 logger.info 를 사용하여 파일에 기록을 남기게 되는 구조입니다.

 

(http 상태코드는 아래 링크를 참고해 주세요.)

https://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C#4xx_(%EC%9A%94%EC%B2%AD_%EC%98%A4%EB%A5%98)

 

 

 

다음번에는 AWS S3 로 로그를 남기는 방법에 대해 적어보겠습니다.

 

감사합니다.

댓글