iAS 7.0 SE Monitoring Framework

### Monitoring framework for iAS 7.0 SE.

Note:

- This writeup assumes some familiarity with JMX, specifically the terms MBeanServer, MBean and DynamicMBean. Please refer to JMX documentation at http://java.sun.com/products/JavaManagement/index.html for more information
- This API is project private and the status is unstable, meaning that it is likely to change in every release.

#### Overview

iAS 7.0 SE monitoring framework is built on top of infrastructure provided by JMX (Java Management Extenstions). A set of MBeans dedicated to monitoring are registered to the MBeanServer running in every instance. These MBeans are queried from the administration server whenever a user requests statistics.

The communication between admin server and adminitered instance is done over the admin channel. For more details, please see the admin channel package description. Admin channel is used to send notifications from admin server to the instance. For monitoring, the notification MonitoringEvent is used. The notification supports four actions - start monitoring, stop monitoring, get monitoring data and list monitorable components.

A set of MBeans dedicated to monitoring task are created and registered to MBean server by the components that need to be monitored. These MBeans are organized in a tree structure with a pre defined root. Monitoring MBeans are identified by a type, name and a parent. The tree can be extended in any direction as long as a MBean does not conflict with any other MBean under its parent.

#### MonitoredObectType

An instance of this class rpresents the type of monitoring MBean. This class defines various `public static` constants representing known monitoring MBean types.

A type can be designated as singleton, which will enforce that only one MBean of that type exists under a given node of Monitoring MBean tree. For example, ejb pool is a singleton, because for every stateless session bean there is one pool.

Description

#### BaseMonitorMBean

This is the abstract super class of all monitoring MBeans. It implements the JMX interface DynamicMBean and also provides start and stop methods to manage monitoring state. All the basic tree management features are also available through this object.

Description

#### GenericMonitorMBean

This is a simple concrete sub-class of BaseMonitorMBean that exposes no monitorable statistics but can be used to group other monitoring MBeans by building up the tree of Monitoring MBeans. The only significant implementation in this class is those of methods startMonitoring and stopMonitoring call the same method on all its children,

Description

#### MonitoringHelper

A helper (utility) class to manage monitoring MBeans. This class uses GenericMonitorMBean to build up the tree, whenever a node does not exist in the tree.

Description

#### MBean Naming

The object name for monitoring MBeans is based on the position of the MBean in the tree. The name and type of MBean is represented by the property called `name` and `mclass` respectively. In addition to that, all object names contain properties describing its parent node.

The root MBean for monitoring is named `ias:type=monitor,mclass=root,name=root,instance-name=ias1`. All MBeans in iAS 7.0 SE have the same domain `ias`. The property `type` is required by MBeanServer and should always be set to `monitor`. The property `instance-name` is also required by the MBeanServer implementation and must be set to the name of the server instance. As there is only one root monitoring MBean, its name is always `root`. The value for mclass is derived from MonitoredObjectType.

If there is a MBean registered to monitor an application called app1, to its parent, the root monitoring MBean, the name will be `ias:type=monitor,mclass=application,name=app1,root=root,instance-name=ias1`. In addition to the required properties -- `type`, `instance-name`, `mclass` and `name`, the object name contains a reference to the parent MBean by applying a transform to the properties `mclass` and `name` of the parent -- the transform is to convert the value of `mclass` attribute to a property name and the value of the `name` attribute to the value of that property. A general rule is that a child MBean name contains all properties other than `mclass` and `name` with same values as in its parent.

More examples, a monitoring MBean for ejb module mod1 in application app1 will be named `ias:type=monitor,mclass=ejb-module,name=mod1,application=app1,root=root,instance-name=ias1`. A monitoring MBean for stateless session bean bean1 in module mod1 and application app1 will be named `ias:type=monitor,mclass=stateless-bean,name=bean1,ejb-module=mod1,application=app1,root=root,instance-name=ias1`.

#### CLI Name Mapping

CLI names address MBeans under root monitoring MBean in any instance. The CLI names are of the form --

          instanceName([.type[.name])*[.(star|attrName)]
      where,
         instanceName is name of server instance,
         type is derived from MonitoredObjectType,
         name is monitored component name,
         star is the character * (denotes all attributes)
         attrName is the name of the attribute

The other rules for CLI names are --

1. (star|attrName) is required only for GET command. It should not be present for other commands.
2. For a singleton MonitoredObjectType, name must not be specified. For non-singleton types both name and type must be specified.

For example, CLI name `ias1.application.myApp.module.fortune_jar.stateless-bean.fortune.pool` addresses the MBean monitoring pool for stateless session bean named fortune contained within the module fortune_jar in the J2EE application myApp.

#### Monitorable Attribute Type

There is a package com.sun.enterprise.admin.monitor.types that defines types for monitorable attributes (See Description). JMX supports three different types of Monitorable attributes -- Counter, Gauge and String and there are classes corresponding to them in this package.

JMX model for monitoring suggests one MBean for every monitorable attribute. The JMX monitoring MBean acts as an observer of the statistic exposed by some other MBean and collects statistic at pre defined interval. It also manages notification for thresold values. For iAS 7.0 SE, a simpler approach has been taken and an attempt has been made to collect as much data as possible, so that transition to full JMX model will be easier.

Another expectation for iAS 7.0 SE is that all monitorable attribute values have a simple `toString()` representation that is used to display statistic on the user interface.

#### Tutorial

##### Step 1: Create a Monitoring MBean

The first step is to determine the statistics that need to be exposed, their names and types (as defined in the package com.sun.enterprise.admin.monitor.types. A naming convention guide for monitorable attributes is maintained by user experience group which should be consulted while choosing names. The attributes should be exposed through MBeanInfo interface in a sub-class of BaseMonitorMBean and the MBean should then be registered to the tree of Monitoring MBeans.

##### Step 1a: Define Attributes

The goal of this step is to create/reference objects that will allow creation of a MBeanInfo object and also provide enough information to implement methods `getMonitoringMetaData()` and `getMonitoredAttributeValues()`. Following is a sample implementation suitable for use by other protected methods in BaseMonitorMBean --

        public class MyMonitorMBean extends BaseMonitorMBean {

            /**
             * A 2-d array initialized to attribute names and their types
             */
            private static Object[][] attrNameTypeArray = {
                    {"context-root", StringMonitoredAttributeType.DEFAULT},
                    {"count-requests", Counter.INTEGER},
                    {"average-response-time-seconds", Counter.INTEGER},
                    {"count-servlets-deployed", Counter.INTEGER}
                };

As stated earlier, the goal is to provide easy implementation of the methods `getMBeanInfo()`, `getMonitoringMetaData()` and `getMonitoredAttributeValues()`, so if you have other ways of implementing those methods, you do not need to declare a 2-d object array of monitorable attribute names and types.

##### Step 1b: Create MBeanInfo

This step is relevant only if you used 2-d object array in Step 1a. Continuing on from previous example --

            /**
             * Map of attribute names and their types
             */
            private static Map attrNameTypeMap;

            /**
             * Info on this MBean
             */
            private static MBeanInfo mBeanInfo;

            static {
                attrNameTypeMap = createAttrNameTypeMap(attrNameTypeArray);
                mBeanInfo = createMBeanInfo(attrNameTypeMap);
            }

The above steps create an instance of `MBeanInfo` that can be returned directly in the implementation for `getMBeanInfo()` --

            /**
             * Provides the exposed attributes and actions of the monitoring MBean using
             * an MBeanInfo object.
             * @return An instance of MBeanInfo with all attributes and actions exposed
             *         by this monitoring MBean.
             */
            public MBeanInfo getMBeanInfo() {
                return mBeanInfo;
            }

##### Step 1c: Implement getAttribute

The method `getAttribute()` is expected to return the value of specified monitored attribute and the code for that will vary greatly among various components being monitored. A sample implementation can be --

            /**
             * Obtains the value of a specific monitored attribute.
             * @param attribute The name of the attribute to be retrieved
             * @return The value of the attribute retrieved.
             * @throws AttributeNotFoundException if attribute name is not valid
             */
            public Object getAttribute(String attribute) {
                Object retval = null;
                if (attribute.equals(name1)) {
                    retval = obj1.getAttr1();
                } else if (attribute.equals(name2)) {
                    retval = obj2.getAttr2();
                } else {
                    throw new AttributeNotFoundException("Invalid attribute!");
                }
                return retval;
            }

Another method `getAttributes` can be used to get values for more than one attributes in same call. This method should also be implemented in best possible way. At the minimum, the implementation can call getAttribute for every attribute that is on its parameter list.

##### Step 1d: Implement other abstract methods

The remaining abstract methods that must be implemented are `getMonitoringMetaData()` and `getMonitoredAttributeValues()`. A simple implementation that works alongwith the code in Step 1a and 1b above is --

            /**
             * Get a map of monitored attribute names and their types. The keys
             * in the map are names of the attribute and the values are their
             * types. The type value are instances of class
             * com.iplanet.ias.monitor.type.MonitoredAttributeType (or its
             * sub-classes)
             *
             * @return map of names and types of all monitored attributes
             */
            public Map getMonitoringMetaData() {
                return attrNameTypeMap;
            }

            /**
             * Get type of the specified monitored attribute.
             */
            public MonitoredAttributeType getAttributeType(String attrName) {
                    MonitoredAttributeType type = null;
                if (attrNameTypeMap != null && attrName != null) {
                    type = (MonitoredAttributeType)attrNameTypeMap.get(attrName);
                }
                return type;
            }

##### Step 2: Register MBean

The MBean should be created and registered appropriately, for it to become usable by the admin server. The class `MonitoringHelper` provides some ease of use methods to register MBeans.

The other approach is to get the root monitoring MBean by a call to the method `getRootMonitorMBean` in the class `com.sun.enterprise.admin.server.core.AdminService`. The monitoring provider can then traverse through to the node of its interest, starting from the top node in monitoring MBean tree, and then add itself as child to that node using the method `addChild()` from class `BaseMonitorMBean`.

Of course, a combination of the two approaches is to use MonitoringHelper to register an MBean, keep a reference to it and then use addChild method on it to expand the tree further.