일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- next13 head
- background setttimeout
- getUTCDate
- React 18
- background: url
- CSS
- Render Props
- background setInterval
- React 고급안내서
- react hook
- Next13
- react
- react-helmet
- Programmers
- background tab
- React 18 Nextjs
- React API 참고서
- Babel
- codingtest
- context
- Nextjs React 18
- 고급안내서
- React 공식문서
- Javascript
- notFound()
- React18
- React 고급 안내서
- hook
- RTK Query
- Nextjs
- Today
- Total
akjfal
nextjs와 pino를 이용한 로그 처리 및 로그 파일 저장 본문
Nextjs 공식 문서를 찾아보면, 로그에 관련되서 구조화된 로크 패키지를 원한다면 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"
}
}
Pino를 사용한 기본 로깅
우선 pino를 사용한 코드를 작성해줍니다.
// logger.js
import pino from 'pino';
const logger = pino();
export const log = (msg) => logger.info(msg);
다음으로 페이지 코드를 작성하는데, getServerSideProps의 에러를 잡아내기 위한 코드만 적었습니다.
// pages/index.js
import { 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: {} };
}
};
해당 페이지를 실행시키면 에러가 발생하고 서버에서 아래와 같이 출력됩니다.
로그를 간단히 살펴보면 아래와 같습니다.
- level : trace : 10, debug: 20, info : 30, warn: 40, error: 50, fatal: 60으로 지정되어져있고 커스텀 가능합니다.
- time : 에러가 기록된 시간입니다.
- err : msg로 넣은 메시지가 들어가게 됩니다.
이를 통해서 getServerSideProps에서 발생하는 에러들을 출력시켰습니다.
Pino 환경 설정 커스텀
level에 따른 로그 저장이 다르다고 했는데, 아래와 같이 각자 저장하는 곳을 따로 가지고 있습니다.
// logger.js
import 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);
단 아래와 같이 모든 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: {} };
}
};
해당 결과는 이렇게 발생합니다. trace와 debug는 찍히지 않고, 보면 level이 30부터 시작하는 것을 알 수 있습니다.
시간 표현 변경
로그에 문제가 있는데 우선 time이 유닉스 시간으로 되어있다는 점입니다. 해당 표현은 가독성이 나빠 이를 수정해보려고 합니다. 참고
// logger.js
import pino from 'pino';
/** custom time */
const logger = pino({ timestamp: pino.stdTimeFunctions.isoTime });
export const infoTimeLogger = (msg) => logger.info(msg)
// index.js
export const getServerSideProps = async () => {
try {
throw new Error('make error');
return {
props: {},
};
} catch (error) {
console.log('에러 로그를 찍습니다');
infoTimeLogger(error);
return { props: {} };
}
};
해당 코드를 실행하게 되면 아래와 같이 시간 표현 방식이 바뀝니다.
Pino-Pretty 적용
하지만 아직까지 데이터 표현방식의 가독성이 나쁩니다.
이를 위해서 pino-pretty를 사용할 예정인데 주의점이 있습니다.
- import 로 pino-pretty 라이브러리를 불러올 시 해당 파일은 nodejs에 맞게 되어있는 라이브러리라서 에러가 발생한다.
- 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',
},
},
},
);
export const getServerSideProps = async () => {
try {
throw new Error('make error')
return {
props: {},
};
} catch (error) {
console.log('에러 로그를 찍습니다');
prettyLog(error);
return { props: {} };
}
};
이렇게 되면 아래와 같이 정리된 방식으로 출력이 됩니다.
위에 transport에 있는 옵션들은 해당 페이지를 참고하면 됩니다.
파일에 로그 남기기
option에서 사용된 변수 중 destination은 파일에 로그를 저장하는데, 다른 방식으로도 호출할 수 있습니다.
단 경로의 경우 /는 c드라이브로 잡히게 되고 ./는 프로젝트의 루트가 잡히게 됩니다.
const logger = pino(pino.destination('./log/info.log'));
로그 일괄 처리하기
아래 함수를 통해서 getServerSideProps를 받아서 로그를 동일하게 처리할 수 있습니다.
// logger.js
export function withGetServerSideProps(getServerSideProps) {
return async (context) => {
try {
return await getServerSideProps(context);
} catch (error) {
log.info(error);
return {
props: {},
};
// throw error;
}
};
}
// index.js
export const getServerSideProps = withGetServerSideProps() => {
// 동작 작성
return {
props: {
},
};
});
위와 같이 함수를 작성해 줘서 로그 동작을 일괄로 처리 할 수 도있다.
'react' 카테고리의 다른 글
Next13을 사용하며(2023.08 ver) (1) | 2023.12.03 |
---|---|
프로젝트 웹사이트 최적화 (0) | 2021.07.29 |
Material-ui makeStyle float해제 or content가 제대로 적용 안되는 현상 (0) | 2021.07.28 |