Prawidłowy sposób korzystania z log4net (nazewnictwo loggera)


83

Istnieją dwa sposoby konfigurowania i używania log4net. Pierwsza to sytuacja, w której mogę skonfigurować własny appender i powiązany logger:

<!-- language: xml -->

<appender name="myLogAppender" type="log4net.Appender.RollingFileAppender" >
    <file value="Logs\myLog.log" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %level - %message%n" />
    </layout>
</appender>

<logger name="myLog">
    <level value="All"></level>
    <appender-ref ref="myLogAppender" />
</logger>

A kiedy chcę coś zapisać w logu, mogę wykonać następujące czynności:

ILog log = LogManager.GetLogger("myLog");
log.Info("message");

Innym sposobem na użycie tego jest skonfigurowanie roota tak, aby był tak szczegółowy, jak chcę:

<!-- language: xml -->

<root>
    <level value="Error" />
    <appender-ref ref="myLogAppender" />
</root>

W tym przypadku mogę rejestrować takie komunikaty:

ILog log = LogManager.GetLogger(typeof(Bar));
log.Info("message");

Zaletą drugiego podejścia jest to, że możesz włączyć lub wyłączyć niektóre wiadomości w locie. Ale problem polega na tym, że rozwijam się w EPiServer CMS i ma własny system logowania, który używa log4net i jeśli włączę rejestrowanie informacji na poziomie roota, zostanie zapisanych wiele dzienników systemowych.

Jak używasz log4net? Każda część systemu zapisuje w swoim własnym rejestratorze, czy wszystko jest zapisywane w domyślnym rejestratorze, a konfiguracja decyduje, co dalej robić?

Odpowiedzi:


96

Jeśli chodzi o sposób logowania wiadomości w kodzie, wybrałbym drugie podejście:

ILog log = LogManager.GetLogger(typeof(Bar));
log.Info("message");

Gdzie wiadomości wysyłane do powyższego dziennika będą „nazwane” przy użyciu w pełni kwalifikowanego typu Bar, np

MyNamespace.Foo.Bar [INFO] message

Zaletą tego podejścia jest fakt, że jest to de facto standard organizowania rejestrowania, a także umożliwia filtrowanie komunikatów dziennika według przestrzeni nazw. Na przykład możesz określić, że chcesz rejestrować komunikat poziomu INFO, ale podnieść poziom rejestrowania Barspecjalnie do DEBUG:

<log4net>
    <!-- appenders go here -->
    <root>
        <level value="INFO" />
        <appender-ref ref="myLogAppender" />
    </root>

    <logger name="MyNamespace.Foo.Bar">
        <level value="DEBUG" />
    </logger>
</log4net>

Możliwość filtrowania logowania według nazwy jest potężną funkcją log4net, jeśli po prostu zarejestrujesz wszystkie swoje wiadomości "myLog", stracisz wiele z tej mocy!

Jeśli chodzi o EPiServer CMS, powinieneś być w stanie zastosować powyższe podejście do określenia innego poziomu logowania dla CMS i własnego kodu.

Aby przeczytać więcej, oto artykuł o projekcie kodu, który napisałem na temat logowania:


5
Możesz nawet wykluczyć z dziennika przestrzeni nazw klas, aby zmniejszyć szum w dziennikach, używając PatternLayout logging.apache.org/log4net/release/sdk/… ”Na przykład dla nazwy programu rejestrującego„ abc ”wzorzec% logger {2} będzie wyjście "bc". "
AlfeG

7
prywatny statyczny tylko do odczytu ILog log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod (). DeclaringType);
Casper Leon Nielsen

Dlaczego drugie podejście jest lepsze od pierwszego ?! Nazwa klasy jest statyczna, a jeśli ją zmienisz, będziesz musiał zaktualizować również nazwę w programie rejestrującym. Czy jest jakiś sens wywoływanie odbicia tylko po to, aby uzyskać nazwę klasy?
MeTitus

1
@CasperLeonNielsen Czy możesz wyjaśnić, czym to się różni this.GetType()?
ErikE

2
@ErikE this.GetType () nie będzie dostępne podczas definiowania właściwości statycznej, w klasie statycznej ani poza konstruktorem.
dhochee

12

Moja odpowiedź może się spóźnić, ale myślę, że może pomóc nowicjuszowi. Nie zobaczysz wykonanych dzienników, chyba że zmiany zostaną wprowadzone poniżej.

2 Pliki muszą zostać zmienione podczas implementacji Log4net.


  1. Dodaj odniesienie do log4net.dll w projekcie.
  2. app.config
  3. Plik klasy , w którym zaimplementujesz Logi.

Wewnątrz [ app.config ]:

Najpierw w sekcji „configSections” musisz dodać poniższy fragment kodu;

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

Następnie pod blokiem „konfiguracja” musisz napisać poniżej fragment kodu (ten fragment kodu jest dostosowywany zgodnie z moimi potrzebami, ale działa jak urok).

<log4net debug="true">
    <logger name="log">
      <level value="All"></level>
      <appender-ref ref="RollingLogFileAppender" />
    </logger>

    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="log.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <maxSizeRollBackups value="1" />
      <maximumFileSize value="1MB" />
      <staticLogFileName value="true" />

      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %C.%M [%line] %-5level - %message %newline %exception %newline" />
      </layout>
    </appender>
</log4net>

Klasa wywołań wewnętrznych :

W klasie, w której zamierzasz używać tego log4net, musisz zadeklarować poniższy fragment kodu.

 ILog log = LogManager.GetLogger("log");

Teraz jesteś gotowy do dziennika połączeń, gdziekolwiek chcesz w tej samej klasie. Poniżej znajduje się jedna z metod, które możesz wywołać podczas wykonywania operacji.

log.Error("message");

Nie musisz tworzyć ILogelementu instancji, prawda? Zadałem tutaj bardziej szczegółowo to samo pytanie , ale może uda mi się uzyskać od Ciebie informacje?
Minh Tran

6

Zamiast nazywać moją klasę wywołującą, zacząłem używać:

private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

W ten sposób mogę używać tej samej linii kodu w każdej klasie używającej log4net bez konieczności pamiętania o zmianie kodu podczas kopiowania i wklejania. Alternatywnie mógłbym utworzyć klasę rejestrowania i mieć wszystkie inne klasy dziedziczące z mojej klasy rejestrowania.


0

Wadą drugiego podejścia jest duże repozytorium z utworzonymi loggerami. Te programy rejestrujące robią to samo, jeśli zdefiniowano root, a rejestratory klas nie są zdefiniowane. Standardowy scenariusz na systemie produkcyjnym wykorzystuje kilka rejestratorów dedykowanych dla grupy klas. Przepraszam za mój angielski.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.