81

Is there a way to configure log4j so that it outputs different levels of logging to different appenders?

I'm trying to set up multiple log files. The main log file would catch all INFO and above messages for all classes. (In development, it would catch all DEBUG and above messages, and TRACE for specific classes.)

Then, I would like to have a separate log file. That log file would catch all DEBUG messages for a specific subset of classes, and ignore all messages for any other class.

Is there a way to get what I'm after?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 3
    Do you mean you want one logfile to capture DEBUG and only DEBUG, another logfile to capture INFO and only INFO, and so on? – Eddie Apr 08 '09 at 02:45

5 Answers5

71

This should get you started:

log4j.rootLogger=QuietAppender, LoudAppender, TRACE
# setup A1
log4j.appender.QuietAppender=org.apache.log4j.RollingFileAppender
log4j.appender.QuietAppender.Threshold=INFO
log4j.appender.QuietAppender.File=quiet.log
...


# setup A2
log4j.appender.LoudAppender=org.apache.log4j.RollingFileAppender
log4j.appender.LoudAppender.Threshold=DEBUG
log4j.appender.LoudAppender.File=loud.log
...

log4j.logger.com.yourpackage.yourclazz=TRACE
Eric Darchis
  • 24,537
  • 4
  • 28
  • 49
jasonnerothin
  • 1,556
  • 10
  • 15
  • 4
    What does the very last line do? – djangofan Mar 11 '12 at 02:24
  • 1
    @djangofan sets up a custom package/class log level (i.e. com.yourpackage.yourclazz with TRACE logging), although in this case it was already the default (set up on line 1) so it does nothing. IMO this example would be better if the rootLogger had INFO and "yourclass" had DEBUG. – Tom Clift May 21 '12 at 05:33
  • 1
    The parameters of the first line should be TRACE, QuietAppender, LoudAppender not QuietAppender, LoudAppender, TRACE – Richard Whitehead Oct 25 '16 at 15:00
26

Perhaps something like this?

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 <!-- general application log -->
 <appender name="MainLogFile" class="org.apache.log4j.FileAppender">
  <param name="File" value="server.log" />
  <param name="Threshold" value="INFO" />
  <layout class="org.apache.log4j.PatternLayout">
   <param name="ConversionPattern" value="%-5p %t [%-40.40c] %x - %m%n"/>
  </layout>
 </appender> 
 <!-- additional fooSystem logging -->
 <appender name="FooLogFile" class="org.apache.log4j.FileAppender">
  <param name="File" value="foo.log" />
  <layout class="org.apache.log4j.PatternLayout">
   <param name="ConversionPattern" value="%-5p %t [%-40.40c] %x - %m%n"/>
  </layout>
 </appender>
 <!-- foo logging -->
 <logger name="com.example.foo">
  <level value="DEBUG"/>
  <appender-ref ref="FooLogFile"/>
 </logger>
 <!-- default logging -->
 <root>
  <level value="INFO"/>
  <appender-ref ref="MainLogFile"/>
 </root>
</log4j:configuration>

Thus, all info messages are written to server.log; by contrast, foo.log contains only com.example.foo messages, including debug-level messages.

araqnid
  • 127,052
  • 24
  • 157
  • 134
7

I had this question, but with a twist - I was trying to log different content to different files. I had information for a LowLevel debug log, and a HighLevel user log. I wanted the LowLevel to go to only one file, and the HighLevel to go to both a file, and a syslogd.

My solution was to configure the 3 appenders, and then setup the logging like this:

log4j.threshold=ALL
log4j.rootLogger=,LowLogger

log4j.logger.HighLevel=ALL,Syslog,HighLogger
log4j.additivity.HighLevel=false

The part that was difficult for me to figure out was that the 'log4j.logger' could have multiple appenders listed. I was trying to do it one line at a time.

Hope this helps someone at some point!

Kieveli
  • 10,944
  • 6
  • 56
  • 81
3

For the main logfile/appender, set up a .Threshold = INFO to limit what is actually logged in the appender to INFO and above, regardless of whether or not the loggers have DEBUG, TRACE, etc, enabled.

As for catching DEBUG and nothing above that... you'd probably have to write a custom appender.

However I'd recommend not doing this, as it sounds like it would make troubleshooting and analysis pretty hard:

  1. If your goal is to have a single file where you can look to troubleshoot something, then spanning your log data across different files will be annoying - unless you have a very regimented logging policy, you'll likely need content from both DEBUG and INFO to be able to trace execution of the problematic code effectively.
  2. By still logging all of your debug messages, you are losing any performance gains you usually get in a production system by turning the logging (way) down.
matt b
  • 138,234
  • 66
  • 282
  • 345
  • I should have explained my goal better. The main log is for tracking errors, unusual conditions, etc. anywhere in the app--this log is required to be kept small, so it rolls over regularly. The special log tracks behavior of one subsystem, and needs to be kept for long periods of time. –  Apr 08 '09 at 02:51
  • Do you want to exclude ERROR, WARN, INFO messages from the second log file? – matt b Apr 08 '09 at 03:03
  • and in XML you can add parameter Threshold like this: – razor Jan 24 '17 at 13:08
0

Demo link: https://github.com/RazvanSebastian/spring_multiple_log_files_demo.git

My solution is based on XML configuration using spring-boot-starter-log4j. The example is a basic example using spring-boot-starter and the two Loggers writes into different log files.

RazvanParautiu
  • 2,805
  • 2
  • 18
  • 21