JMX meets Log4J
It doesn’t take much to find that this is not a new and revolutionary idea, but nonetheless, those who never gave it much thought until today (like me…) may benefit from this small tip.
One thing that bothered me for quite some time was that whenever I encountered some bugs, exceptions, or even just wanted to better understand how my application behaved at runtime, I stopped the application (during development phase of course), changed the log4j configuration and restarted it.
Today, after repeating this routine a few times, for the first time I told myself “There must be a better way…”. It didn’t take me long to feature out that spring’s jmx support and jdk 5 practically hand me the solution to this problem on a silver plate - Just create a simple management bean that controls the log levels for categories, export this bean as an MBean using spring superb JMX’s support, and use jdk5 jconsole application to manage the logging levels. Here’s a quick recipe:
1. Create the management bean:
public class Log4jMBean {
public void activateInfo(String category) {
LogManager.getLogger(category).setLevel(Level.INFO);
}
public void activateDebug(String category) {
LogManager.getLogger(category).setLevel(Level.DEBUG);
}
public void activateWarn(String category) {
LogManager.getLogger(category).setLevel(Level.WARN);
}
public void activateError(String category) {
LogManager.getLogger(category).setLevel(Level.ERROR);
}
public void activateFatal(String category) {
LogManager.getLogger(category).setLevel(Level.FATAL);
}
}
2. Export the bean in the application context.
<beans>
. . .
<bean id=
loggingMBean
class=Log4jMBean
/>
<bean id=exporter
class=org.springframework.jmx.export.MBeanExporter
>
<property name=beans
>
<map>
<entry key=bean:name=logging
value-ref=loggingMBean
/>
</map>
</property>
</bean>
. . .
</beans>
3. Run your application with the following system property -Dcom.sun.management.jmxremote
4. Run jconsole tool (found at JAVA_HOME/bin)
5. Look for the exported MBean (”logging” in our case)
6. Change the log level of categories just by invoking the management methods.
Done!
After googling a bit, I found out that loads of people already thought about this solution (hell… there’s even an MBean class in the jdk that does the same for jdk’s logging mechanism). Unfortunately, I only gave it a thought today - if I had done so long time ago it would have probably saved me quite a lot of time… So if it’s new to you aswell, stop wasting your time and add it to your project today.
Note: This can be quite useful at production phase as well, but keep in mind that a more secured schema should be applied - possibly using jdk’s jmx security support (for more information, see the resources below).
Some resources:
Monitoring and Management Using JMX
Spring JMX support
January 14th, 2006 at 7:21 am
You can achieve the same effect by configuring log4j with Properties.configureAndWatch(…) method. In that case, log4j automatically rescans your log4j.properties file when you make changes in it. The only benefit of JMX way is ability to change logging levels on the remote applications, but it makes little sense, because logs are usually written to files on local file system.
The other problem with provided implementation is requirement to give FQN of log category to method invocations. This lowers usability of solution. There are way to fix it - create separate MBean for each category with methods like setDebug(), setInfo() etc. However, I have to idea how this may be done without patching log4j or using AOP.
August 10th, 2006 at 5:14 pm
I was wondering to know, will it modify any properties file and how do we enable/disable specific logging option and also would like to know if we have to set/unset the logging at the class level, how do we achieve that?
Thanks
Kris