[node.js express] winston으로 node console log 관리하기. winston 사용 설정 자세한 설명!!
오늘은 express에서 winston으로 console창에 logger 남기는 법, log기록 파일로 저장하는 법에 대해 말해볼 것이다
정말...열심히 찾아가보면서 만들었더니 혼자 쓰기 아까워서 글로 남김ㅋㅋㅋ글쓰는데 시간 더 걸리는거같혀ㅠㅠ
node로 서버단을 구현하게 되면서 console창에 logger를 남겨야겠다는 생각이 들었다.
엄청 소규모 프로젝트를 하는 중이라 파일까지는 안남겨도 될 것 같았으나...
아직 이해력 부족으로 파일로도 log를 저장하는 코드까지 구현해봤다 (=사실상 블로그보고 따라하기)
수 많은 블로그를 봤으나 제일 많이 참고된 블로그...
참고 : https://velog.io/@denmark-banana/%EA%B0%84%EB%8B%A8%ED%95%9C-Node.js-API-Server-%EB%A7%8C%EB%93%A4%EA%B8%B0-1
참고2 : https://velog.io/@ash/Node.js-%EC%84%9C%EB%B2%84%EC%97%90-logging-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-winston-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0
참고3 : https://levelup.gitconnected.com/better-logs-for-expressjs-using-winston-and-morgan-with-typescript-1c31c1ab9342
node서버에 bable을 설치안해놔서 es6버전을 쓰지 못해 애좀 먹었다...ㅋㅋㅋㅋㅋㅋ 그냥 설치해도 되긴하는데 이상한 오기가 생겨서....
아무튼 시작~~
server디렉토리 하위에 config디렉토리를 생성하고 (이미 있는 분들은 그냥 설정파일 넣어놓는 곳에 파일 생성하면 돼요)
logger.js 파일을 만들어주었다.
(이름은 winston.js든 뭐든 하고싶은대로 하면 됨. 나는 logger로 하고 모듈 명도 logger로 했으니 이 점 참고해서 이름만 바꿔주면 됩니다요)
그러고나서 winstone 다운로드!
npm install winston winston-daily-rotate-file
-> 만약 이걸로도 winston 잘 안되면 추가 설치 : npm install --save winston
winston을 이용하여 log file을 생성하려면 위의 ~~file 모듈을 다운받으면 된다.
나는 하도 여러 블로그를 보고 따라하다보니 기존의 일반 winston과 file관리할 수 있는 것까지 설치해
어떤 기능이 어디에 속한 모듈인지 모름..ㅠㅠ
winston공식 홈페이지 가면 아래의 일반 winston설치법이 나와있긴하다. 굳이 file로 관리안할 거면 기본만 설치해도 되지않을까라는 생각ㅎㅎ
아무튼 설치해주고 내가 설정한 logger.js를 보자
servers >config > logger.js
const winston = require('winston');
require('winston-daily-rotate-file');
const logDir = '../logs';
const levels = {
error: 0,
warn: 1,
info: 2,
http: 3,
debug: 4,
}
const level = () => {
const env = process.env.NODE_ENV || 'development'
const isDevelopment = env === 'development'
return isDevelopment ? 'debug' : 'warn'
}
const colors = {
error: 'red',
warn: 'yellow',
info: 'green',
http: 'magenta',
debug: 'blue',
}
winston.addColors(colors);
const format = winston.format.combine(
winston.format.timestamp({ format: ' YYYY-MM-DD HH:MM:SS ||' }),
winston.format.colorize({ all: true }),
winston.format.printf(
(info) => `${info.timestamp} [ ${info.level} ] ▶ ${info.message}`,
),
)
const logger = winston.createLogger({
format,
level: level(),
transports: [
new winston.transports.DailyRotateFile({
level: 'info',
datePattern: 'YYYY-MM-DD',
dirname: logDir,
filename: `%DATE%.log`,
zippedArchive: true,
handleExceptions: true,
maxFiles: 30,
}),
new winston.transports.DailyRotateFile({
level: 'error',
datePattern: 'YYYY-MM-DD',
dirname: logDir + '/error',
filename: `%DATE%.error.log`,
zippedArchive: true,
maxFiles: 30,
}),
new winston.transports.Console({
handleExceptions: true,
})
]
});
module.exports = logger;
+) 21년 10월 01일 추가
dirname 설정해줄 때 주의할 점은 상대경로를 제대로 입력해줘야 해당 위치에 파일이 정상적으로 생긴다는 점!!
만약 logger 설정 파일과 log 파일 남기는 위치가 동일하다면
이렇게 __dirname 을 쓰면 편하다!
현재 파일이 있는 경로 /log 폴더에 생성하겠다 뭐 이런 말이라서...
나중에 linux 서버에 배포해야된다면 이런식으로 써주는게 더 편할 것 같아서 추가해봄
그리고 파일이 안생긴다면, 해당 폴더를 한번 만들어주는 것도 좋다.
나는 바로 안생기길래 log 폴더를 새로 생성해주니까 파일이 생성되었음...
이제 하나씩 뜯어보면서 얕게 이해해보자
const levels = {
error: 0,
warn: 1,
info: 2,
http: 3,
debug: 4,
}
const level = () => {
const env = process.env.NODE_ENV || 'development'
const isDevelopment = env === 'development'
return isDevelopment ? 'debug' : 'warn'
}
- const level = {}
log의 레벨 설정, 별 변동없이 쓸 거면 이거 안적어도 되는데
아래의 개발 환경(배포인지 개발 중인지)에 따라서 표시할 logger 레벨을 다르게하기 위해 선언
- const level = () => {}
개발 중이면 0레벨~debug까지 표시, 아니라면 error ~ warn까지 logger표시
const colors = {
error: 'red',
warn: 'yellow',
info: 'green',
http: 'magenta',
debug: 'blue',
}
winston.addColors(colors);
- const colors = {}
레벨에 따라 어떤 색상을 쓸 것인지 표시. 아무 색깔을 쓰면 에러나고 winston에서 지원하는 색상만 사용 가능
-winston.addColors(colors);
위에서 설정한 색상을 winston에게 추가해줘야 정상적으로 작동
const format = winston.format.combine(
winston.format.timestamp({ format: ' YYYY-MM-DD HH:MM:SS ||' }),
winston.format.colorize({ all: true }),
winston.format.printf(
(info) => `${info.timestamp} [ ${info.level} ] ▶ ${info.message}`,
),
)
- const format = winston.format.combine()
log 표시 형식을 바꿔준다. 필요없으면 안해도 됨.
* timestamp -> 표시 날짜 형식 변경 출력 예) 2021-04-10 11:04:47 대문자 HH는 24시간 형식(이라고 알고있음)
공백과 || 표시는 내가 임의로 넣은 것이니 변경 가능!
* colorize -> log level별로 색상을 표시할 것인지. log 직관적이게 하려면 색상 주는게 나음
* printf -> 실제 출력 양식 => 뒤에부터는 `` 랑 ${}말고는 마음대로 바꾸면 된다.
* 나의 출력 예 : 날짜 || [ 레벨 ] ▶ 출력내용 -> 2021-04-10 11:04:47 || [ debug ] ▶ 출력 예시입니다.
참고로 info.level.toUpperCase() 이거 대문자로 표시하게 하니까 색상이 말을 안듣길래
왜인지 생각해봤는데 대문자로 할거면 level도 대문자로 다시 설정해줘야 인식을 하는듯 했다.
(안해봐서 실제로 이렇게하면 되는지는 모르겠음!)
포맷 설정하기 귀찮고 싫다!! 그럼 따로 안하고 나중에 transports안에 아래 문장만 적어주면 됨
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple(),
)
})
- winston.format.colorize()
log level별로 색상 적용하기
- winston.format.simple()
-> `${info.level}: ${info.message} JSON.stringify({ ...rest })` 포맷으로 출력되게 해줌. winston 기본 설정
const logger = winston.createLogger({
format,
level: level(),
transports: [
new winston.transports.DailyRotateFile({
level: 'info',
datePattern: 'YYYY-MM-DD',
dirname: logDir,
filename: `%DATE%.log`,
zippedArchive: true,
handleExceptions: true,
maxFiles: 30,
}),
new winston.transports.DailyRotateFile({
level: 'error',
datePattern: 'YYYY-MM-DD',
dirname: logDir + '/error',
filename: `%DATE%.error.log`,
zippedArchive: true,
maxFiles: 30,
}),
new winston.transports.Console({
handleExceptions: true,
})
]
});
- const logger = winston.createLogger({})
winston의 logger를 생성해주는 코드
생성할 로거option을 주면 된다.
미리 설정한 옵션이 있다면 format, level:level() 이런 식으로 적어줘도 됨
아니라면 transports 처럼 안에서 새로 선언하고 작성해줘도 됨.
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp({ format: ' YYYY-MM-DD HH:MM:SS ||' }),
winston.format.colorize({ all: true }),
winston.format.printf(
(info) => `${info.timestamp} [ ${info.level} ] ▶ ${info.message}`,
),
),
이하 생략...
})
이런식으로 createLogger({ })안에 설정해줘도 된다는 말!!
transports: [
new winston.transports.DailyRotateFile({
level: 'info',
datePattern: 'YYYY-MM-DD',
dirname: logDir,
filename: `%DATE%.log`,
zippedArchive: true,
handleExceptions: true,
maxFiles: 30,
}),
생략...
]
대충 보면 알아볼 것 같은거 빼고 간략 설명갑니당
-DaillyRotateFile({ }) : 파일로 남기기
>> level : 어떤 레벨을 log로 남길지
>> dirname: 어느 폴더에 저장할 지... 나는 맨 위에 const logDir = '../logs'; 이라고 servers-logs 폴더를 만들어놓고 거기 저장되게 해놨음
>> zippedArchive: 압축 여부
>> maxFiles: 몇일치까지 log file을 저장할 지 ex) 30이면 30일치 파일 저장
new winston.transports.Console({
handleExceptions: true,
})
위에서 이미 출력 형식을 지정해줘서 간단한데... 위에서 따로 설정을 안했다면
new winston.transports.Console({
format: 설정한 format 형식(없다면 직접 적기),
handleExceptions: true,
colorize: true,
})
이런식으로 해주면 된다!!
module.exports = logger;
어휴 힘들다... 실질적으로 어떻게 쓰나 보자!!! 다되어 간다
서버의 app.js에 가보자 (나는 server.js로 이름 바꿔놨으니 server.js라고 하겠음)
servers > server.js
const logger = require('./config/logger'));
app.use(((req, res, next) => {
logger.info('로그 출력 test용 middleware');
logger.error('error 메시지');
logger.warn('warn 메시지');
logger.info('info 메시지');
logger.http('http 메시지');
logger.debug('debug 메시지');
next();
}));
서버에 요청이 들어오면 위의 코드를 실행하게 설정해보았다.
서버 키자마자 logger찍히는지 실험해보고 싶으면 app.listen() 안에 넣어도 되지싶다...
미들웨어(middleware)란?
공식홈페이지 설명 참고: expressjs.com/ko/guide/using-middleware.html
결과는!!!
(((o(*゚▽゚*)o)))
server단에서 log를 남길 땐 console.log 보단 logger를 사용하는 것이 좋다고 했다.(이유........암튼 그랬음)
앞으로는 console.log 대신 logger.레벨()을 사용해야지!!
참고로 logger.이라고 쓰기 귀찮으면 선언해줄 때 이름을 다른거 쓰면 됨!!
const log = require('./config/logger'));
log.error('error 메시지');
log.warn('warn 메시지');
log.info('info 메시지');
log.http('http 메시지');
log.debug('debug 메시지');
끝...이냐고요? 놉...
사실 내가 하고 싶었던 것은 node 와 react (서버와 프론트엔드)간의 통신 시 log기록을 출력하고 싶었던 것....
다음 글에서는 morgan이라는 것을 사용해 서버통신 결과를 console창의 log로 출력할 것이다!
node에서 winston으로 logger 다루는 법은 일단 여기서 끝!!
--------------------------------------
morgan이용해서 log남기는 것은 >> https://xively.tistory.com/49