1

我在这里发现了一个错误,还是我对这个配置做错了什么?

<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 的任何内容都将通过管道输出到控制台两次,而不是预期的一次。如果我删除了更具体的记录器,则不会记录任何内容,如果我删除了不太具体的记录器,则事情只会记录一次,两者都符合预期。此外,颠倒配置文件中记录器的顺序没有任何作用(正如我所料,因为我猜这个顺序无关紧要)。

我是否在这里发现了错误,或者我错过了层次结构如何工作的重要内容?

4

2 回答 2

2

我使用多个记录器节点的实验经验是 log4net 将使用您在任何特定记录器中设置的最低级别。因此,即使您在 MyApp.Common 中指定了 WARN,在 MyApp.Common.SomeGenericClass 中使用 INFO 也会导致全局(?)级别设置下降到 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 继承,如果我将 root 引用的 appender 上的日志记录级别更改为 WARN,我也会得到 OtherNamespace 日志。我想要实现的只是将更详细的日志记录到与其他所有文件不同的文件中。

于 2011-11-28T20:09:32.513 回答
0

我认为这应该做你想做的(没有测试):

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

无需再次引用 appender,它会自动继承,除非您将additivity设置为 false。

于 2011-04-21T14:21:31.923 回答