How to configure log4j to log different log levels to different files for the same logger

Viewed 59827

I have a normal INFO level log for application. What I need is to additionally log all ERROR level events to separate error log. I am using configuration like this:

<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>

This configuration logs errors only. If I put info level logger first, then it will log only to general appender, but error logger will not work. I would like to have them both working.

5 Answers

If you are using log4j2 and config with XML format, ThresholdFilter is a good solution.

Here is a sample:

    <?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>

Well, actually, you can do it using .properties file; you don't have to use .xml file :

  • 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
    
Related