61

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.

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
vilmonts
  • 613
  • 1
  • 5
  • 4

5 Answers5

84

What you need to do is have a single <logger> definition with a defined level of INFO, but in your two appender definitions, you set their thresholds accordingly, e.g.

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

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

You then add both appenders to your logger:

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

Log entries now going to the logger will get sent to both appenders, but since they have different independent thresholds, the ERROR_FILE appender will only log ERROR and above.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • @vilmonts If you define the same logger (com.acme) twice, one of them gets overwritten, and that's why you can't see the INFO messages: the first one (with "error" level) erases the next (with "info" messages). – Alexandre Brasil Dec 03 '09 at 13:42
  • 2
    But I want to allow my ERROR_FILE appender to get selected debug messages of some other logger?! – AmanicA Aug 03 '12 at 23:59
  • I think then I need to write a custom filter. (In my case I found an application level tweak to fix this) – AmanicA Aug 04 '12 at 00:36
  • how to call this in java, is it like below Logger.getLogger()? – mahesh Feb 06 '14 at 18:25
12

Full working solution including the date in the filename:

<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>
Peter Perháč
  • 20,434
  • 21
  • 120
  • 152
Tcaci Oleg
  • 121
  • 1
  • 2
6

You need to use log4j filters:

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

That way you can create log files for each level separately.

Pawel Solarski
  • 1,028
  • 8
  • 7
  • this is a great answer. i am using .properties files for my log4j configuration. Could you please include in your answer how I would go about configuring this filter in .properties? please – Peter Perháč Feb 26 '16 at 13:22
  • That is not possible with a .properties file use XML file instead – Stimpson Cat Aug 30 '18 at 09:00
4

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>
Deepesh kumar Gupta
  • 884
  • 2
  • 11
  • 29
robothy
  • 1,132
  • 11
  • 18
2

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
    
borieux
  • 21
  • 2