62

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 5

86

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.

Sign up to request clarification or add additional context in comments.

4 Comments

@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).
But I want to allow my ERROR_FILE appender to get selected debug messages of some other logger?!
I think then I need to write a custom filter. (In my case I found an application level tweak to fix this)
how to call this in java, is it like below Logger.getLogger(<classname under the package com.acme>)?
13

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>

2 Comments

It would be helpfult o know the dependencies
Does this need to be named logback.xml? Or logback-spring.xml?
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.

2 Comments

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
That is not possible with a .properties file use XML file instead
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>

Comments

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
    

1 Comment

The question was to log it into different files, not to filter by level.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.