로그가 서비스를 죽였다
백엔드
로그가 서비스를 죽였다
두줄요약
동기 stdout 로깅이 커넥션 풀 고갈과 요청 실패로 이어진 원인을 분석했습니다. caller에서 추적 ID를 캡처해 비동기 로깅과 관측성을 함께 유지했습니다.
문제 상황
- DEBUG 로그 급증으로 stdout 파이프 버퍼 포화와 요청 스레드 write 대기
- DB 커넥션 반환 지연에 따른 HikariCP 풀 고갈과 30초 주기 요청 실패
원인 분석
- 동기 Logback 출력의 락 직렬화와 stdout 소비 처리량 병목
- AsyncAppender 워커 스레드에서 OpenTelemetry ThreadLocal 컨텍스트 접근 불가
- trace_id 누락 방지를 위한 비동기 로깅 금지 정책의 가용성 위험
해결 방법
- caller 스레드의 append()에서 trace_id·span_id를 캡처하는 TraceAwareAsyncAppender
- ILoggingEvent 래퍼에 ID를 저장하고 표준 AsyncAppender의 큐·워커 구조 재사용
- neverBlock=true 기반 큐 포화 시 로그 드롭으로 요청 스레드 대기 방지
성능/운영 포인트
- 극한 부하에서 로그 드롭 조건에도 출력 로그의 trace_id 결측 0% 확인
- 초당 로그량 1만 5천 줄 조건에서 p95 29ms 유지
- 지속 과부하 대응을 위한 로그 발생량 관리 필요


