Fallback Logger¶
Fox Logging은 주어진 이름의 로거를 찾을 수 없을 때 대체 로거를 반환하는 기능이 있습니다. 대체 로거는 FoxDummyLogger
클래스에 의해 구현되는 로거로서 매우 빠르게 모든 로그 메시지를 필터링합니다.
Scenario¶
일반적으로 어플리케이션을 개발할 때에는 발생되는 문제를 해결하기 위해 많은 로그를 남기곤 합니다. 이들 로그는 디버그 성격의 로그도 존재하며 어플리케이션의 작동을 추적하는 추적 성격의 로그도 존재합니다. 어플리케이션 개발이 완료되고 테스트 하는 과정에서도 이들 디버그 성격의 로그와 추적 성격의 로그들은 그대로 놔두고 발생되는 문제를 파악하기 위해 사용합니다.
개발/테스트가 완료되고 어플리케이션이 안정화 된 후에는 디버그 및 추적 성격의 로그는 어플리케이션의 성능과 관리 상의 문제를 유발할 수 있습니다. 불필요하게 많은 로그는 성능을 저하시킬 뿐만 아니라 파일에 로그를 남기는 경우 계속 생성되는 로그 파일을 처리해야 하기 때문입니다.
따라서 어플리케이션 안정화 이후에는 기존 로그의 양을 줄이거나 로그를 더 이상 남기 않도록 조정할 필요가 있습니다. 어떤 로깅 프레임워크를 사용하는 가에 따라 조금씩 다르지만 대부분의 경우 로그 필터링 수준을 높여서 로그가 기록되지 않도록 하거나 소스 코드에서 로그를 남기는 코드들 막는 것이 일반적입니다.
다음 코드는 개발 시 사용했던 추적 및 디버깅을 위해 로그를 기록하는 코드를 코멘트로 막아서 로그가 남지 않도록 하는 예를 보여 주고 있습니다.
어플리케이션이 안정화 되었다 할지라도 추후 기능 개선 등의 작업을 수행하면서 새로운 문제가 발생할 수도 있습니다. 이 때 추적 및 디버그 로그를 남겨야 한다면 어떻게 해야 할까요?
어쩔 수 없이 기존에 막아 두었던 로그 코드를 다시 활성화 시켜야 하며 이는 소스 코드 수정과 빌드 배포를 동반합니다. 또한 문제가 해결되었다면 다시 로그 코드를 막고 빌드와 배포를 해야 할 것입니다. 이러한 작업은 매우 번거로우며 불필요한 코드 수정, 빌드, 배포를 동반하게 됩니다.
Approach¶
Fox Logging 의 기본적인 접근 방법은 로그 관련 코드를 변경하지 않도록 하는 것입니다. 대신 로깅 구성 설정에서 로거를 제거하고 GetLogger
메서드가 구성 설정에 존재하지 않는 로거에 대해서 대체 로거(FoxDummyLogger
클래스)를 반환합니다. 대체 로거는 로그를 전혀 남기 않고 모든 로그를 빠르게 필터링 합니다.
Note
성능은 테스트 환경에 따라 다를 수 있지만 FoxDummyLogger
클래스는 7세대 인텔 i7 데스크톱 용 CPU 환경에서 대체 로거는 초당 50만개 이상의 로그를 필터링할 수 있습니다
어플리케이션을 개발하는 상황을 가정해 봅시다. 어플리케이션 개발 시에는 디버깅과 수행 추적을 위해 다양한 로그를 남겨야 할 수 있습니다. 따라서 다음과 같이 Verbose
필터 수준을 사용하여 로거 구성 설정을 사용하여 진단 로그를 남기도록 설정할 수 있습니다.
어플리케이션 코드는 GetLogger
메서드와 Verbose
, Information
메서드를 사용하여 추적, 디버깅 등 진단 로그를 남깁니다.
개발 및 테스트가 완료되면 어플리케이션을 배포해야 하지만 운영 중인 어플리케이션이 너무 많은 로그를 남기게 되면 성능 하락이 발생할 수도 있습니다. 따라서 구성 설정에서 로거를 제거하거나 로거의 이름을 사용하지 않는 로거 이름으로 바꿉니다. 이 경우 로거 이름을 FI.Closing
에서 Disabled
로 바꾸었습니다.
Tip
구성 설정에서 로거를 제거하는 것보다 이름을 바꾸는 것을 추천합니다. 추후에 필요한 경우 다시 로거를 활성화 할 수도 있기 때문입니다.
Note
구성 설정에서 로그 필터링 수준을 높여 발생 되는 로그의 양을 줄이는 방법도 있습니다. 하지만 이 예제는 대체 로거에 대한 설명을 위해 로거 이름을 바꾸는 것으로 설명할 것입니다.
로거 구성 설정만을 바꾸었을 뿐 어플리케이션 코드는 변경하지 않았음에 주목하십시요. 이제 어플리케이션 코드가 호출하는 GetLogger
메서드는 로거를 찾지 못할 것이기 때문에 대체 로거인 FoxDummyLogger
를 반환할 것이며 FoxDummyLogger
는 모든 로그를 빠르게 필터링할 것입니다. 이제 더 이상 로그는 기록되지 않으며 성능 저하도 발생하지 않을 것입니다.
어플리케이션 운영 과정에서 문제가 발생하여 로그가 필요하게 된다면 구성 설정에서 바꾸었던 로거의 이름을 원상 복구하면 됩니다. 즉, Disabled
라는 로거 이름을 다시 FI.Closing
으로 바꾸면 어플리케이션을 재시작하지 않고도 곧바로 로그는 다시 기록되기 시작합니다!
Warning
GetLogger
메서드를 호출하는 시점에서 구성 설정 변경을 감지하고 로거를 다시 생성함에 유의하십시요. 구성 설정 변경 전에 GetLogger
메서드를 호출하여 읽어 둔 로거에 대해서는 구성 설정 변경이 반영되지 않습니다.
FoxDummyLogger
and FoxDummyLoggerProvider
¶
대체 로거는 FoxDummyLogger
클래스에 의해 구현되며 이 클래스는 FoxLogManager 에 의해 필요할 때마다 GetLogger
메서드에서 반환될 수 있습니다. FoxLogManager
가 대체 로거로서 반환하는 FoxDummyLoger
인스턴스는 싱글톤 객체이며 FoxLogManager.FallbackLogger
속성을 통해 접근이 가능합니다.
어플리케이션은 필요에 따라 직접 FoxDummyLogger
를 사용할 수도 있습니다. FoxDummyLoggerProvider
클래스를 통해 구성 설정에 등록하거나 직접 FoxDummyLogger
인스턴스를 생성하여 FoxLogManager.RegisterLogger
메서드를 호출하여 등록하여 사용할 수도 있습니다.
UseFallbackLogger property¶
로깅 구성 설정의 "logging:useFallbackLogger
" 속성이나 FoxLogManager.UseFallbackLogger
속성을 사용하여 대체 로거의 사용 여부를 제어할 수 있습니다. 이 속성을 false
로 설정하면 FoxLogManager
는 더 이상 대체 로거를 사용하지 않습니다. FoxLogManager
가 요청된 이름의 로거를 찾지 못한 경우, GetLogger
메서드는 FoxInvalidConfigurationException
예외를 발생시킵니다.
일반적으로 UseFallbackLogger
속성의 값을 변경할 필요는 없습니다. 하지만 대체 로거로 인해 로깅 구성에서 발생하는 문제를 발견하기 어려울 때가 있습니다. 예를 들어 개발자가 실수로 로깅 구성 설정에서 로거의 이름에 오타가 발생한 경우, GetLogger
메서드는 예외를 발생하는 대신 대체 로거를 반우하기 때문에 개발자는 로그가 기록되지 않을 뿐 다른 어떤 징후도 발견하기 어렵습니다.
Important
사실 개발자는 오타를 잘 발견하지 못합니다!
이러한 상황에서 임시적으로 UseFallbackLogger
속성을 false
로 지정하면 곧바로 예외가 발생되므로 구성 설정 오타를 발견할 가능성을 높여줍니다.
Consideration¶
FoxDummyLogger
클래스는 매우 빠르게 로그 기록을 필터링 합니다. 다만 주의해야 할 사항이 있습니다. 모든 로깅 프레임워크가 그러하듯이 로그 메시지에 C# 문자열 보간(interpolation)을 사용하면 대체 로거의 로그 필터링 성능에 악 영향을 미칠 수 있습니다. 포멧팅이 필요한 로그 메시지를 기록할 때에는 C# 문자열 보간 대신 WriteFormat 메서드를 사용하십시요. FoxDummyLogger
는 불필요한 문자열 포맷팅을 수행하지 않고 로그 메시지를 필터링 할 것입니다. 상세한 예제는 WriteFormat 메서드 문서를 참고 하십시요.