Правильний спосіб використання log4net (іменування реєстратора)


83

Існує два способи налаштування та використання log4net. Перший - це коли я можу налаштувати власний додаток та пов’язаний журнал:

<!-- 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>

І тоді, коли я хочу написати щось у журналі, я можу зробити наступне:

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

Інший спосіб його використання - налаштувати root так детально, як я хочу:

<!-- language: xml -->

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

І в цьому випадку я можу реєструвати такі повідомлення:

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

Переваги другого підходу в тому, що ви можете вмикати або вимикати деякі повідомлення на льоту. Але проблема в тому, що я розробляю систему управління вмістом EPiServer, і вона має власну систему ведення журналу, яка використовує log4net, і якщо я ввімкнув реєстрацію інформації на кореневому рівні, тоді буде записано багато системних журналів.

Як ви використовуєте log4net? Кожна частина системи пише у своєму реєстраторі, або все записується в реєстраторі за замовчуванням, і конфігурація вирішує, що робити далі?

Відповіді:


96

Щодо того, як ви реєструєте повідомлення в коді, я б обрав другий підхід:

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

Там, де повідомлення, надіслані до журналу вище, будуть "іменовані" з використанням повністю кваліфікованого типу Bar, наприклад

MyNamespace.Foo.Bar [INFO] message

Перевага цього підходу полягає в тому, що він є фактичним стандартом організації ведення журналу, а також дозволяє фільтрувати повідомлення журналу за простором імен. Наприклад, ви можете вказати, що ви хочете реєструвати повідомлення рівня INFO, але підняти рівень реєстрації для BarDEBUG:

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

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

Можливість фільтрувати журнал за іменами - це потужна функція log4net, якщо ви просто увійдете в усі свої повідомлення "myLog", ви втратите більшу частину цієї сили!

Що стосується системи управління вмістом EPiServer, ви повинні мати можливість використовувати наведений вище підхід для визначення іншого рівня реєстрації для системи управління вмістом та власного коду.

Для подальшого читання, ось стаття про codeproject, яку я написав про реєстрацію:


5
Ви навіть можете виключити з журналу частину просторів імен класів, щоб зменшити шум у журналах, використовуючи PatternLayout logging.apache.org/log4net/release/sdk/… "Наприклад, для імені реєстратора" abc "шаблон% logger {2} буде вивести "bc". "
AlfeG

7
приватний статичний журнал ILog для читання = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod (). DeclaringType);
Каспер Леон Нільсен,

Чому другий підхід кращий за перший ?! Ім'я класу є статичним, і якщо ви його зміните, вам доведеться також оновити ім'я в реєстраторі, чи є сенс викликати дзвінок для відображення лише для того, щоб отримати ім'я класу?
MeTitus

1
@CasperLeonNielsen Чи можете ви пояснити, чим це відрізняється this.GetType()?
ErikE

2
@ErikE this.GetType () не буде доступним при визначенні статичного властивості, у статичному класі або поза конструктором.
dhochee

11

Моя відповідь може пізніше, але я думаю, що це може допомогти новачкові. Ви не побачите виконуваних журналів, якщо зміни не будуть внесені, як показано нижче.

2 Файли повинні бути змінені під час реалізації Log4net.


  1. Додайте посилання на log4net.dll у проект.
  2. app.config
  3. Файл класу, де ви будете реалізовувати журнали.

Усередині [ app.config ]:

По-перше, у розділі 'configSections' потрібно додати нижче шматок коду;

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

Потім, у блоці "конфігурація", вам потрібно написати нижче фрагмент коду. (Цей фрагмент коду налаштований відповідно до моїх потреб, але він працює як шарм.)

<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>

Клас внутрішнього дзвінка :

Усередині класу, де ви збираєтеся використовувати цей log4net, вам потрібно оголосити нижче шматок коду.

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

Тепер ви готові до журналу викликів, де б ви не хотіли в тому ж класі. Нижче наведено один із методів, який можна викликати під час виконання операцій.

log.Error("message");

Вам не потрібно робити учасника ILogекземпляра правильно? Я задав те саме питання тут більш докладно, але, можливо, я можу отримати вашу інформацію?
Мінь Тран

6

Замість того, щоб називати свій клас, що викликається, я почав використовувати наступне:

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

Таким чином, я можу використовувати той самий рядок коду в кожному класі, який використовує log4net, не пам'ятаючи про зміну коду під час копіювання та вставлення. Крім того, я міг би створити клас ведення журналу, і кожен інший клас успадкував би від мого класу журналювання.


0

Недоліком другого підходу є великий репозиторій зі створеними реєстраторами. Ці реєстратори роблять те саме, якщо визначено root і реєстратори класів не визначені. Стандартний сценарій виробничої системи - використання декількох лісорубів, присвячених групі класів. Перепрошую за мою англійську.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.