fix: MDC 복사가 종료 신호를 건너뛰어 다음 시퀀스가 이전 Context 로 로그를 남기는 문제 수정 - #372
Open
wantaekchoi wants to merge 1 commit into
Open
fix: MDC 복사가 종료 신호를 건너뛰어 다음 시퀀스가 이전 Context 로 로그를 남기는 문제 수정#372wantaekchoi wants to merge 1 commit into
wantaekchoi wants to merge 1 commit into
Conversation
EgovSubscriber 는 onNext 에서만 copyToMdc 를 부른다. copyToMdc 는 Context 가 비어 있으면 MDC.clear() 까지 해서 MDC 를 현재 Context 와 맞추는데, onComplete 와 onError 는 이 호출을 거치지 않는다. Reactor 스케줄러 스레드는 재사용된다. publishOn 으로 하류가 다른 스레드로 넘어가면 상류 절반이 돌던 스레드에는 그 시퀀스의 Context 값이 MDC 에 그대로 남는다. 같은 스레드에서 다음 시퀀스가 값 없이 완료되거나 에러로 끝나면 onNext 가 한 번도 불리지 않아, 자기 Context 를 두고도 앞 시퀀스의 값으로 종료 콜백의 로그가 찍힌다. 클래스 Javadoc 은 "스레드의 변경이 있을 때마다 Context의 값을 MDC에 삽입" 이라고 적어 신호 종류를 가리지 않는다. onNext 와 같은 자리에서 두 종료 신호도 copyToMdc 를 거치게 했다. 미수정 상태에서 실패하는 케이스 2건을 더했다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
수정 사유 Reason for modification
수정된 소스 내용 Modified source
EgovMdcContextConfig.EgovSubscriber는onNext에서만copyToMdc(coreSubscriber.currentContext())를 부릅니다. 종료 신호인onError와onComplete는 그대로 위임합니다."MDC 는 현재 Context 와 일치해야 한다" 는 규칙은 이 클래스가 스스로 세운 것입니다.
copyToMdc는 Context 가 비어 있으면MDC.clear()까지 합니다. 클래스 Javadoc 도 "스레드의 변경이 있을 때마다 Context의 값을 MDC에 삽입" 이라고만 적어 신호 종류를 가리지 않습니다.@PostConstruct contextOperatorHook()이Hooks.onEachOperator로 전역 등록하므로 이 빈이 뜬 뒤 만들어지는 모든 Mono/Flux 가EgovSubscriber로 감싸집니다.Reactor 스케줄러 스레드는 재사용됩니다.
publishOn으로 하류가 다른 스레드로 넘어가면 상류 절반이 돌던 스레드에는 그 시퀀스의 Context 값이 MDC 에 남습니다. 같은 스레드에서 다음 시퀀스가 값 없이 완료되거나 에러로 끝나면onNext가 한 번도 불리지 않아, 자기 Context 를 두고도 종료 콜백(doOnTerminate·doFinally·에러 핸들러)의 로그가 앞 시퀀스의 값으로 찍힙니다. WebFilter 로 traceId·userId 를 Context 에 넣는 구성이라면 다른 요청의 식별자가 로그에 섞입니다.AS-IS / TO-BE
onNext와 같은 자리에서 두 종료 신호도copyToMdc를 거치게 했습니다.@Override public void onError(Throwable throwable) { + copyToMdc(coreSubscriber.currentContext()); coreSubscriber.onError(throwable); } @Override public void onComplete() { + copyToMdc(coreSubscriber.currentContext()); coreSubscriber.onComplete(); }영향 범위
값이 흐르는 시퀀스의 MDC 최종 상태는 그대로입니다. 마지막
onNext와 같은 Context 를 한 번 더 쓰기 때문입니다. 종료 신호는 시퀀스당 한 번이라 늘어나는 호출도 시퀀스당 한 번입니다.같은 이너클래스의
onSubscribe(:101)도copyToMdc를 거치지 않아doOnSubscribe콜백은 여전히 앞 시퀀스의 값을 볼 수 있습니다. 구독 신호는 호출 스레드의 MDC 까지 덮게 되는 범위라 판단이 갈려 이번에는 종료 신호만 맞췄습니다.시퀀스가 끝난 뒤 스레드에 MDC 가 남는 것 자체는 이 수정으로 달라지지 않습니다. 그 자리의 Context 는 실제로 그 값이라 이 클래스의 규칙에 어긋나지 않고, 언제나 지우려면 다른 설계가 필요해 이 PR 범위 밖으로 두었습니다.
JUnit 테스트 JUnit tests
EgovMdcContextConfigTest2건을 더했습니다. 공개 진입점인contextOperatorHook()·cleanupHook()만 쓰고,newSingle스케줄러 두 개로 상·하류를 갈라 스레드 재사용을 결정론적으로 만듭니다. 두 번째 시퀀스의 Context 는userId=B인데 종료 콜백이 읽은 MDC 는userId=A입니다.수정 두 줄을 도로 빼면 실패합니다.
수정 후 모듈 전체입니다.
테스트 브라우저 Test Browser
테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video
화면이 없는 실행환경 모듈이라 첨부하지 않았습니다.