Pino로 로깅하기
해당 로그들을 파일로 뽑아내야 할 일이 있어 Pino를 사용해 getServerSideProps에서 나오는 로그들을 뽑아내보았습니다.
아래는 버전 참고하시면 될듯합니다.
// package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -p 3000",
"build": "next build",
"start": "NODE_ENV=production node server.js"
},
"dependencies": {
"next": "^12.2.2",
"pino": "^8.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
JavaScript
복사
Pino를 사용한 기본 로깅
우선 pino를 사용한 코드를 작성해줍니다.
// logger.jsimport pino from 'pino';
const logger = pino();
export const log = (msg) => logger.info(msg);
Plain Text
복사
다음으로 페이지 코드를 작성하는데, getServerSideProps의 에러를 잡아내기 위한 코드만 적었습니다.
// pages/index.jsimport { log } from '../next-pino/logger';
...
export const getServerSideProps = async () => {
try {
// 에러 강제 발생throw new Error('make error');
return {
props: {},
};
} catch (error) {
console.log('에러 로그를 찍습니다');
log(error);
return { props: {} };
}
};
Plain Text
복사
해당 페이지를 실행시키면 에러가 발생하고 서버에서 아래와 같이 출력됩니다.
로그를 간단히 살펴보면 아래와 같습니다.
•
level : trace : 10, debug: 20, info : 30, warn: 40, error: 50, fatal: 60으로 지정되어져있고 커스텀 가능합니다.
•
time : 에러가 기록된 시간입니다.
•
err : msg로 넣은 메시지가 들어가게 됩니다.
이를 통해서 getServerSideProps에서 발생하는 에러들을 출력시켰습니다.
Pino 환경 설정 커스텀
level에 따른 로그 저장이 다르다고 했는데, 아래와 같이 각자 저장하는 곳을 따로 가지고 있습니다.
// logger.jsimport pino from 'pino';
const traceLogger = pino();
const debugLogger = pino();
const infoLogger = pino();
const warnLogger = pino();
const errorLogger = pino();
const fatalLogger = pino();
export const traceLog = (msg) => traceLogger.trace(msg);
export const debugLog = (msg) => debugLogger.debug(msg);
export const infoLog = (msg) => infoLogger.info(msg);
export const warnLog = (msg) => warnLogger.warn(msg);
export const errorLog = (msg) => errorLogger.error(msg);
export const fatalLog = (msg) => fatalLogger.fatal(msg);
Plain Text
복사
단 아래와 같이 모든 trace와 debug의 경우 에러에서는 로그를 작성하지 않고 있는데 상황에 따라 저장되는 사항이 다릅니다. 참고
export const getServerSideProps = async () => {
try {
throw new Error('make error');
return {
props: {},
};
} catch (error) {
console.log('에러 로그를 찍습니다');
traceLog(error);
debugLog(error);
infoLog(error);
warnLog(error);
errorLog(error);
fatalLog(error);
return { props: {} };
}
};
Plain Text
복사
해당 결과는 이렇게 발생합니다. trace와 debug는 찍히지 않고, 보면 level이 30부터 시작하는 것을 알 수 있습니다.
시간 표현 변경
로그에 문제가 있는데 우선 time이 유닉스 시간으로 되어있다는 점입니다. 해당 표현은 가독성이 나빠 이를 수정해보려고 합니다. 참고
// logger.jsimport pino from 'pino';
/** custom time */const logger = pino({ timestamp: pino.stdTimeFunctions.isoTime });
export const infoTimeLogger = (msg) => logger.info(msg)
Plain Text
복사
// index.jsexport const getServerSideProps = async () => {
try {
throw new Error('make error');
return {
props: {},
};
} catch (error) {
console.log('에러 로그를 찍습니다');
infoTimeLogger(error);
return { props: {} };
}
};
Plain Text
복사
해당 코드를 실행하게 되면 아래와 같이 시간 표현 방식이 바뀝니다.
Pino-Pretty 적용
하지만 아직까지 데이터 표현방식의 가독성이 나쁩니다.
이를 위해서 pino-pretty를 사용할 예정인데 주의점이 있습니다.
1.
import 로 pino-pretty 라이브러리를 불러올 시 해당 파일은 nodejs에 맞게 되어있는 라이브러리라서 에러가 발생한다.
2.
transport를 이용하면 되는데 v7부터 생겼으므로 설치된 버전을 확인해야 합니다.
import pino from 'pino';
/** pino pretty */const log = pino(
{
timestamp: pino.stdTimeFunctions.isoTime,
transport: {
target: 'pino-pretty',
options: {
// colorize: true, // boolean// levelFirst: true, // level이 가장 앞으로 오도록 설정// ignore: 'pid,hostname', // 해당 형식 무시// destination: './log/info.log',
},
},
},
);
Plain Text
복사
export const getServerSideProps = async () => {
try {
throw new Error('make error')
return {
props: {},
};
} catch (error) {
console.log('에러 로그를 찍습니다');
prettyLog(error);
return { props: {} };
}
};
Plain Text
복사
이렇게 되면 아래와 같이 정리된 방식으로 출력이 됩니다.
파일에 로그 남기기
option에서 사용된 변수 중 destination은 파일에 로그를 저장하는데, 다른 방식으로도 호출할 수 있습니다.
단 경로의 경우 /는 c드라이브로 잡히게 되고 ./는 프로젝트의 루트가 잡히게 됩니다.
const logger = pino(pino.destination('./log/info.log'));
Plain Text
복사
로그 일괄 처리하기
아래 함수를 통해서 getServerSideProps를 받아서 로그를 동일하게 처리할 수 있습니다.
// logger.jsexport function withGetServerSideProps(getServerSideProps) {
return async (context) => {
try {
return await getServerSideProps(context);
} catch (error) {
log.info(error);
return {
props: {},
};
// throw error;
}
};
}
Plain Text
복사
// index.jsexport const getServerSideProps = withGetServerSideProps() => {
// 동작 작성return {
props: {
},
};
});
Plain Text
복사
위와 같이 함수를 작성해 줘서 로그 동작을 일괄로 처리 할 수 도있다.