Monitoring complex attributes with the JMX Monitor API

Eamonn McManus, the JMX spec lead, has already blogged about the two biggest changes to the JMX API in Mustang: MXBeans and Descriptors.

I would like to talk now about a minor improvement that has been made to the JMX Monitor API in Mustang that allows to monitor simple numerical types or string types buried inside complex types in an MBean attribute.

A bit of history

The JMX Monitor API allows you to sample an attribute (property) of an MBean periodically and send an event if it exceeds a given threshold. A Monitor can sample the same attribute in many MBeans but it must have the same threshold for all of them. If you need to sample more than one attribute or if you need to have more than one threshold, then you must have more than one Monitor. Therefore, a Monitor is an MBean that periodically observes the value of an attribute in one or more other MBeans. If the attribute meets a certain condition, the Monitor emits a MonitorNotification.

There are three kinds of Monitors:

  • A CounterMonitor observes attributes of integer type. Each observed attribute has an associated threshold value. A notification is sent when the attribute exceeds its threshold.
  • A GaugeMonitor observes attributes of numerical type. Each observed attribute has an associated high threshold and low threshold. Notifications are sent when the attribute exceeds the high or low thresholds.
  • A StringMonitor observes attributes of type String. A notification is sent when an observed attribute becomes equal and/or not equal to a given string.

In Mustang, the JMX Monitor API supports complex types. Previously with the JMX Monitor API, you could only monitor an attribute of simple type. Often, the value you want to monitor is buried inside a more complex type. For example, if you are dealing with the J2EE instrumentation defined by JSR 77, then to set a monitor on a servlet's service time, you want to get the ServiceTime attribute for the servlet and monitor serviceTime.getMaxTime(). The JMX Monitor API specification is changed so that you can monitor ServiceTime.maxTime to get this effect. The detailed specification is in javax.management.monitor.

Let's see how this new feature works with an example

Imagine a simple MXBean "QueueSampler" that manages a resource of type "Queue<String>". Of course, this would also work for a Standard MBean defining the same management interface. The MXBean declares a getter "getQueueSample" that takes a snapshot of the queue when invoked and returns a Java class "QueueSample" that bundles the following values together: the time the snapshot was taken, the queue size and the head of the queue at that given time.

The QueueSamplerMXBean interface looks like:

public interface QueueSamplerMXBean {
    ...
    public QueueSample getQueueSample();
    ...
}

The QueueSampler class implements that interface following the MXBean rules:

public class QueueSampler implements QueueSamplerMXBean {
    ...
    public QueueSampler(Queue<String> queue) {
        this.queue = queue;
    }

    public QueueSample getQueueSample() {
        synchronized (queue) {
            return new QueueSample(new Date(), queue.size(), queue.peek());
        }
    }
    ...
}

and the QueueSample class looks like:

public class QueueSample {
    ...
    public QueueSample(Date date, int size, String head) {
        this.date = date;
        this.size = size;
        this.head = head;
    }

    public Date getDate() {
        return date;
    }

    public int getSize() {
        return size;
    }

    public String getHead() {
        return head;
    }
    ...
}

Now let's create a CounterMonitor MBean to monitor the "size" attribute in "QueueSample", register it in the MBeanServer and start it. Using the new dot(.) notation for the monitor's observed attribute, the CounterMonitor will observe the "QueueSample.size" complex attribute in the QueueSampler MXBean every two seconds and emit a threshold notification if the queue contains five or more elements. The CounterMonitorMBean is a NotificationEmitter so JMX clients interested in the MonitorNotifications emitted by this MBean can add listeners to it through the addNotificationListener method.

...
CounterMonitorMBean monitor = new CounterMonitor();
monitor.addObservedObject(ObjectName.getInstance("com.example.mxbeans:type=QueueSampler"));
monitor.setObservedAttribute("QueueSample.size");
monitor.setNotify(true);
monitor.setInitThreshold(5);
monitor.setGranularityPeriod(2000);
mbs.registerMBean(monitor, ObjectName.getInstance("com.example.mxbeans:type=CounterMonitor"));
monitor.start();
...

Here we've seen how to monitor simple types inside complex types such as CompositeData. In this example the "QueueSample" class is converted into a CompositeData by the MXBean framework.

The JMX Monitor API can also monitor the length of a given array which is buried inside a complex type by appending the suffix ".length" to the name of the property returning the array.

For example, if an MBean attribute "ComplexAttribute" returns a complex type "ComplexAttribute" with a property "arrayAttribute" which returns an array we could monitor the length of the returned array with the following observed attribute string "ComplexAttribute.arrayAttribute.length".

public class ComplexAttribute {
    ...
    public Integer[] getArrayAttribute();
    ...
}

public interface ArrayLengthMBean {
    ...
    public ComplexAttribute getComplexAttribute();
    ...
}

public class ArrayLength implements ArrayLengthMBean {
    ...
    public ComplexAttribute getComplexAttribute() {...};
    ...
}

Now let's create a CounterMonitor MBean to monitor the array's length. The CounterMonitor will observe the "ComplexAttribute.arrayAttribute.length" complex attribute in the ArrayLength MBean every two seconds and emit a threshold notification if the array length equals or exceeds five elements.

...
CounterMonitorMBean monitor = new CounterMonitor();
monitor.addObservedObject(ObjectName.getInstance("com.example.mbeans:type=ArrayLength"));
monitor.setObservedAttribute("ComplexAttribute.arrayAttribute.length");
monitor.setNotify(true);
monitor.setInitThreshold(5);
monitor.setGranularityPeriod(2000);
...

If you were thinking about monitoring individual elements of arrays, something similar to "ComplexAttribute.arrayAttribute[4]" to monitor the fifth element in the arrayAtttribute array, then I'll have to let you know that this is something which is not supported by the JMX Monitor API.

Properties representing complex types other than "CompositeData" or "array length" are introspected using the Java Beans introspector. This is very powerful as it allows to map property names to arbitrary methods by means of PropertyDescriptors. The value being monitored will be the result of calling the property's read method in the PropertyDescriptor.

For example, a PropertyDescriptor can be used to map the property "name" to the method Enum.name(). This PropertyDescriptor will allow to monitor enums defined in a Standard MBean management interface with a StringMonitor. Enums defined in MXBean interfaces don't require this additional level of indirection as they get mapped into Strings by the MXBean framework and can be monitored directly with a StringMonitor.

public enum TrafficLight { GREEN, YELLOW, RED };

// Java Beans Introspector:
// For each class "Foo", explicit information may be available if there exists a corresponding
// "FooBeanInfo" class that provides a non-null value when queried for the information.
public class TrafficLightBeanInfo extends SimpleBeanInfo {
    public PropertyDescriptor[] getPropertyDescriptors() {
        return new PropertyDescriptor[] { new PropertyDescriptor("name", TrafficLight.class, "name", null) };
    }
}

public interface TrafficMBean {
    ...
    public TrafficLight getTrafficLight();
    ...
}

public class Traffic implements TrafficMBean {
    ...
    public TrafficLight getTrafficLight() {...};
    ...
}

Now let's create a StringMonitor MBean to monitor the value of the TrafficLight enum. The StringMonitor will observe the "TrafficLight.name" complex attribute in the Traffic MBean every two seconds and emit a match notification if the attribute value matches the string to compare value, i.e. when the traffic light becomes RED.

...
StringMonitorMBean monitor = new StringMonitor();
monitor.addObservedObject(ObjectName.getInstance("com.example.mbeans:type=Traffic"));
monitor.setObservedAttribute("TrafficLight.name");
monitor.setNotifyMatch(true);
monitor.setNotifyDiffer(false);
monitor.setStringToCompare("RED");
monitor.setGranularityPeriod(2000);
..

Eager to learn more about the JMX Monitor API? Go to javax.management.monitor and have fun!

Comments:

Hi Miguel,
thanks for your very useful post.

Only a question: in some circumstances I've to monitor, via CounterMonitor, all MBean attributes. I've to use setObservedAttribute for all MBean attributes? ..or maybe is possible to monitor an entire MBean?...I've seen that void setObservedObject(ObjectName object)
is deprecated

thanks in advance
luke

Posted by luke on December 04, 2007 at 01:50 AM CET #

You cannot monitor an entire MBean with a single monitor because you can only specify a single attribute name.

The idea behind the current monitor specification is to be able to monitor the same attribute in multiple MBeans.

Posted by Luis-Miguel Alventosa on December 04, 2007 at 02:35 AM CET #

I'm sorry, I don't know I correctly understood.

A counterMonitor can observe only one attribute (so I can invoke setObservedAttribute only once), but if I've the same attribute (with the same meaning,same threshold...) in different MBeans I can monitor all together (I think invoking addObservedObject for every MBean)

I don't know if I've correctly understood

thanks a lot

Posted by luke on December 04, 2007 at 04:53 AM CET #

That's correct!

Posted by Luis-Miguel Alventosa on December 04, 2007 at 05:57 AM CET #

Only another question, what is the exact meaning of CounterMonitor.getDerivedGauge(javax.management.ObjectName name) method?

It's seems that always return 0 (but I'm not use differenceMode, so I argue that maybe only in this case it's the difference between two sample).

thanks

Posted by luke on December 17, 2007 at 12:24 AM CET #

When a given JMX CounterMonitor is used to monitor the same attribute on several MBeans, calling CounterMonitor.getDerivedGauge(ObjectName) returns the last sampled value of the attribute on the MBean denoted by the supplied ObjectName. When the monitor is used in difference mode the derived gauge is the difference between the two last sampled values.

Have a look at the javax.mangement.monitor.CounterMonitor javadoc to get more detailed info.

Posted by Luis-Miguel Alventosa on December 17, 2007 at 02:15 PM CET #

I've created a gaugeMonitor and a counterMonitor, but while gaugeMonitor DerivedGauge attribute returns correctly sampled value, counterMonitor DerivedGauge attribute always returns 0.

It's strange that in HtmlAdaptor ObservedObject view
I see the attribute corrected values

thanks

Posted by luke on December 18, 2007 at 12:46 AM CET #

Hi Luke,

Your problem seems to be due to a too small granularity period, i.e. less than 1000 ms.

Regards,
Luis

Posted by Luis-Miguel Alventosa on December 19, 2007 at 06:16 AM CET #

Hi,
now I've created a Class that would generate MonitorNotification jmx events. I'm not sure how I can create and populate a MonitorNotification Object. I.e. MonitorNotification has methods like getTrigger(), getDerivedGauge() and getObservedAttribute(), but not correspondent set methods. So I don't know how I can set trigger and derivedGauge in a monitorNotification

thanks in advance

Posted by luca on January 16, 2008 at 03:06 AM CET #

I'm not sure what you mean by having a class that generates MonitorNotification events but if what you are trying is to implement your own monitor by extending the JMX Monitors you should know that the MonitorNotification's constructor is package protected and you won't be able to instantiate it.

Posted by Luis-Miguel Alventosa on January 20, 2008 at 05:33 PM CET #

Yes, I've to monitor attributes in some MBean servers on remote jvm.
So in my monitor class, I extend NotificationBroadcasterSupport, and at the moment I send a simple Notification when some event occurs. The problem is that when a threshold exceeded event occurs, I can't send a MonitorNotification but only a Notification (I don't know where I can specify threshold and attributeValue).

Posted by luca on January 21, 2008 at 05:15 AM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
About

lmalvent

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today