## 에러는 보이는데 원인이 안 보였다
요청, 응답 로그는 잘 찍히는데 서로 엮이지 않았다.
400이 났다는 건 보이는데,
어떤 요청의 결과인지 바로 연결되지 않았다.
## 눈으로는 구분이 안 됐다
로그는 이런 식이었다.
(이해를 돕기 위해 예제에서는 요청(Request)과 응답(Response) 로그만 사용했습니다.
실제 서비스 환경에서는 이 외에도 인증 정보, 파라미터, 내부 처리 과정, 외부 API 호출 등 다양한 로그를 함께 기록합니다.)
- Before Request
- Before Request
- After Request status = 500
- Before Request
- After Request status = 200
- After Request status = 400
어떤 요청이 어떤 응답을 주는지 한 눈에 들어오지 않는다.
사람이 눈으로 따라가기엔 무리였다.
## 기준을 하나 만들기로 했다
요청 단위로 로그를 묶을 수 있어야 했다.
식별 가능한 키가 필요했다.
요청이 시작될 때 하나 만들고,
끝날 때까지 같이 가는 값.
이 조건에 딱 맞는 게 MDC였다.
## MDC를 적용한 뒤
요청마다 UUID 하나를 붙였다.
로그에 항상 같이 찍히게 했다.
그 뒤 로그는 이렇게 바뀌었다.
- [uuid_1] Before ...
- [uuid_2] Before ...
- [uuid_1] After status = 500
- [uuid_3] Before ...
- [uuid_2] After status = 200
- [uuid_3] After status = 400
400 에러를 보면 uuid 하나만 따라가면 됐다.
앞뒤 로그가 바로 연결됐다.
이제 어떤 요청에 대해 로그를 추적하려면 uuid기준으로 검색하면 쉽게 추적할 수 있게 되었다.
## 적용은 필터에서 했다
요청 시작 지점이 명확해야 했다.
그래서 필터를 선택했다.
요청이 들어오면 UUID를 만들고,
MDC에 넣는다.
요청이 끝나면 제거한다.
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class MDCFilter : OncePerRequestFilter() {
companion object {
const val MDC_REQUEST_ID_KEY = "requestId"
}
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {
val requestId = UUID.randomUUID().toString().replace("-", "")
MDC.put(MDC_REQUEST_ID_KEY, requestId)
try {
filterChain.doFilter(request, response)
} finally {
MDC.remove(MDC_REQUEST_ID_KEY)
}
}
}
# application.yml
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - [%X{requestId:-startup}] %msg%n"'개발 > Spring Boot' 카테고리의 다른 글
| Spring 테스트할 때 @Transactional 써야 할까 말아야 할까 (0) | 2023.07.30 |
|---|---|
| JPA 복합키 @IdClass vs @EmbeddedId (0) | 2023.07.24 |