log4net logger иерархия с похожими именами корня журнала - PullRequest
1 голос
/ 21 апреля 2011

Я нашел ошибку здесь, или я что-то не так с этой конфигурацией?

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%message%newline" />
  </layout>
</appender>
<logger name="MyApp.Common">
  <level value="WARN" />
  <appender-ref ref="ConsoleAppender" />
</logger>
<logger name="MyApp.Common.Namespace.SomeGenericClass`1">
  <level value="INFO" />
  <appender-ref ref="ConsoleAppender" />
</logger>

Предполагая, что я назвал свои регистраторы в соответствии со стандартной схемой именования "... DeclaringType",Я ожидаю, что все, что находится в пространстве имен MyApp.Common, будет зарегистрировано на консоли, если оно WARN или выше.Все, что находится в SomeGenericClass`1, будет зарегистрировано, если оно INFO или выше (и в два раза, если оно WARN или выше из-за регистратора WARN).

То, что происходит в том, что что-то в SomeGenericClass`1, которое регистрируется в INFO, будетбыть выведенным на консоль дважды вместо ожидаемого один раз.Если я удаляю более конкретный регистратор, ничто не регистрируется, а если я удаляю менее специфичный регистратор, все регистрируется только один раз, как и ожидалось.Кроме того, изменение порядка регистраторов в файле конфигурации ничего не дает (как и следовало ожидать, поскольку я предполагаю, что порядок не имеет значения).

Нашел ли я здесь ошибку, или я пропустилчто-то важное в том, как работает иерархия?

Ответы [ 2 ]

2 голосов
/ 29 ноября 2011

Мой экспериментальный опыт использования нескольких узлов логгера заключается в том, что log4net будет использовать самый низкий уровень, который вы установили в любом конкретном логгере.Таким образом, даже если вы указали WARN в MyApp.Common, использование INFO в MyApp.Common.SomeGenericClass привело к тому, что глобальный (?) Уровень настройки упал до WARN.Таким образом, вы получили запись от MyApp.Common, а также MyApp.Common.SomeGenericClass, так как appender ConsoleAppender был запущен дважды.

После чего я получил набор журналов для перехода в отдельный файл.Не совсем то, что вы задали в своем вопросе, но оно охватывает то, что вы хотите сделать.И я действительно хотел документировать свое решение где-нибудь, где я мог бы найти его снова для моей собственной выгоды ;-).

Я создал два разных регистратора, таких как у вас выше, хотя один из них - root, он будет работать одинаково.Затем я создал два разных приложения, каждый из которых фильтровал по разным уровням ошибок, и сослался на них отдельно в двух регистраторах.То, что я получаю, это журналы из OtherNamespace в одном файле и все остальное в другом.Код для этого приведен ниже.

<log4net>
<logger name="OtherNamespace">
  <appender-ref ref="OtherNamespaceAppender"/>
</logger>
<root>
  <level value="WARN"/>
  <appender-ref ref="MyRollingFileAppender"/>
</root>
<appender name="MyRollingFileAppender" type="log4net.Appender.RollingFileAppender">
  <file type="log4net.Util.PatternString" value="C:\Comanche\mylogfileFor_%property{User}.log" />
  <appendToFile value="true" />
  <rollingStyle value="Size" />
  <threshold value="ERROR" />
  <countDirection value="3" />
  <maxSizeRollBackups value="2" />
  <maximumFileSize value="200KB" />
  <staticLogFileName value="true" />
  <layout type="log4net.Layout.PatternLayout">
    <param name="ConversionPattern" value="%-6level%utcdate{ABSOLUTE} – %location :: %message%newline" />
  </layout>
</appender>
<appender name="OtherNamespaceAppender" type="log4net.Appender.RollingFileAppender">
  <file value="C:\Comanche\OtherNamespace.log" />
  <appendToFile value="true" />
  <rollingStyle value="Size" />
  <threshold value="WARN" />
  <countDirection value="3" />
  <maxSizeRollBackups value="2" />
  <maximumFileSize value="200KB" />
  <staticLogFileName value="true" />
  <filter type="log4net.Filter.LoggerMatchFilter">
    <acceptOnMatch value="true" />
    <LoggerToMatch value="OtherNamespace" />
    <!-- set your class name here -->
  </filter>

  <filter type="log4net.Filter.DenyAllFilter" />

  <layout type="log4net.Layout.PatternLayout">
    <param name="ConversionPattern" value="%-6level%utcdate{ABSOLUTE} :: %message%newline" />
  </layout>
</appender>

Имейте в виду, что «все остальное» было в другом пространстве имен, поэтому оно не шунтировалось в регистратор OtherNamespace, который он мог бы иметь при наличиибыло бы совпадение имен какой-то.Также обратите внимание, что, поскольку все наследуется от root, если бы я изменил уровень ведения журнала в appender, на который ссылается root, на WARN, я бы также получил журналы OtherNamespace.Все, чего я хотел добиться, - это сделать более подробное ведение журнала в другом файле, чем все остальное.

0 голосов
/ 21 апреля 2011

Я думаю, что это должно делать то, что вы хотите (не проверял):

<logger name="MyApp.Common">
     <level value="WARN" />
     <appender-ref ref="ConsoleAppender" />
</logger>
<logger name="MyApp.Common.Namespace.SomeGenericClass`1">
     <level value="INFO" />  
</logger>

Нет необходимости снова ссылаться на аппендера, он автоматически наследуется, если вы не установите аддитивность 1005 * в ложь.

...