PARA/03_Resources/R001_개발_레퍼런스(참고문서)/트러블슈팅/260507 로그분석.md

260507 로그분석

404 WARN 분석 정리

현상

Datadog에 아래 WARN 로그가 반복적으로 찍힘.

http not found. msg=No static resource .

발생 서비스는 xxx-MP.xxx-card, 환경은 xxx-stage임.

원인 분석

처음엔 애플리케이션 로그에 요청 URI, User-Agent, client IP가 안 남아서 어떤 요청이 404를 만든 건지 파악이 어려웠음.

Datadog APM trace 까보니 실제 요청은 이랬음.

GET http://xxx.xxx.xxx.xxx:8080/
User-Agent: ELB-HealthChecker/2.0
Status: 404
Handler: ResourceHttpRequestHandler.handleRequest
Error: NoResourceFoundException: No static resource .

즉 해당 서비스 내부 API가 터진 게 아니라, ELB Health Check가 / 경로로 때리고 있었고 현재 서비스엔 / 매핑이나 정적 index.html이 없어서 Spring 정적 리소스 핸들러에서 404가 떨어진 것임.

결론

이번 WARN은 비즈니스 장애가 아니라 ELB Health Check path 설정이랑 애플리케이션 라우팅이 안 맞아서 반복적으로 찍히는 404 로그임.

ELB HealthChecker
→ GET /
→ 서비스에 / 매핑 없음
→ Spring ResourceHttpRequestHandler에서 정적 리소스 조회
→ NoResourceFoundException
→ DefaultExceptionHandler에서 WARN 출력

조치 방향

현재 프로젝트에 spring-boot-starter-actuator가 들어가 있으니까, ELB Health Check path는 아래 경로로 바꾸는 게 맞음.

/actuator/health

권장 설정:

Health check path: /actuator/health
Port: 8080
Success codes: 200

추가로 인터셉터 예외 경로에 /actuator/**도 넣어두는 게 좋음.

/actuator
/actuator/**

로그 보강

재발했을 때 Datadog APM trace 안 까봐도 원인을 바로 알 수 있게 404 로그에 요청 정보를 추가해둠.

추가한 필드:

request_method
request_uri
query_string
user_agent
client_ip

변경 후 로그 예시:

http not found. request_method=GET, request_uri=/, query_string=null, user_agent=ELB-HealthChecker/2.0, client_ip=..., msg=No static resource .

몰랐던 것

  • Spring Boot 3/Spring 6에선 매핑 안 된 요청이 정적 리소스 핸들러로 넘어가서 NoResourceFoundException으로 처리될 수 있음.
  • No static resource .처럼 경로가 비어 보이는 메시지는 / 루트 요청일 가능성이 큼.
  • 애플리케이션 로그에 URI가 없어도 Datadog APM trace span엔 http.url, http.method, user-agent 정보가 남아있을 수 있음.
  • ELB-HealthChecker/2.0 User-Agent 보면 ALB/ELB Health Check 요청인 거 식별 가능함.
  • 헬스체크도 애플리케이션 입장에선 그냥 HTTP 요청이라 path 잘못 부르면 정상적으로 404 떨어짐.

배운 점

  • 로그 메시지만 보고 애플리케이션 장애라고 단정하면 안 되고, trace/span까지 같이 봐야 정확한 원인이 보임.
  • 404 로그 분석엔 최소한 method, uri, user-agent, client_ip는 있어야 함.
  • Health Check path는 단순히 "응답 오는 URL"이 아니라 서비스 상태를 표현할 수 있는 경로여야 함.
  • /는 화면 서비스나 루트 매핑 없는 API/BFF 서비스에선 헬스체크 경로로 안 맞을 수 있음.
  • Actuator 들어간 Spring Boot 서비스라면 /actuator/health가 제일 표준적인 후보임.

향후 해봐야 할 것

  • ELB Target Group Health Check path를 /에서 /actuator/health로 변경
  • 변경 전후로 /actuator/health가 200 떨어지는지 확인
  • 인터셉터 예외 경로에 /actuator/** 추가 검토
  • 운영/스테이지 환경의 readinessProbe, livenessProbe, ALB health check path를 서비스별로 점검
  • 404, 405 같은 공통 예외 로그에 요청 식별 정보 기본 포함되게 다른 서비스에도 같은 패턴 적용 검토
  • Datadog dashboard에서 user_agent=ELB-HealthChecker/2.0이면서 status_code=404인 서비스들 찾아서 비슷한 설정 오류 있는지 확인

확장적으로 생각해볼 점

  • 헬스체크를 "서버 프로세스 떠 있음"만 볼지, "서비스가 실제로 처리 가능한 상태"까지 볼지 기준을 정해야 함.
  • /actuator/health에 Redis, 외부 API, DB 같은 dependency 상태를 넣으면 일시적인 외부 장애가 바로 ELB unhealthy로 이어질 수 있음. 어떤 dependency를 readiness에 포함할지 정책이 필요함.
  • 모든 서비스의 Health Check path를 표준화하면 운영 중 쓸데없는 404 로그랑 헬스체크 오탐을 줄일 수 있음.
  • 로그 보강은 그냥 디버깅 편하자고 하는 게 아니라 장애 대응 시간을 줄이는 운영 품질 개선임.
  • APM trace, access log, application log가 서로 연결돼야 "누가, 어떤 경로로, 왜 실패했는지"를 빠르게 설명할 수 있음.

댓글

첫 번째 댓글을 남겨보세요.