Changing Log4j logging levels dynamically
Simple problem and may seem oh-not-so-cool. Make the log4j level dynamically configurable. You
should be a able to change from DEBUG to INFO or any of the others. All
this in a running application server.
First the simple, but not so elegant approach. Don't get me wrong (about the elegance statement) this approach works.
Log4j API
Often applications will have custom log4j properties files. Here we define the appenders and the layouts for the appenders. Somewhere in the java code we have to initialize log4j and point it to this properties file. We can use the following API call to configure and apply the dynamic update.
If you are using Spring then you are in luck. Spring provides ready-to-use classes to do this job. You can use the support class org.springframework.web.util.Log4jWebConfigurer. Provide it values for log4jConfigLocation, log4jRefreshInterval. For the path you can pass either one that is relative to your web application (this means you need to deploy in expanded WAR form) or provide an absolute path. I prefer the latter; that way I can keep my WAR file warred and not expanded.
There is also a web application listener class org.springframework.web.util.Log4jConfigListener that you can use in the web.xml file. The actual implementation of the Spring class Log4jWebConfigurer does the call to either:
Log4j spawns a separate thread to watch the file. Make sure your application has a shutdown hook where you can org.apache.log4j.LogManager.shutdown() to shut down log4j cleanly. The thread unfortunately does not die if your application is undeployed. Thats the only downside of using Log4j configureAndWatch API. In most cases thats not a big deal so I think its fine.
JMX Approach
JMX according to me is the cleanest approach. Involves some leg work initially but is well worth it. This example here is run on JBoss 4.0.5. Lets look at a simple class that will actually change the log level.

One thing to note here is that the parameter names are p1 (for loggerName) and p2 for (level). This is because I have not provided any meta data about the parameters. When I do my blog on using JMX+Spring+CommonsAttributes under Weblogic 8.1, you will see how this can be resolved. BTW for jdk 1.4 based Spring projects you must use commons attributes tags provided by Spring to register and describe your beans as JMX beans. The initial minor learning curve will save you tons of time later.
First the simple, but not so elegant approach. Don't get me wrong (about the elegance statement) this approach works.
Log4j API
Often applications will have custom log4j properties files. Here we define the appenders and the layouts for the appenders. Somewhere in the java code we have to initialize log4j and point it to this properties file. We can use the following API call to configure and apply the dynamic update.
org.apache.log4j.PropertyConfigurator.configureAndWatch( |
- Pass it the path to the custom log4j.properties and a delay in milliseconds. Log4j will periodically check the file for changes (after passage of the configured delay time).
If you are using Spring then you are in luck. Spring provides ready-to-use classes to do this job. You can use the support class org.springframework.web.util.Log4jWebConfigurer. Provide it values for log4jConfigLocation, log4jRefreshInterval. For the path you can pass either one that is relative to your web application (this means you need to deploy in expanded WAR form) or provide an absolute path. I prefer the latter; that way I can keep my WAR file warred and not expanded.
There is also a web application listener class org.springframework.web.util.Log4jConfigListener that you can use in the web.xml file. The actual implementation of the Spring class Log4jWebConfigurer does the call to either:
org.apache.log4j.PropertyConfigurator.configureAndWatch |
Log4j spawns a separate thread to watch the file. Make sure your application has a shutdown hook where you can org.apache.log4j.LogManager.shutdown() to shut down log4j cleanly. The thread unfortunately does not die if your application is undeployed. Thats the only downside of using Log4j configureAndWatch API. In most cases thats not a big deal so I think its fine.
JMX Approach
JMX according to me is the cleanest approach. Involves some leg work initially but is well worth it. This example here is run on JBoss 4.0.5. Lets look at a simple class that will actually change the log level.
package com.aver.logging; |
- Given a logger name and a level to change to this code will do just that. The code needs some error handling and can be cleaned up a little. But this works for what I am showing.
- To change the log level we get the logger for the specified loggerName and change to the new level.
<?xml version="1.0" encoding="UTF-8"?> |
- In Spring we use the MBeanExporter to register your MBeans with the containers running MBean Server.
- I provide MBeanExporter with references to beans that I want to expose via JMX.
- Finally my management bean is Log4jLevelChanger is registered with Spring.

One thing to note here is that the parameter names are p1 (for loggerName) and p2 for (level). This is because I have not provided any meta data about the parameters. When I do my blog on using JMX+Spring+CommonsAttributes under Weblogic 8.1, you will see how this can be resolved. BTW for jdk 1.4 based Spring projects you must use commons attributes tags provided by Spring to register and describe your beans as JMX beans. The initial minor learning curve will save you tons of time later.





Weblogic provided a jsp page known as Log4jAdmin which we used with very good results for this purpose.
Reply to this
I considered this exact same approach but did not realize there was a ready-made page available at the dev2dev site. For a lot of projects that may be just about good enough. The advantage with JMX is that you can have operations folks who are using a JMX-supporting management tool (such as openview or jmanage) to control certain behaviour from the tool rather than visit the individual applications page (in this case log4j being just one of the options).
Thanks for pointing me to the dev2dev posted component.
Reply to this
Hi,
Really helpful article,got me reading on mbeans and spring.. and since BEA does not recommend using deamon threads and configureAndWatch is just that.
But it would be more helpful if you could provide the weblogic 8.1 mbean article too
Cheers,
kitty
Reply to this
Very useful information. Thanks.
In order to change for whole application you can use
Level lvl = Level.toLevel(level);
Logger.getRootLogger().setLevel(lvl);
This avoids having sending the loggerName.
Reply to this
Great example! Here is one that shows what to do if you're not using Spring:
http://fahdshariff.blogspot.com/2008/06/change-logging-levels-using-jmx-howto.html
Reply to this