如何配置log4j2的可加性以尊重父级别的设置?

5
我认为这段代码已经很好地解释了我想要做的事情。
package us.benanderson;

public class MyClass {

  private static final Logger LOG = LogManager.getLogger(MyClass.class);
  ...
    // within a method
    LOG.debug("only output to appFile");
    LOG.error("output to both appFile and errorFile");

这是我猜测应该是我的配置。
<Loggers>
    <Logger name="us.benanderson" level="debug" additivity="true">
        <AppenderRef ref="appFile" />
    </Logger>

    <Root level="error">
        <AppenderRef ref="errorFile" />
    </Root>
</Loggers>

然而,我发现当additivity="true"时,调试信息也会输出到errorFile。当additivity="false"时,不会有任何输出到errorFile。有没有什么方法可以实现我想做的事情?

4个回答

8
我认为实现您想要的最简单的方法是直接在appender-ref上放置一个级别。这样可以消除在配置中拥有命名记录器的必要性,从而简化配置。
如果您想将某个包的日志事件重定向到单独的appender,则命名记录器仍然很有用。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <File name="appFile" fileName="logs/appFile.log" append="true">
      <PatternLayout pattern="%-5p %d{ABSOLUTE} [%t] %c - %m%n" />
    </File>
    <File name="errorFile" fileName="logs/errorFile.log" append="true">
      <PatternLayout pattern="%-5p %d{ABSOLUTE} [%t] %c - %m%n" />
    </File>
  </Appenders>
  <Loggers>
    <Root level="trace">
      <AppenderRef ref="appFile" level="debug" />
      <AppenderRef ref="errorFile" level="error" />
    </Root>
  </Loggers>
</Configuration>

如果您想进行更加特殊的过滤操作,阈值过滤器和组合过滤器可能会非常有用,尤其是在涉及it技术时。例如,如果您想要将仅INFO和WARN级别的事件发送到特定的appender,同时排除TRACE/DEBUG,以及ERROR和FATAL级别的事件(!),您可以执行以下操作:

<Console name="only-info-warn">
    <PatternLayout pattern="%-5p %c %message %n" />
    <Filters>

        <!-- First deny error and fatal messages -->
        <ThresholdFilter level="error" onMatch="DENY"   onMismatch="NEUTRAL"/>
        <ThresholdFilter level="fatal" onMatch="DENY"   onMismatch="NEUTRAL"/>

        <!-- Then accept info, warn, error, fatal and deny debug/trace -->
        <ThresholdFilter level="warn"  onMatch="ACCEPT" onMismatch="NEUTRAL"/>
        <ThresholdFilter level="info"  onMatch="ACCEPT" onMismatch="DENY"/>
    </Filters>
</Console>

在log4j2中,我们可以直接在appender-ref上设置“level”吗?难道不是通过appender内部的过滤器实现相同的功能吗? - M..
Appender-ref支持级别的功能在很久以前就已经添加了,具体可以参考https://issues.apache.org/jira/browse/LOG4J2-60。您可以将其视为在appender配置元素中放置<threshold/>过滤器的简短表示法。 - Remko Popma
@RemkoPopma 如果父记录器与子记录器的记录级别不同,传递日志事件给父记录器的目的是什么?如果遇到具有更高记录级别的父级记录器,该事件不应立即被阻止冒泡吗? - Michel Feinstein
如果我没记错的话,父记录器可能会被阻止,但祖先记录器可能是启用的。如果您想了解更多详细信息,请在log4j-user邮件列表上提问。 - Remko Popma

4

使用过滤器。

以下是一个配置,将所有内容输出到C:/Logs/Log.log,并且仅将调试信息输出到C:/Logs/Debug.log

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
    <appender name="general-out" class="org.apache.log4j.FileAppender"> 
        <param name="File" value="C:/Logs/Log.log"/> 
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1} : %m%n"/> 
        </layout> 
    </appender> 

    <appender name="debug-out" class="org.apache.log4j.FileAppender"> 
        <param name="File" value="C:/Logs/Debug.log"/>
        <layout class="org.apache.log4j.PatternLayout"> 
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1} : %m%n"/> 
        </layout> 
        <filter class="org.apache.log4j.varia.LevelMatchFilter">
            <param name="LevelToMatch" value="debug"/> 
            <param name="AcceptOnMatch" value="true"/> 
        </filter>     
        <filter class="org.apache.log4j.varia.DenyAllFilter"/> 
    </appender> 

    <root>
        <appender-ref ref="debug-out" />
        <appender-ref ref="general-out" /> 
    </root> 
</log4j:configuration>

这里的关键部分是:
<filter class="org.apache.log4j.varia.LevelMatchFilter">
    <param name="LevelToMatch" value="debug"/> 
    <param name="AcceptOnMatch" value="true"/> 
</filter>     
<filter class="org.apache.log4j.varia.DenyAllFilter"/> 

这样可以记录使用debug的事情,然后拒绝其他任何事情。
来源:http://wiki.apache.org/logging-log4j/LogByLevel

谢谢,Pokechu22。这很有帮助,尽管我真正想要的是log4j2配置。 - andersonbd1

2

既然您正在使用Log4j 2,您可能想要使用ThresholdFilter。通过使用此过滤器,您的配置文件可以如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <File name="appFile" fileName="logs/appFile.log" append="true">
      <PatternLayout pattern="%d %-5p (%c.java:%L).%M - %m%n" />
      <ThresholdFilter level="DEBUG" />
    </File>
    <File name="errorFile" fileName="logs/errorFile.log" append="true">
      <PatternLayout pattern="%d %-5p (%c.java:%L).%M - %m%n" />
      <ThresholdFilter level="ERROR" />
    </File>
  </Appenders>
  <Loggers>
    <Logger name="us.benanderson" level="debug">
      <AppenderRef ref="appFile" />
    </Logger>
    <Root level="error">
      <AppenderRef ref="errorFile" />
    </Root>
  </Loggers>
</Configuration>

谢谢,保罗。如果我没有得到一个稍微更详细的答案,我肯定会接受这个答案的。 - andersonbd1

1

根据您的要求,配置应该如下(带注释):

<Loggers>
    <!-- Do not trickle down 'debug' logs to parent logger using additivity as false; keeping them only in appFile -->
    <Logger name="us.benanderson" level="debug" additivity="false">
            <AppenderRef ref="appFile" />
    </Logger>
    <!-- Error messages by default go to both appfile and errorFile -->
    <Root level="error">
            <AppenderRef ref="errorFile" />
        <AppenderRef ref="appFile" />
    </Root>
</Loggers>

如果您特别担心来自“us.benanderson”包的错误日志,则可以尝试为“error”级别设置单独的记录器。因此,配置应如下所示:-
<Loggers>
    <Logger name="us.benanderson" level="debug" additivity="false">
        <AppenderRef ref="appFile" />
    </Logger>
    <!-- Not specifying additivity here would default to 'true'; hence the error logs   would also be relayed to the root/errorFile -->
    <Logger name="us.benanderson" level="error">
        <AppenderRef ref="appFile" />
    </Logger>
    <Root level="error">
        <AppenderRef ref="errorFile" />
    </Root>
</Loggers>

谢谢,Abhin。如果我没有得到稍微更详尽的答案,我会接受这个答案的。 - andersonbd1
不用客气:)只要能解决你的问题就好了。那么'appenderRef'中的'level'确实可以工作吗? - M..

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接