Appendix A. JMX Monitoring Examples

Table of Contents

A.1. Servlet Thread Info Monitoring Example
A.2. Thread Pool Information Monitoring Example
A.3. JVM Information Monitoring Example
A.4. JDBC Datasource(DB Connection Pool) Monitoring Example

This appendix introduces four examples of monitoring JEUS MBean information.

In the examples, RemoteMBeanServerFactory class is used to get information from MBean servers. For other methods of getting information from MBean servers, refer to "Chapter 3. JMX Application Development".

The example below monitors information about web engine listeners. In Particular, the thread pool and each thread are monitored.

The information monitored is:

  • The number of currently assigned worker threads (current thread count)

  • The maximum number of threads allowed in the thread pool (max thread count)

  • The number of clients in the wait-queue (wait queue count)

See the following example of monitoring the servlet thread information.

package monitoring;

import java.util.*;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.ObjectInstance;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanServerInvocationHandler;

import jeus.management.j2ee.servlet.*;

public class ServletThreadInfo {
    public void showInfo(MBeanServerConnection mBeanServer, String targetName)
    throws Exception {
        System.out.println("=== Servlet Thread Info ===");

        // Get the object name of the servlet engine using JMX Standard API 
        // Otherwise, the object name could be queried through MBeanServer.
        // Please see JEUS MBean API javadoc for more concrete name, key properties.
        ObjectName name = new ObjectName("JEUS:jeusType=WebEngine,J2EEServer=" + 
                          targetName + ",*");
        Set names = mBeanServer.queryMBeans(name, null);
        if (names == null || names.size() == 0) {
            System.out.println("there is no servlet engine");
            return;
        }

        // Choose one servlet engine from the returned object names
        Iterator it = names.iterator();
        ObjectName fullName = null;
        while (it.hasNext()) {
            fullName = ((ObjectInstance)it.next()).getObjectName();
            break;
        }

        assert fullName != null;

        WebEngineMoMBean engineMBean = 
       (WebEngineMoMBean)MBeanServerInvocationHandler.newProxyInstance(mBeanServer,
       fullName, WebEngineMoMBean.class, false);

        // Get listeners from WebEngine
        String[] listeners = engineMBean.getWebListeners();
        if(listeners == null || listeners.length == 0){
        	return;
        }
        
        String webEngineName = engineMBean.getObjectName().getKeyProperty("name");
        for(int i = 0; i < listeners.length; i++) {
           ObjectName listener = new ObjectName(listeners[i]);
        
           WebListenerMoMBean listenerMBean= 
            (WebListenerMoMBean) MBeanServerInvocationHandler.newProxyInstance
            (mBeanServer, listener, WebListenerMoMBean.class, false);

            String[] tpoolNames = listenerMBean.getThreadPools();

            // Get stats from thread pools
            if (tpoolNames != null) {
               showThreadPoolStats(mBeanServer, webEngineName, tpoolNames);
            }    
        }
        System.out.println();
    }

    private void showThreadPoolStats(MBeanServerConnection mBeanServer, 
                                     String contextGroupName, 
                                     String[] tpoolNames) 
    throws MalformedObjectNameException {
        for (int k = 0; k < tpoolNames.length; k++) {
          ObjectName tpool = new ObjectName(tpoolNames[k]);
          System.out.println("[MBean] " + tpool);
          ThreadPoolMoMBean tpoolMBean = 
            (ThreadPoolMoMBean)MBeanServerInvocationHandler.newProxyInstance(
             mBeanServer,tpool, ThreadPoolMoMBean.class, false);
          ThreadPoolStatsImpl stats = (ThreadPoolStatsImpl) tpoolMBean.getstats();
          System.out.println("Listener: " + contextGroupName 
                + "/" + tpool.getKeyProperty("name"));
         System.out.println("- current thread count      : " 
                + stats.getAllThreadCount().getCount());
         System.out.println("- max thread count          : " 
                + stats.getMaxThreadCount().getCount());

         if (stats.getStatisticVersion() == ThreadPoolStatsImpl.NIO_VERSION) {
                // pipeline
                System.out.println("- total connection count    : " 
                    + stats.getTotalConnectionCount().getCount());
                System.out.println("- max queue count           : " 
                    + stats.getMaxQueueCount().getCount());
                System.out.println("- current queue count       : " 
                    + stats.getCurrentQueueCount().getCount());
                System.out.println("- remain queue count        : " 
                    + stats.getRemainQueueCount().getCount());
                System.out.println("- peak queue count          : " 
                    + stats.getPeakQueueCount().getCount());
                System.out.println("- total queue count         : " 
                    + stats.getTotalQueueCount().getCount());
                System.out.println("- difference queue 1m count  : " 
                    + stats.getDifferenceQueue1MCount().getCount());
                System.out.println("- difference queue 5m count  : " 
                    + stats.getDifferenceQueue5MCount().getCount());
                System.out.println("- difference queue 15m count : " 
                    + stats.getDifferenceQueue15MCount().getCount());
                System.out.println("- overflow queue count      : " 
                    + stats.getOverflowCount().getCount());
                System.out.println("- average queue time        : " 
                    + stats.getQueueWaitTimeAverage().getCount() + "(ms)");
            } else {
                System.out.println("- wait queue count          : " 
                    + stats.getWaitQueueCount().getCount());
            }

            System.out.println();
        }
    }
}

In the following example of monitoring the thread pool information, thread pool states used in JEUS are monitored.

The information monitored is:

  • Thread pool size

  • Thread pools statistics

  • Thread execution time statistics

  • Wait-queue size statistics (size stats)

See the following example of monitoring the thread information.

package monitoring;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.j2ee.statistics.TimeStatistic;
import javax.management.j2ee.statistics.RangeStatistic;
import javax.naming.*;

import jeus.jndi.JNSConstants;
import jeus.management.JMXConstants;
import jeus.management.RemoteMBeanServerFactory;
import jeus.management.j2ee.thread.ThreadPoolMBean;
import jeus.management.j2ee.thread.stats.ThreadPoolStats;


public class ThreadPoolInfo {
    public void showInfo(MBeanServerConnection mBeanServer, String name)
    throws Exception {
        System.out.println("=== ThreadPool Info ===");

        // Get the object names of the thread pools. 
        // Please see JEUS MBean API javadoc for more concrete name, key 
        // properties.
        ObjectName objectNames = new ObjectName("JEUS:jeusType=ThreadPool,*");
        Set tpMBeans = mBeanServer.queryMBeans(objectNames, null);

        for (Iterator i = tpMBeans.iterator(); i.hasNext();) {
          ObjectName mbeanName = ((ObjectInstance) i.next()).getObjectName();

          // thread pool name
          System.out.println("[Thread-pool : " 
                + mbeanName.getKeyProperty("name") + "]");

          System.out.println("[MBean] " + mbeanName);

          ThreadPoolMBean pool = 
             (ThreadPoolMBean)MBeanServerInvocationHandler.newProxyInstance(
                   mBeanServer, mbeanName, ThreadPoolMBean.class, false);

          // ThreadPool Size
          System.out.println("-size : " + pool.getPoolSize());
          System.out.println("-core size : " + pool.getCorePoolSize());
          System.out.println("-largest Size : " + pool.getLargestPoolSize());
          System.out.println("-max size : " + pool.getMaximumPoolSize());
          System.out.println("-queue size : " + pool.getWorkQueueSize());

          // ThreadPool Stats
          ThreadPoolStats stats = (ThreadPoolStats) pool.getstats();
          TimeStatistic executionTimeStats = stats.getThreadExecutionTime();
          TimeStatistic waitingTimeStats = stats.getQueueWaitingTime();

          System.out.println("# Thread Execution Time Stats");
          System.out.println("--unit : " + executionTimeStats.getUnit());
          System.out.println("--count : " + executionTimeStats.getCount());
          System.out.println("--min time : " + executionTimeStats.getMinTime());
          System.out.println("--max time : " + executionTimeStats.getMaxTime());

          System.out.println("# Queue Waiting Time Stats");
          System.out.println("--unit : " + waitingTimeStats.getUnit());
          System.out.println("--count : " + waitingTimeStats.getCount());
          System.out.println("--min time : " + waitingTimeStats.getMinTime());
          System.out.println("--max time : " + waitingTimeStats.getMaxTime());
      }
   }
}

In the following example of monitoring the JVM information, JVMs of JEUS nodes or engines are monitored.

The information monitored is:

  • Total JVM size

  • JVM heap size

  • JVM uptime

See the following example of monitoring the JVM information.

package monitoring;

import java.util.Iterator;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.j2ee.statistics.BoundedRangeStatistic;
import javax.management.j2ee.statistics.CountStatistic;
import javax.management.j2ee.statistics.RangeStatistic;

import jeus.management.j2ee.JVMMBean;
import jeus.management.j2ee.statistics.JVMStatsImpl;


public class JVMInfo {
    
    public void showInfo(MBeanServerConnection mBeanServer, String targetName)
    throws Exception {
        System.out.println("=== JVM Statistics ===");

        ObjectName objectName = new ObjectName("JEUS:j2eeType=JVM,name=" 
                                + targetName + ",*");
        Set jvmMBeans = mBeanServer.queryMBeans(objectName, null);

        for (Iterator i = jvmMBeans.iterator(); i.hasNext();) {
            ObjectName objName = ((ObjectInstance) i.next()).getObjectName();
            System.out.println("[MBean] " + objName);
            
            // JVMMBean Stats
            JVMMBean jvm = (JVMMBean)MBeanServerInvocationHandler.newProxyInstance(
                           mBeanServer, objName, JVMMBean.class, false);

            JVMStatsImpl jvmstatsimpl = (JVMStatsImpl) jvm.getstats();
            RangeStatistic totalSize = jvmstatsimpl.getTotalSize();
            BoundedRangeStatistic heapSize = jvmstatsimpl.getHeapSize();
            CountStatistic upTime = jvmstatsimpl.getUpTime();

            // JVM Total Size
            System.out.println("[Total Size]");
            System.out.println("-unit : " + totalSize.getUnit());
            System.out.println("-current : " + totalSize.getCurrent());
            System.out.println("-min size : " + totalSize.getLowWaterMark());
            System.out.println("-max size : " + totalSize.getHighWaterMark());

            // JVM Heap Size
            System.out.println("[Heap Size]");
            System.out.println("-unit : " + heapSize.getUnit());
            System.out.println("-current : " + heapSize.getCurrent());
            System.out.println("-min Size : " + heapSize.getLowWaterMark());
            System.out.println("-max Size : " + heapSize.getHighWaterMark());
            System.out.println("-lower bound : " + heapSize.getLowerBound());
            System.out.println("-upper bound : " + heapSize.getUpperBound());

            // JVM UpTime
            System.out.println("[Up Time]");
            System.out.println("-unit : " + upTime.getUnit());
            System.out.println("-count : " + upTime.getCount());
            System.out.println("-start time : " + upTime.getStartTime());
        }
    }
}

In the following example of monitoring the JDBC datasource (DB connection pool), DB connection pools in JEUS servers are monitored. The example also shows how to obtain an MBean connection by using the javax.management.remote.JMXConnector class.

The details of the example are:

  • Connects to a specific MBean server.

  • Queries the jeus.management.j2ee.JDBCResourceMBean object, and periodically records information about the current connection pools to a file.

    Note

    A connection pool is created when the service is actually called.

See the following example of monitoring the DB connection pool.

package monitoring;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.j2ee.statistics.JDBCConnectionPoolStats;
import javax.management.j2ee.statistics.JDBCStats;
import javax.management.remote.JMXConnector;
import javax.naming.Context;
import javax.naming.InitialContext;

import jeus.management.JMXConstants;
import jeus.management.j2ee.JDBCResourceMBean;

public class DBStatsClient {
    public static void main(String[] args) {
        String serverName = "changeplz"; //e.g. server1

        Hashtable<String, Object> env = new Hashtable<String,Object>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "jeus.jndi.JNSContextFactory");
        env.put(Context.URL_PKG_PREFIXES, "jeus.jndi.jns.url");
        env.put(Context.PROVIDER_URL, "localhost:9736");
        MBeanServerConnection mbsc;
        try {
            InitialContext ctx = new InitialContext(env);
            JMXConnector connector = (JMXConnector)ctx.lookup(
                    JMXConstants.JNDI_BINDING_PREFIX + serverName);
            connector.connect();
            mbsc = connector.getMBeanServerConnection();
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        System.out.println("mbean server connection successfully established");
        Set mbeans;
        try {
            ObjectName dbstats = new ObjectName("JEUS:j2eeType=JDBCResource,*");
            mbeans = mbsc.queryMBeans(dbstats, null);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        System.out.println("Successfully get JDBCResource");
        File file = new File(serverName+".log");
        FileOutputStream stream = null;
        try {
            stream = new FileOutputStream(file);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        while(true) {
          for (Iterator iter = mbeans.iterator();iter.hasNext();) {
             ObjectName jdbcResourceMBeanName = 
                    ((ObjectInstance) iter.next()).getObjectName();
             JDBCResourceMBean jdbcResource = 
                (JDBCResourceMBean) MBeanServerInvocationHandler.newProxyInstance(
                    mbsc, jdbcResourceMBeanName,
                    JDBCResourceMBean.class, false);
             JDBCStats jdbcStats = (JDBCStats) jdbcResource.getstats();
             SimpleDateFormat format = new SimpleDateFormat("[MM-dd]HH:mm:ss");
             StringBuilder builder = new StringBuilder();
             builder.append("[STA] ");
            for (JDBCConnectionPoolStats cpStats : jdbcStats.getConnectionPools())
            {
                String output =format.format(new Date(System.currentTimeMillis()))
                        + " name:[" +cpStats.getJdbcDataSource() + "]"
                        + " total:[" +cpStats.getPoolSize().getCurrent() +"]"
                        + " use:[" + (cpStats.getPoolSize().getCurrent() 
                                 - cpStats.getFreePoolSize().getCurrent()) +"]  ";
                builder.append(output);
             }
           builder.append("/n");
           try {
                    stream.write(builder.toString().getBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}