如何配置log4j,使同一记录器将不同的日志级别记录到不同的文件中。

61

我有一个应用程序的普通INFO级别日志。我需要额外记录所有ERROR级别事件到单独的错误日志中。我使用的配置如下:

<logger name="com.acme">
    <level value="error"/>
    <appender-ref ref="error"/>
</logger>

<logger name="com.acme">
    <level value="info"/>
</logger>

<root>
    <level value="warn"/>
    <appender-ref ref="general"/>
</root>

这个配置只记录错误。如果我先放置信息级别的记录器,那么它将仅记录到一般的附加程序,但错误记录器将不起作用。我希望它们都能正常工作。

5个回答

85

你需要做的是创建一个单一的<logger>定义并设置为INFO级别,然后在两个appender的定义中,相应地设置它们的阈值,例如:

<appender name="ERROR_FILE">
   <param name="Threshold" value="ERROR"/>
</appender>

<appender name="GENERAL">
   <param name="Threshold" value="INFO"/>
</appender>

然后您将两个appender添加到您的logger中:

<logger name="com.acme">
  <level value="INFO"/>
  <appender-ref ref="ERROR_FILE"/>
  <appender-ref ref="GENERAL"/>
</logger>

现在发送到记录器的日志条目将发送到两个附加器,但由于它们具有不同的独立阈值,因此ERROR_FILE附加器只记录ERROR及以上级别的信息。


如果您定义了相同的记录器(com.acme)两次,其中一个将被覆盖,这就是为什么您无法看到INFO消息的原因:第一个记录器(具有“错误”级别)会擦除下一个(具有“信息”消息)。 - Alexandre Brasil
2
但是我想允许我的ERROR_FILE appender选择其他记录器的调试消息?! - AmanicA
我认为我需要编写一个自定义过滤器。(在我的情况下,我发现了一个应用级别的调整来修复这个问题) - AmanicA
非常感谢您。 - WillBD
如何在Java中调用它,是像下面这样Logger.getLogger(<位于包com.acme下的类名>)吗? - mahesh

12

完整的工作解决方案,包括日期在文件名中:

<appender name="InfoFileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
    <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
      <param name="FileNamePattern" value="/var/output/Info_%d{ddMMyyyy}.log" />
    </rollingPolicy>
    <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%d{HH:mm:ss} %-5p %t %c{2} - %m%n" />
    </layout>
    <filter class="org.apache.log4j.varia.LevelRangeFilter">
      <param name="levelMin" value="INFO" />
      <param name="levelMax" value="INFO" />
    </filter>
</appender>

<appender name="ErrorFileAppender" class="org.apache.log4j.rolling.RollingFileAppender">
    <param name="Threshold" value="ERROR" />
    <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="FileNamePattern" value="/var/output/Error_%d{ddMMyyyy}.log" />
    </rollingPolicy>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{HH:mm:ss} %-5p %t %c{2} - %m%n" />
    </layout>
</appender>
<root>
    <level value="INFO" />
    <appender-ref ref="InfoFileAppender" />
    <appender-ref ref="ErrorFileAppender" />
</root>

知道依赖关系会很有帮助。 - Carlos López Marí
这个需要命名为logback.xml吗?还是logback-spring.xml? - Woodchuck

6

您需要使用log4j过滤器:

<filter class="org.apache.log4j.varia.LevelRangeFilter">
    <param name="levelMin" value="ERROR" />
    <param name="levelMax" value="ERROR" />
</filter>

这样您就可以为每个级别单独创建日志文件。


这是个很好的回答。我正在使用.properties文件来配置我的log4j日志记录器。你能否在回答中提供如何在.properties文件中配置这个过滤器的方法? - Peter Perháč
这在 .properties 文件中是不可能的,请使用 XML 文件。 - Stimpson Cat

4
如果您正在使用log4j2并且配置为XML格式,ThresholdFilter是一个不错的解决方案。
以下是一个示例:
    <?xml version="1.0" encoding="UTF-8"?>

      <Configuration status="WARN">

       <Appenders>
          <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout>
        <Pattern>%d %-5p  %m%n</Pattern>
      </PatternLayout>
      <ThresholdFilter level="DEBUG"/>
    </Console>
    
    <RollingFile name="RollingDebugLogFile" fileName="logs/app-debug.log" filePattern="logs/$${date:yyyy-MM}/app-debug-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %-5p  %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="20MB"/>
      </Policies>
      <ThresholdFilter level="DEBUG"/>
    </RollingFile>
  
    <RollingFile name="RollingErrorLogFile" fileName="logs/app-error.log" filePattern="logs/$${date:yyyy-MM}/app-error-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %-5p  %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="20MB"/>
      </Policies>
      <ThresholdFilter level="ERROR"/>
    </RollingFile>
  
    <RollingFile name="RollingInfoLogFile" fileName="logs/app-info.log" filePattern="logs/$${date:yyyy-MM}/app-info-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %-5p  %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="20MB"/>
      </Policies>
      <ThresholdFilter level="INFO"/>
    </RollingFile>
    
  </Appenders>

  <Loggers>
    <Logger name="testLogger" level="DEBUG" additivity="false">
        <AppenderRef ref = "Console" />
        <AppenderRef ref="RollingErrorLogFile" />
        <AppenderRef ref="RollingInfoLogFile" />
        <AppenderRef ref="RollingDebugLogFile" />
    </Logger>
    <Root level="INFO">
      <AppenderRef ref = "Console" />
      <AppenderRef ref="RollingErrorLogFile" />
      <AppenderRef ref="RollingInfoLogFile" />
      <AppenderRef ref="RollingDebugLogFile" />
    </Root>
    
  </Loggers>
</Configuration>

2

实际上,您可以使用.properties文件来完成这项任务,不必使用.xml文件:

  • Log only WARN

    log4j.appender.appenderName.filter.a=org.apache.log4j.varia.LevelRangeFilter
    log4j.appender.appenderName.filter.a.LevelMin=WARN
    log4j.appender.appenderName.filter.a.LevelMax=WARN
    
  • Log from INFO to WARN

    log4j.appender.appenderName.filter.a=org.apache.log4j.varia.LevelRangeFilter
    log4j.appender.appenderName.filter.a.LevelMin=INFO
    log4j.appender.appenderName.filter.a.LevelMax=WARN
    

问题是将其记录到不同的文件中,而不是按级别过滤。 - Carlos López Marí

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