2022. 3. 5. 16:43ㆍ프로젝트/Just Site
얼마 전에 회사에서 윈스턴을 썼는데,
추가적으로 공부도 할 겸해서 정리해보겠다.
1. 설치
우선 패키지를 설치한다.
npm i winston winston-daily-rotate-file
winston-daily-rotate-file은 매일 로그 파일을 만들어주는 패키지다.
2. 실행해보기
그리고 로거(logger)를 담당할 파일을 하나 만들자.
나는 logger.js로 만들었다.
const winston = require('winston');
const logger = winston.createLogger({
format: winston.format.simple(),
level: 'info',
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
// test
logger.info('test');
exports.logger = logger;
이제 logger.js를 실행해보자
node logger.js
같은 폴더에 conbined.log와 error.log 파일이 생성되었다.
// combined.log
info: test
위와 같이 로그가 찍혀서 파일로 출력되었다.
이제 요소 하나하나를 살펴보도록 하자.
3. 로거에 속성 주기
logger객체는 다음의 요소들을 가진다.
{
level: 'info', // 이 로그 이상만 기록함. info라면 info위에 있는 error, warn, info만 기록
levels: winston.config.npm.levels, // 커스텀한 레벨을 등록할 수 있다.
format: winston.format.json, // 로그의 형식(포맷)을 정할 수 있다.
transports: [], // 로그를 어떻게 처리할건지 정할 수 있다.
exitOnError: true, // false면 process.exit일 때의 exception을 기록하지 않는다.
silent: false, // true면, 로그는 찍히지 않는다.
}
이 요소들은 createLogger를 호출하면서 매개변수로 줄 수도 있고,
따로 줄수도 있다. 또는 새로운 설정으로 덮어쓸 수 있다.
// 생성과 동시에
const logger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'combined.log' }),
],
});
// 따로 주기
logger.level = 'warn';
logger.levels = {};
logger.silent = true;
// 이미 생성된 로거 객체의 설정 덮어쓰기
logger.configure({
transports: [
new winston.transports.File({ filename: 'somefile.log' }),
],
});
3-1. level
암 온더 넥스트 레벨
우선 RFC 5424를 기준 + winston에서 추가된 종류를 살펴보자.
const levels = {
error: 0,
warn: 1,
info: 2,
http: 3,
verbose: 4,
debug: 5,
silly: 6
};
위와 같이 순서대로 에러, 경고, 정보, http, 주절주절, 디버그, 잡로그 등이 있다.
로그의 성격에 따라서 호출하면 된다.
logger.error(''); // 에러
logger.warn(''); // 경고
logger.info(''); // 정보
logger.http(''); // http
logger.verbose(''); // 주절주절
logger.debug(''); // 디버그
logger.silly(''); // 잡로그
내가 logger에 level을 'info'로 줬다면,
info(2)이상인 error(0), warn(1), info(2)만 로거에 기록된다.
3-2. levels
위에서 살펴본 levels변수를 직접 설정할 수 있다.
그냥 바로 예시를 보고 이해하자.
const myCustomLevels = {
levels: {
foo: 0,
bar: 1,
baz: 2,
foobar: 3
},
colors: {
foo: 'blue',
bar: 'green',
baz: 'yellow',
foobar: 'red'
}
};
const customLevelLogger = winston.createLogger({
levels: myCustomLevels.levels
});
customLevelLogger.foobar('some foobar level-ed message');
위와 같이 foo, bar, baz, foobar를 로그의 종류로 만들었다.
그리고 호출도 .foobar()같이 하면 된다.
3-3. format
로그의 형식을 정할 수 있다.
우선 기본으로 제공해준 winston.format를 살펴보자.
const { splat, timestamp, label, ms, combine, printf } = winston.format;
splat(): C언의 printf처럼 %d, %s 스타일로 작성할 수 있다
timestamp(): 메시지를 받은(로그가 찍힌) 시간을 알 수 있다.
label(): 각 메시지에 연결된 커스텀 라벨을 알 수있다.
ms(): 이전 로그메세지 이후에 몇초만에 도착한 로그인지 알려준다
combine(): 여러 format을 연결한다.
printf(): 포맷을 커스텀하게 설정할 수 있다.
예시로 하나 해보자.
우리는 시간 + 타입 + 메시지를 기록하고 싶다.
const winston = require('winston');
const { combine, printf, timestamp } = winston.format;
const myFormat = printf(({ timestamp, level, message }) => {
return `${timestamp} [${level}]: ${message}`;
});
const logger = winston.createLogger({
format: combine(
timestamp(),
myFormat,
),
transports: [
new winston.transports.File({ filename: 'combined.log '}),
],
});
2022-03-05T07:02:22.808Z [info]: test
위와 같이 로그가 찍혔다.
보다시피 combined를 사용하면 먼저 호출된 정보가 뒤로 가서 쌓이게 된다.
combined에 들어간 순서대로 처리가 된다는 소리다.
이번엔 ms를 넣어보자.
const winston = require('winston');
const { combine, printf, timestamp, ms } = winston.format;
const myFormat = printf(({ timestamp, ms, level, message }) => {
return `${timestamp} [${level}]: ${message} - ${ms}`;
});
const logger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'combined.log' }),
]
});
// test
logger.info('test');
logger.info('test2');
exports.logger = logger;
2022-03-05T07:04:56.557Z [info]: test - +0ms
2022-03-05T07:04:56.558Z [info]: test2 - +1ms
3-4. transports
가장 중요한 핵심 부분이다.
로그를 받았다. 근데?
'어~ 잘받았다~' 할게 아니라면,
어디론가 출력을 해줘야 하지 않겠는다.
이게 정식 API가 없어서 README를 보고 하는 중인데,
이것저것 알아보도록 하자
File
가장 기본적으로 파일로 저장하는 방식이다.
한 줄씩 쌓는다.
const logger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'combined.log' }),
],
});
참고로 transports에 여러개를 넣으면 다 처리된다.
combined와는 다른 구조다.
그리고 특정 레벨의 로그를 분리할 수도 있다.
const logger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'combined.log' }),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
]
});
// test
logger.info('test');
logger.error('test2');
// combined.log
2022-03-05T07:29:51.529Z [info]: test - +0ms
2022-03-05T07:29:51.530Z [error]: test2 - +1ms
// error.log
2022-03-05T07:29:51.530Z [error]: test2 - +1ms
Console
우리가 실행하는 콘솔에 표시하는 방식이다.
const logger = winston.createLogger({
transports: [
new winston.transports.Console(),
]
});
// test
logger.info('test');
logger.error('test2');
// 콘솔창(cmd)
C:\Users\user\Documents\GitHub\legacy\winston-sample (winston-sample@1.0.0)
λ node logger.js
2022-03-05T07:33:18.457Z [info]: test - +0ms
2022-03-05T07:33:18.459Z [error]: test2 - +2ms
winstonDaily
우리가 아까 설치했던, 매일매일 파일로 분리를 해준다.
로그 파일이 쌓이면 여는거조차 힘들고, 날짜 찾기도 힘들어서 있으면 좋다.
물론 일반 File과 daily를 섞어도 좋다.
아까 패키지 설치를 안 했다면 패키지부터 설치하자.
npm i winston-daily-rotate-file
const winstonDaily = require('winston-daily-rotate-file');
const logger = winston.createLogger({
transports: [
new winstonDaily({
level: 'info', // 어떤 정보를 기록할건가
datePattern: 'YYYY-MM-DD', // 파일 형식. 2022-03-05
dirname: 'log, // 저장할 폴더. 프로젝트 root를 기준으로 생성됨
filename: `%DATE%.log`, //파일이름. %DATE%는 위의 datePattern으로 정해진다.
maxFiles: 30, // 30일치 로그 파일 저장
zippedArchive: true, // 아카이브 압축
}),
]
});
// test
logger.info('test');
logger.error('test2');
이렇게 생겼다. 날짜가 바뀌면 날짜에 맞게 새 파일에 저장된다.
물론 딴짓도 하긴 했는데 찾아보면서 정리하니까
약 2시간 반정도 갔다. 이게 말인가...
그래도 원리가 이해되니까 원하는대로 할 수 있을 것 같다.
'프로젝트 > Just Site' 카테고리의 다른 글
[Just Site] 11. node.js 서버 설정 숨기기 (feat. dotenv) (0) | 2022.03.05 |
---|---|
[Just Site] 9. 살며시 내려오는 애니메이션 만들기 (CSS) (0) | 2022.02.20 |
[Just Site] 8. socket.io 공부 (2) - 튜토리얼 숙제 풀이 (0) | 2022.02.12 |
[Just Site] 7. socket.io 공부 (1) - 튜토리얼 따라하기 (0) | 2022.02.12 |
[Just Site] 6. MYSQL과 서버 연결하기 (feat. Network) (0) | 2022.02.09 |