Friday, June 13, 2008

Change Logging Levels using JMX [Howto]

This handy example shows you how you can use Java Management Extensions (JMX) to change your application's logging level.

Step 1: Create your management interface which consists of all the attributes which can be read or set and all the operations that can be invoked. In this case, we want to change the logging level of our application.

public interface MyAppMBean{
    public void setLoggingLevel(String level) ;
    public String getLoggingLevel() ;
}
Step 2: Create a class which implements the MBean interface
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.sun.jdmk.comm.HtmlAdaptorServer;

public class MyApp implements MyAppMBean{

    private static Logger logger = Logger.getLogger(MyApp.class);

    public void go() throws Exception{
        while(true){
            logger.debug("DEBUG") ;
            logger.info("INFO") ;
            Thread.sleep(2000);
        }
    }

    public void setLoggingLevel(String level){
        logger.info("Setting logging level to: " + level);
        Level newLevel = Level.toLevel(level, Level.INFO);
        Logger.getRootLogger().setLevel(newLevel);
    }

    public String getLoggingLevel(){
        return Logger.getRootLogger().getLevel().toString() ;
    }
}
Step 3: Register the MBean with the MBeanServer. Also register an HTMLAdaptorServer which allows us to manage an MBeanServer through a web browser.
public static void main(String[] args) throws Exception{
    MyApp app = new MyApp() ;
    ObjectName objName = new ObjectName("MyApp:name=MyApp");
    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    server.registerMBean(app, objName);

    int portNumber=9393;
    ObjectName htmlName = new ObjectName(
       "MyApp:name=MyAppHtmlAdaptor,port="+portNumber) ;
    HtmlAdaptorServer html = new HtmlAdaptorServer(portNumber);
    html.setPort(portNumber);
    server.registerMBean(html, htmlName);
    html.start();
    app.go();
}
Step 4: Compile. Make sure you have log4j, jmxtools and a log4j properties file in your classpath

Step 6: Run MyApp. You need to add the following JVM properties:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Step 5: Open jconsole
  • Click on MyApp and press Connect
  • Go to the MBeans tab and choose MyApp from the tree on the left
  • You can then change your Logging Level while the application is running!
Step 6: Open the web console
  • Go to http://localhost:9393
  • Click on name=MyApp
  • Change the LoggingLevel!

2 comments:

  1. Anonymous12:52 PM

    Hi Fahd,
    I am working on an app which is running on WAS , i will have to compile the whole code u mentioned above and then package it into a jar and deploy it onto the same server where my application is running ???
    then only i would be able to get all the logger instances using LogManager one by one in the above implementation and change the level ??
    is my understanding right about this concept please correct me if im right .

    ReplyDelete
  2. No one may see this because of all the SPAM comments you've not deleted, but this works. Thanks.
    BTW, I'm running Java 7 and did not have to add the com.sun.management.jmxremote options to my JVM

    ReplyDelete