Правильный способ использования 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 CMS, и у нее есть собственная система ведения журнала, которая использует log4net, и если я включу ведение журнала информации на корневом уровне, будет записано много системных журналов.

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

Хитрый
источник

Ответы:

96

Что касается того, как вы регистрируете сообщения в коде, я бы выбрал второй подход:

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

Если сообщения, отправленные в журнал выше, будут 'именоваться' с использованием полностью квалифицированного типа Bar, например

MyNamespace.Foo.Bar [INFO] message

Преимущество этого подхода состоит в том, что он является стандартом де-факто для организации ведения журнала, а также позволяет фильтровать сообщения журнала по пространству имен. Например, вы можете указать, что хотите регистрировать сообщение уровня INFO, но поднять уровень ведения журнала Barспециально до DEBUG:

<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 CMS, вы должны иметь возможность использовать описанный выше подход, чтобы указать другой уровень ведения журнала для CMS и вашего собственного кода.

Для дальнейшего чтения вот статья кода проекта, которую я написал о ведении журнала:

Колин
источник
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
12

Мой ответ может прийти с опозданием, но я думаю, что он может помочь новичку. Вы не увидите выполненных журналов, если не внесены следующие изменения.

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, а регистраторы классов не определены. Стандартный сценарий в производственной системе использует несколько регистраторов, выделенных для группы классов. Извините за мой английский.

user1785960
источник