[design-patterns] 종속성 주입과 함께 log4net을 사용하는 방법

나는 의존성 주입 프레임 워크에서 log4net의 올바른 패턴과 사용법을 알아 내려고 노력하고 있습니다.

Log4Net은 ILog 인터페이스를 사용하지만 전화를해야합니다.

LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)

정보를 기록해야하는 각 클래스 또는 메소드에서. 이것은 IoC 원칙에 위배되는 것으로 보이며 Log4Net을 사용하는 것과 연결됩니다.

어딘가에 다른 추상화 레이어를 넣어야할까요?

또한 다음과 같은 현재 사용자 이름과 같은 사용자 지정 속성을 기록해야합니다.

log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;

매번 기억할 필요가없고 로깅중인 현재 메서드를 유지 관리 할 수 ​​있도록 어떻게 캡슐화 할 수 있습니까? 이런 식으로해야합니까, 아니면 마크를 완전히 놓치고 있습니까?

public static class Logger
{
    public static void LogException(Type declaringType, string message, Exception ex)
    {
        log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
        ILog log = LogManager.GetLogger(declaringType);
        log.Error(message, ex);
    }
}



답변

여기 나무가있는 숲이 보이지 않는 것 같습니다. ILog 및 LogManager는 Apache commons-logging과 거의 1 : 1에 해당하는 경량 파사드이며 실제로 코드를 나머지 log4net에 연결하지 않습니다.

<rant>
또한 누군가가 log4net 주위에 MyCompanyLogger 래퍼를 만들면 거의 항상 요점을 잘못 놓치고 프레임 워크의 중요하고 유용한 기능을 잃고 유용한 정보를 버리고 단순화 된 ILog 인터페이스를 사용하여 가능한 성능 향상을 잃게됩니다. 또는 위의 모든 것. 즉, log4net과의 결합을 피하기 위해 래핑하는 것은 안티 패턴 입니다.
</rant>

주입 할 필요가 있다고 생각되면 속성을 통해 로거 인스턴스에 액세스하여 주입을 활성화하고 기본 인스턴스를 구식 방식으로 만듭니다.

모든 로그 메시지에 컨텍스트 상태를 포함 ToString()하려면 찾고있는 내용을 확인 하는 전역 속성을 추가해야 합니다. 예를 들어 현재 힙 크기의 경우 :

public class TotalMemoryProperty
{
    public override string ToString()
    {
        return GC.GetTotalMemory(false).ToString();
    }
}

그런 다음 시작 중에 연결하려면 :

GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty();


답변

내가 한 방법은 자체 인터페이스를 만들고 Log4Net을 사용하는 인터페이스를 구현하고 해당 클래스를 주입하는 클래스를 갖는 것이 었습니다. 그런 식으로 Log4Net에 묶여 있지 않습니다. 새 로거에 대한 다른 클래스를 만들고 해당 클래스를 삽입 할 수 있습니다.


답변

로거가 여러 개있는 것이 정말로 걱정된다면 항상 전역 로거를 선언하고 모든 로깅 요구에 대해 호출 할 수 있습니다. 이것의 단점은 로그가 발행 된 클래스를 식별하는 내장 된 기능을 잃는다는 것입니다. 그러나 사용자 정의 메시지를 로그에 삽입하여 클래스를 식별 할 수도 있습니다.

얼마나 강력한 로깅을 원하는지에 따라 다릅니다. 로거를 메인 클래스에 놓고 처리되지 않은 모든 예외가 로깅을 위해 버블 링되도록 할 수도 있습니다.


답변

이를 수행하는 또 다른 방법은 log4net ILog 인터페이스 컨테이너 등록 시퀀스를 다음과 같이 연결하는 것입니다. (아래의 ASP.NET 컨텍스트에서 Castle을 예로 사용)

container.Register(Component.For<ILog>().LifeStyle
    .PerWebRequest.UsingFactoryMethod(() => LogManager.GetLogger(
    MethodBase.GetCurrentMethod().DeclaringType)));

필요할 때마다 ILog를 생성자 주입합니다.


답변