Tue, 22 Feb 05
Runtime log4j configuration
So, I’ve spent the last day or so trying to track down how to configure log4j at runtime (log4j 1.2.8). Now, there are some things that are easy: setting the level of the root logger is as easy as: LogManager.getRootLogger().setLevel((Level) Level.DEBUG). However, if you want to do more complicated things at runtime based on other inputs than the log4j.{properties,xml} file, things begin to get a bit kludgy. For example, I wanted to set up a set of appenders with sane defaults. Then, if values were present in a configuration file, I wanted to update those appenders with different configuration values and change the root logger’s behavior.
The easiest way I could find was to manipulate the properties file, as shown below:
package test;
import org.apache.log4j.*;
import org.apache.log4j.net.SMTPAppender;
import org.apache.log4j.net.SyslogAppender;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.Properties;
import java.io.*;
public class Test {
private Log log = LogFactory.getLog(Test.class);
Test() {
log.debug("test1");
switchAppenders();
log.debug("test2");
}
public static void main(String args[]) {
Test t = new Test();
}
private void switchAppenders() {
Properties props = new Properties();
try {
InputStream configStream = getClass().getResourceAsStream("/log4j.properties");
props.load(configStream);
configStream.close();
} catch(IOException e) {
System.out.println("Error: Cannot laod configuration file ");
}
props.setProperty("log4j.rootLogger","DEBUG, file");
props.setProperty("log4j.appender.file.File","out.log");
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
}
}
This code is executed via this command, making sure that log4j.properties is present in the classpath:
java -classpath .:log4j-1.2.8.jar:commons-logging.jar test.Test
This is quite a kludge, but I couldn’t find anything better out there. It has the obvious setback that the changes you make to the log4j aren’t persisted, nor can they easily happen in more than one place, and any changes to appender names break a log of things, but at least it works.
« Looking for a job? RSS can help | Permalink | Setting the content encoding for HTML message parts with Javamail »
Antony said,
January 2, 2009 at 3:30 pm
Hi,
Thanks a lot for your post!! Spent nearly 3 hours on this topic and finally got a solution thru yours.
Just a minor suggestion. Instead of reading the properties file into an InputStream and changing values and then reloading. Try using variable substitutions in log4j.properties and set the system properties and reload.
your log4j.properties should look like:
…..
log4j.appender.mailappender.subject=${mail.subject}
…..
Your Backend code:
System.setProperty(”mail.subject”, “Test Succeeded”);
org.apache.log4j.LogManager.resetConfiguration();
PropertyConfigurator.configure(”/log4j.properties”);
By doing so, I feel, the file loading time and the properties memory may be saved.