종속성 주입과 함께 log4net을 사용하는 방법


78

나는 의존성 주입 프레임 워크에서 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);
    }
}

1
더 흥미로운 질문은 어떤 DI 컨테이너를 사용하고 계십니까?
CodeMonkeyKing 2011

답변:


61

여기 나무가있는 숲이 보이지 않는 것 같습니다. 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();

7
당신의 폭언은 여기서 멀리 떨어져 있습니다. 이 사람은 컨테이너 내부에있는 개체에 ILog 인스턴스를 주입하는 방법에 대해 질문했습니다. 그렇게하는 데는 여러 가지 이유가 있습니다.
CodeMonkeyKing 2011

1
@CodeMonkeyKing : 폭언은 log4net과 그의 코드 사이에 추상화 계층을 생성하는 그의 제안 된 접근 방식, 특히 질문 끝에있는 샘플 코드 블록에서 진행되었습니다.
Jeffrey Hantin 2011

4
@JeffreyHantin 귀하의 의견으로는 반 패턴 일 수 있지만 코드를 작성하는 엔지니어만큼 많은 의견이 있다는 것을 알게되었습니다. 물론 내 의견 :)
CodeMonkeyKing

1
나는 이것이 오래된 게시물이라는 것을 알고 있지만 왜 그런 래퍼가 "나쁜"지 설명해 주시겠습니까? ILog 및 LogManager는 log4net 네임 스페이스에 있으며, 코드 전체에서 이러한 유형을 사용함으로써 log4net에 연결되지 않습니까? 내가 여기서 무엇을 놓치고 있습니까?
Andrew Stephens

1
log4net을 래핑하는 것이 좋습니다. 문제는 라이브러리를 래핑하는 것이 아닙니다.
Dan

2

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


2

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

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


하지만 일반적으로 예외 이상을 기록하고 싶습니까?
UpTheCreek

여기서 싱글 톤 패턴을 제안하고 있습니까? 내가하지 희망.
Nate Zaugg 2013 년

2

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

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

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


생성되는 구현 클래스에 대한 올바른 로거를 얻을 때 이것이 더 잘 작동한다고 생각합니다.Component.For<ILog>().UsingFactoryMethod((kernel, model, cc) => LogManager.GetLogger(cc.Handler.ComponentModel.Implementation))
Mark
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.