-
Notifications
You must be signed in to change notification settings - Fork 8
요청, 응답 로그에 correlationId 를 추가하자!
Caution
요청/응답 로그에 correlationId
가 찍히지 않는 문제가 발생
현재 우리는 로그들을 하나의 요청으로 그룹화 하기 위해 로그들에 correlationId
를 함께 출력 중이다.
그런데 HTTP 요청 / 응답 정보를 출력하는 로그들에서 correlationId
이 출력되지 않고 있었다.
- 에러 로그에는
correlationId
가 잘 나오지만[Request]
/[Response]
로그에는 값이 비어있는 모습이다.
현재 correlationId
는 MDCFilter
클래스에서 생성해 주고 있다.
우선, 이 값이 잘 생성되고 있는지 correlationId
의 생존주기를 확인하고 있다.
@Slf4j
@Component
public class MDCFilter implements Filter {
private final String CORRELATION_ID = "correlationId";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String correlationId = generateCorrelationId();
log.info("USE {} : {}", CORRELATION_ID, correlationId); // correlationId 생성 확인
MDC.put(CORRELATION_ID, correlationId);
chain.doFilter(request, response);
log.info("END {} : {}", CORRELATION_ID, correlationId); // correlationId 삭제 확인
MDC.clear();
}
//...
}
- 출력 확인
[INFO][08-21 14:04:43][ ][c.g.logger.MDCFilter] USE correlationId : 45c20ce6
[INFO][08-21 14:04:43][45c20ce6][c.g.e.GlobalExceptionHandler] [CodeZapException] codezap.global.exception.CodeZapException가 발생했습니다.
codezap.global.exception.CodeZapException: 쿠키가 없어서 회원 정보를 찾을 수 없습니다. 다시 로그인해주세요.
at
//...
at java.base/java.lang.Thread.run(Thread.java:842)
[INFO][08-21 14:04:43][45c20ce6][c.g.logger.MDCFilter] END correlationId : 45c20ce6
[INFO][08-21 14:04:43][ ][c.g.l.RequestResponseLogger] [Request] GET /templates, 헤더 값: content-type : application/json
//...
요청 바디:
[INFO][08-21 14:04:43][ ][c.g.l.RequestResponseLogger] [Response] Status: 401, Duration: 62ms, 헤더 값: Vary : Origin
//...
Caution
correlationId
생성 주기 확인
정상적으로 correlationId
가 잘 생성되는 것을 확인하였다.
그런데, 요청 / 응답 내용을 출력하는 순간이 correlationId
삭제 이후이다.
correlationId
를 생성하는 MDCFilter
보다 요청 / 응답 로그를 출력하는 RequestResponseLogger
가 더 먼저 실행되는 것이 문제였다.
Tip
분명 로컬에서는 정상적으로 correlationId
가 보였는데, 뭐가 다른거죠?!
서버에서 사용하는 파일은 gradle bootJar
로 jar 파일을 생성 후 java -jar XXX
로 서버를 실행하고 있다.
이와 똑같이 gradle bootJar
를 사용해 jar 파일을 생성 후 터미널에서 java -jar XXX
를 실행하면 로컬에서도 똑같은 문제가 발생함을 확인할 수 있다.
결국 bootJar
와 단순 인텔리제이 실행은 무언가 다르다는 건데...
뭐가 다른지는 아직 몰라용~~ :ㅇ
더 확실히 하기 위해 RequestResponseLogger
에도 로그를 찍어 보자.
@Slf4j
@Component
public class RequestResponseLogger extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//...
log.info("REQUEST / RESPONSE LOG START");
filterChain.doFilter(requestWrapper, responseWrapper);
log.info("REQUEST / RESPONSE LOG END");
//...
log.info("[Request] {} {}, 헤더 값: {} \n 요청 바디: {}", request.getMethod(), request.getRequestURI(),
getHeaderAndValue(requestWrapper), getBodyAsUtf8String(requestWrapper.getContentAsByteArray()));
log.info("[Response] Status: {}, Duration: {}ms, 헤더 값: {} \n 응답 바디: {}", response.getStatus(), duration,
getHeaderAndValue(responseWrapper), getBodyAsUtf8String(responseWrapper.getContentAsByteArray()));
responseWrapper.copyBodyToResponse();
//...
}
}
요청을 보내면 다음과 같은 로그가 찍힌다.
[INFO][08-21 14:04:43][ ][c.g.l.RequestResponseLogger] REQUEST / RESPONSE LOG START
[INFO][08-21 14:04:43][ ][c.g.logger.MDCFilter] USE correlationId : 45c20ce6
[INFO][08-21 14:04:43][45c20ce6][c.g.e.GlobalExceptionHandler] [CodeZapException] codezap.global.exception.CodeZapException가 발생했습니다.
codezap.global.exception.CodeZapException: 쿠키가 없어서 회원 정보를 찾을 수 없습니다. 다시 로그인해주세요.
at
//...
at java.base/java.lang.Thread.run(Thread.java:842)
[INFO][08-21 14:04:43][45c20ce6][c.g.logger.MDCFilter] END correlationId : 45c20ce6
[INFO][08-21 14:04:43][ ][c.g.l.RequestResponseLogger] REQUEST / RESPONSE LOG END
[INFO][08-21 14:04:43][ ][c.g.l.RequestResponseLogger] [Request] GET /templates, 헤더 값: content-type : application/json
//...
문제 정의가 확실해 졌으니, 필터의 순서를 변경하자.
필터 순서는 @Order
어노테이션을 사용해 손쉽게 지정해 줄 수 있다.
우리는 correlationId
를 먼저 생성 후 요청 / 응답 로그를 출력해야 하므로 MDCFilter
에는 @Order(1)
을, RequestResponseLogger
에는 @Order(2)
를 사용해 순서를 지정해 주었다.
[INFO][08-21 14:34:57][ ][c.g.logger.MDCFilter] USE correlationId : bf3a04e2
[INFO][08-21 14:34:57][bf3a04e2][c.g.l.RequestResponseLogger] REQUEST / RESPONSE LOG START
[INFO][08-21 14:34:57][bf3a04e2][c.g.e.GlobalExceptionHandler] [CodeZapException] codezap.global.exception.CodeZapException가 발생했습니다.
codezap.global.exception.CodeZapException: 쿠키가 없어서 회원 정보를 찾을 수 없습니다. 다시 로그인해주세요.
at codezap.auth.manager.CookieCredentialManager.checkCookieExist(CookieCredentialManager.java:32)
//...
at java.base/java.lang.Thread.run(Thread.java:842)
[INFO][08-21 14:34:57][bf3a04e2][c.g.l.RequestResponseLogger] REQUEST / RESPONSE LOG END
[INFO][08-21 14:34:57][bf3a04e2][c.g.l.RequestResponseLogger] [Request] GET /templates, 헤더 값: content-type : application/json
//...
요청 바디:
[INFO][08-21 14:34:57][bf3a04e2][c.g.l.RequestResponseLogger] [Response] Status: 401, Duration: 49ms, 헤더 값: Vary : Origin
//...
[INFO][08-21 14:34:57][bf3a04e2][c.g.logger.MDCFilter] END correlationId : bf3a04e2
설정이 잘 된다!
- 백엔드 코드 컨벤션
- 백엔드 기술 스택 및 선정 이유
- 각종 인스턴스 설정 파일 및 구성 위치 가이드
- 1.1.2 버전 ERD (24.09.27)
- 백엔드 CI CD 동작 프로세스
- 로컬 DB 환경 설정
- 백엔드 로깅 전략
- 백엔드 로그 모니터링 구성도
- 스프링 메트릭 모니터링 구성도
- Flyway 로 스키마 관리
- 코드잽 서버 구성도
- Git Submodule 사용 메뉴얼
- 프론트엔드 코드 컨벤션
- 프론트엔드 기술 스택 및 선정 이유
- 프론트엔드 서비스 타겟 환경 및 브라우저 지원 범위 선정
- 프론트엔드 모니터링 및 디버깅 환경 구축
- 프론트엔드 테스트 목록
- 프론트엔드 라이브러리 기술 검토
- 프론트엔드 개발서버, 운영서버 빌드 및 배포 환경 구분
- 목표했던 타겟 환경과 디바이스에서 서비스 핵심 기능 동작 확인
- 프론트엔드 접근성 개선 보고서
- EC2 로그 확인 방법
- VSCode를 통한 EC2 인스턴스 SSH 연결 방법
- 터미널을 통한 EC2 인스턴스 SSH 연결 방법
- NGINX 설정 파일 접근 및 적용 방법
- DB 접속 및 백업 방법
- [QA] 배포 전 체크리스트
- CI 파이프라인 구축
- CD 파이프라인 구축
- 백엔드 CI CD 트러블슈팅
- Lombok Annotation Processor 의존성을 추가한 이유
- 2차 스프린트 기준 ERD
- DTO 검증하기
- ProblemDetail
- Fork된 레포지토리 PR에서 CI Secrets 접근 문제 해결
- AWS CloudWatch 모니터링
- 스프링 메트릭 모니터링 구축 방법
- 로깅과 Logback에 대해 알아보아요.
- 백엔드 CD 파이프라인 Ver.2
- 요청, 응답 로그에 correlationId 를 추가하자!
- 3차 스프린트 기준 ERD
- 더미데이터 생성하고 실행하기
- 쿼리 성능 개선 결과
- 테이블별 인덱스 설정 목록
- 사용자 증가 시 발생할 수 있는 문제 상황과 개선 방안
- k6를 사용한 서버 부하 테스트
- 6차 스프린트 기준 ERD
- Query Performance Improvement Results
- 테스트 전략 및 CI 설정
- CI CD 구조
- 배포 전, 로컬에서 로그인 기능 포함 테스트해보는 법
- stylelint 적용기
- 내 작업 브랜치 중간에 Merge된 동료의 작업물을 넣고 싶다면 pull vs rebase
- [TS] Webpack config
- [TS] Webpack 환경에서 MSW v2 이슈
- [TS] webpack에서 react‐router‐dom 적용 안됨
- 2024.07.28 새 기획 회의
- 2024.07.26 2차 데모데이 후 회의
- 2024.07.11 백엔드 논의 좀 할게요
- 2024.07.11 백엔드 ERD 회의
- 2024.07.09 깃 브랜치 전략, PR 템플릿 회의
- 2024.07.03 주제 선정 회의
- 2023.07.03 팀빌딩데이 킥오프 회의
- 2023.08.07 3차 스프린트 중간회고