Log4j Runtime Changes

Tuesday, November 29. 2005

Log4j is a Java library that lets you insert logging statements into your code that can be enabled at runtime without changing the application binary.

It can be configured to "watch" a properties file for changes:

PropertyConfigurator.configureAndWatch(configFilename, delay);

This creates a thread that will periodically check if configFilename has been created or modified. This is about the nicest feature of Log4j, besides the notion of inheritance in loggers. But there is a catch you need to be aware of. Log4j always detects when you add or change lines in log4j.properties. But, Log4j never detects when you delete a line.

Here is an example log4j.properties file:

# log4j properties
log4j.rootLogger=INFO, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{MM/dd HH:mm:ss} [%t] %p %l: %m%n

log4j.logger.com.company.project=DEBUG


This tells the application to log everything at an INFO level and higher, to the console, except for all log entries in classes in the com.company.project package, which will be logged at a DEBUG level.

Now say you have configured Log4j on startup to watch the properties file for changes (as shown above) every 30 seconds. Then you modify the last line of the log4j.properties file:

# log4j properties
log4j.rootLogger=INFO, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{MM/dd HH:mm:ss} [%t] %p %l: %m%n

log4j.logger.com.company.project=INFO


Within 30 seconds, the application will stop logging debug messages for classes in the com.company.project package (and all packages below it).

Now you add a line to the log4j.properties file:

# log4j properties
log4j.rootLogger=INFO, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{MM/dd HH:mm:ss} [%t] %p %l: %m%n

log4j.logger.com.company.project=INFO
log4j.logger.com.company.project.package=DEBUG


Within 30 seconds, the application will start logging debug messages for classes in the com.company.project.package.

Now you delete the line you just added:

# log4j properties
log4j.rootLogger=INFO, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{MM/dd HH:mm:ss} [%t] %p %l: %m%n

log4j.logger.com.company.project=INFO


You wait the 30 seconds, but the application continues to spit out the DEBUG messages. Nothing has changed. Nothing ever will change, either, because Log4j did not detect the removal of the line from the log4j.properties file.

If you think it over, it makes sense. Log4j reads the entire file, and picks up all the properties specified in the file. If there is no property, it won't know to change it.

To get around the issue, simply change the level to where you want it, rather than deleting the line. Then wait 30 seconds or so, then you can delete the line if you want to.