feat: STOMP 에러 로그 구조화#145
Conversation
📝 WalkthroughWalkthroughSTOMP 오류 로깅과 MDC traceId 보존 흐름을 정리하고, ChangesSTOMP 에러 로깅 정리
Sequence Diagram(s)MDC traceId 흐름sequenceDiagram
participant MdcStompInterceptor
participant MessageChannel
participant MDC
MdcStompInterceptor->>MDC: put(traceId) in preSend
MdcStompInterceptor->>MessageChannel: return message with traceId header
MessageChannel->>MdcStompInterceptor: afterSendCompletion(sent, ex)
MdcStompInterceptor->>MDC: remove(traceId)
STOMP 오류 처리 흐름sequenceDiagram
participant StompProtocolErrorHandler
participant StompLogContext
participant StompSubProtocolErrorHandler
StompProtocolErrorHandler->>StompLogContext: from(clientMessage)
StompProtocolErrorHandler->>StompProtocolErrorHandler: log.warn/log.error with context
StompProtocolErrorHandler->>StompSubProtocolErrorHandler: handleClientMessageProcessingError(...)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/test/java/com/howaboutus/backend/common/logging/StompSubProtocolHandlerErrorLogFilterTest.java (1)
54-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMockito 사용 방식이 코딩 지침과 어긋납니다.
Logger목을mock(Logger.class)로 직접 생성하는 대신@ExtendWith(MockitoExtension.class)와@Mock사용이 권장됩니다. 다만 테스트마다 다른 로거 이름이 필요하므로@Mock Logger logger;선언 후 각 테스트에서given(logger.getName()).willReturn(...)로 스텁하는 형태가 적합합니다.As per coding guidelines: "In unit tests using Mockito, prefer
@ExtendWith(MockitoExtension.class)with@Mock/@InjectMocksover directMockito.mock(...)creation".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/com/howaboutus/backend/common/logging/StompSubProtocolHandlerErrorLogFilterTest.java` around lines 54 - 58, The test helper currently creates the Logger with direct Mockito mocking, which violates the Mockito usage guideline. Update StompSubProtocolHandlerErrorLogFilterTest to use MockitoExtension with a class-level `@Mock` Logger instead of mock(Logger.class), and keep the per-test logger name customization by stubbing logger.getName() inside each test or setup. Preserve the existing logger(String name) helper behavior by adapting it to work with the injected mock rather than constructing a new one.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@src/test/java/com/howaboutus/backend/common/logging/StompSubProtocolHandlerErrorLogFilterTest.java`:
- Around line 54-58: The test helper currently creates the Logger with direct
Mockito mocking, which violates the Mockito usage guideline. Update
StompSubProtocolHandlerErrorLogFilterTest to use MockitoExtension with a
class-level `@Mock` Logger instead of mock(Logger.class), and keep the per-test
logger name customization by stubbing logger.getName() inside each test or
setup. Preserve the existing logger(String name) helper behavior by adapting it
to work with the injected mock rather than constructing a new one.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: abb9d44b-77c4-430d-9792-f5a7af40dbe7
📒 Files selected for processing (14)
docs/ai/decisions/20260626-1443-stomp-error-logging.mddocs/superpowers/plans/2026-06-26-stomp-error-logging.mddocs/superpowers/specs/2026-06-26-stomp-error-logging-design.mdsrc/main/java/com/howaboutus/backend/common/filter/MdcStompInterceptor.javasrc/main/java/com/howaboutus/backend/common/logging/StompSubProtocolHandlerErrorLogFilter.javasrc/main/java/com/howaboutus/backend/realtime/config/StompLogContext.javasrc/main/java/com/howaboutus/backend/realtime/config/StompProtocolErrorHandler.javasrc/main/java/com/howaboutus/backend/realtime/config/WebSocketConfig.javasrc/main/resources/logback-spring.xmlsrc/test/java/com/howaboutus/backend/common/filter/MdcStompInterceptorTest.javasrc/test/java/com/howaboutus/backend/common/logging/StompSubProtocolHandlerErrorLogFilterTest.javasrc/test/java/com/howaboutus/backend/realtime/config/StompLogContextTest.javasrc/test/java/com/howaboutus/backend/realtime/config/StompProtocolErrorHandlerTest.javasrc/test/java/com/howaboutus/backend/realtime/config/WebSocketConfigTest.java



문제 상황
기존 STOMP 에러 로그는 Spring 내부
StompSubProtocolHandler가 다음과 같은 형태로만 기록하고 있었습니다.이 로그만으로는 실제 예외가 인증 실패인지, 토큰 만료인지, 방 접근 권한 문제인지, 서버 내부 오류인지 구분하기 어려웠습니다.
또한 다음과 같은 진단 정보가 부족했습니다.
특히 기존
MdcStompInterceptor는beforeHandle시점에 traceId를 설정하고 있어, 그보다 먼저 실행되는 인증·권한 인터셉터의preSend단계에서 예외가 발생하면 traceId가 로그에 포함되지 않는 문제가 있었습니다.이외에도 운영 로그 설정에서 다음 문제를 확인했습니다.
@version,level_value,tags등 현재 운영에서 사용하지 않는 필드가 포함됨변경 내용
StompProtocolErrorHandler에서 공통 처리하도록 추가했습니다.CustomException은 WARN으로 기록errorCode,stompCommand,destination,sessionId,userId,traceId를 구조화 필드로 기록MdcStompInterceptor의 traceId 설정 시점을beforeHandle에서preSend로 앞당겼습니다.logback-spring.xml설정을 정리했습니다.@version,level_value,tags등 불필요한 필드 제거변경 이유
기존 구조에서는 STOMP 예외가 모두 동일한 Spring ERROR 로그로 기록되어 운영 중 장애 원인을 빠르게 구분하기 어려웠습니다.
이번 변경을 통해 사용자 요청으로 발생하는 예상 가능한 오류와 실제 서버 장애를 로그 레벨과 stack trace 포함 여부로 분리하고, STOMP 요청 컨텍스트를 구조화해 운영 로그의 검색성과 추적성을 높이고자 했습니다.
또한 traceId를 메시지 처리 초기 단계부터 유지해 인증·권한 검사 과정에서 발생한 예외도 동일한 요청 흐름으로 추적할 수 있도록 개선했습니다.
테스트
./gradlew build/review-code-against-docs스킬로 검증./gradlew checkstyleMain checkstyleTest,/checking-md-conflicts스킬로 Markdown 참조/중복 규칙/충돌 점검
체크리스트
하네스 변경 체크리스트
Summary by CodeRabbit
New Features
Bug Fixes