Several complete monitoring example applications (including source code and full documentation) are provided when you install Message Queue. You’ll find the examples in your IMQ home directory under /demo/monitoring. Before you can run these clients, you must set up your environment (for example, the CLASSPATH environment variable). For details, see Setting Up Your Environment.
Next are brief descriptions of three examples—Broker Metrics, Destination List Metrics, and Destination Metrics—with annotated code examples from each.
These examples use the utility classes MetricsPrinter and MultiColumnPrinter to print formatted and aligned columns of text output. However, rather than explaining how those utility classes are used, the following code examples focus on how to subscribe to the metrics topic and how to extract information from the metrics messages received.
Notice that in the source files, the code for subscribing to metrics topics and processing messages is actually spread across various methods. However, for the sake of clarity, the examples are shown here as though they were contiguous blocks of code.
The source file for this code example is BrokerMetrics.java. This metrics monitoring client subscribes to the topic mq.metrics.broker and prints broker-related metrics to the standard output.
Example 4–1 shows how to subscribe to mq.metrics.broker.
com.sun.messaging.TopicConnectionFactory metricConnectionFactory; TopicConnection metricConnection; TopicSession metricSession; TopicSubscriber metricSubscriber; Topic metricTopic; metricConnectionFactory = new com.sun.messaging.TopicConnectionFactory(); metricConnection = metricConnectionFactory.createTopicConnection(); metricConnection.start(); metricSession = metricConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); metricTopic = metricSession.createTopic("mq.metrics.broker"); metricSubscriber = metricSession.createSubscriber(metricTopic); metricSubscriber.setMessageListener(this); |
The incoming message is processed in the onMessage() and doTotals() methods, as shown in Example 4–2.
public void onMessage(Message m) { try { MapMessage mapMsg = (MapMessage)m; String type = mapMsg.getStringProperty("type"); if (type.equals("mq.metrics.broker")) { if (showTotals) { doTotals(mapMsg); ... } } private void doTotals(MapMessage mapMsg) { try { String oneRow[] = new String[ 8 ]; int i = 0; /* * Extract broker metrics */ oneRow[i++] = Long.toString(mapMsg.getLong("numMsgsIn")); oneRow[i++] = Long.toString(mapMsg.getLong("numMsgsOut")); oneRow[i++] = Long.toString(mapMsg.getLong("msgBytesIn")); oneRow[i++] = Long.toString(mapMsg.getLong("msgBytesOut")); oneRow[i++] = Long.toString(mapMsg.getLong("numPktsIn")); oneRow[i++] = Long.toString(mapMsg.getLong("numPktsOut")); oneRow[i++] = Long.toString(mapMsg.getLong("pktBytesIn")); oneRow[i++] = Long.toString(mapMsg.getLong("pktBytesOut")); ... } catch (Exception e) { System.err.println("onMessage: Exception caught: " + e); } } |
Notice how the metrics type is extracted, using the getStringProperty() method, and is checked. If you use the onMessage() method to process metrics messages of different types, you can use the type property to distinguish between different incoming metrics messages.
Also notice how various pieces of information on the broker are extracted, using the getLong() method of mapMsg.
Run this example monitoring client with the following command:
java BrokerMetrics
The output looks like the following:
---------------------------------------------------------------- Msgs Msg Bytes Pkts Pkt Bytes In Out In Out In Out In Out -------------------------------------------------------------------- 0 0 0 0 6 5 888 802 0 1 0 633 7 8 1004 1669 |
The source file for this code example is DestListMetrics.java. This client application monitors the list of destinations on a broker by subscribing to the topic mq.metrics.destination_list. The messages that arrive contain information describing the destinations that currently exist on the broker, such as destination name, destination type, and whether the destination is temporary.
Example 4–3 shows how to subscribe to mq.metrics.destination_list.
com.sun.messaging.TopicConnectionFactory metricConnectionFactory; TopicConnection metricConnection; TopicSession metricSession; TopicSubscriber metricSubscriber; Topic metricTopic; String metricTopicName = null; metricConnectionFactory = new com.sun.messaging.TopicConnectionFactory(); metricConnection = metricConnectionFactory.createTopicConnection(); metricConnection.start(); metricSession = metricConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); metricTopicName = "mq.metrics.destination_list"; metricTopic = metricSession.createTopic(metricTopicName); metricSubscriber = metricSession.createSubscriber(metricTopic); metricSubscriber.setMessageListener(this); |
The incoming message is processed in the onMessage() method, as shown in Example 4–4:
public void onMessage(Message m) { try{ MapMessage mapMsg = (MapMessage)m; String type = mapMsg.getStringProperty("type"); if (type.equals(metricTopicName)) { String oneRow[] = new String[ 3 ]; /* * Extract metrics */ for (Enumeration e = mapMsg.getMapNames(); e.hasMoreElements();) { String metricDestName = (String)e.nextElement(); Hashtable destValues = (Hashtable)mapMsg.getObject(metricDestName); int i = 0; oneRow[i++] = (destValues.get("name")).toString(); oneRow[i++] = (destValues.get("type")).toString(); oneRow[i++] = (destValues.get("isTemporary")).toString(); mp.add(oneRow); } mp.print(); System.out.println(""); mp.clear(); } else { System.err.println("Msg received: not destination list metric type"); } } catch (Exception e) { System.err.println("onMessage: Exception caught: " + e); } } |
Notice how the metrics type is extracted and checked, and how the list of destinations is extracted. By iterating through the map names in mapMsg and extracting the corresponding value (a hashtable), you can construct a list of all the destinations and their related information.
As discussed in Format of Metrics Messages, these map names are metrics topic names having one of two forms:
mq.metrics.destination.queue.monitored_destination_name mq.metrics.destination.topic.monitored_destination_name
(The map names can also be used to monitor a destination, but that is not done in this particular example.)
Notice that from each extracted hashtable, the information on each destination is extracted using the keys name, type, and isTemporary. The extraction code from the previous code example is reiterated here for your convenience.
String metricDestName = (String)e.nextElement(); Hashtable destValues = (Hashtable)mapMsg.getObject(metricDestName); int i = 0; oneRow[i++] = (destValues.get("name")).toString(); oneRow[i++] = (destValues.get("type")).toString(); oneRow[i++] = (destValues.get("isTemporary")).toString(); |
Run this example monitoring client with the following command:
java DestListMetrics
The output looks like the following:
--------------------------------------------------- Destination Name Type IsTemporary --------------------------------------------------- SimpleQueue queue false fooQueue queue false topic1 topic false |
The source file for this code example is DestMetrics.java. This client application monitors a specific destination on a broker. It accepts the destination type and name as parameters, and it constructs a metrics topic name of the form mq.metrics.destination.queue.monitored_destination_name or mq.metrics.destination.topic.monitored_destination_name .
Example 4–6 shows how to subscribe to the metrics topic for monitoring a specified destination.
com.sun.messaging.TopicConnectionFactory metricConnectionFactory; TopicConnection metricConnection; TopicSession metricSession; TopicSubscriber metricSubscriber; Topic metricTopic; String metricTopicName = null; String destName = null, destType = null; for (int i = 0; i < args.length; ++i) { ... } else if (args[i].equals("-n")) { destName = args[i+1]; } else if (args[i].equals("-t")) { destType = args[i+1]; } } metricConnectionFactory = new com.sun.messaging.TopicConnectionFactory(); metricConnection = metricConnectionFactory.createTopicConnection(); metricConnection.start(); metricSession = metricConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); if (destType.equals("q")) { metricTopicName = "mq.metrics.destination.queue." + destName; } else { metricTopicName = "mq.metrics.destination.topic." + destName; } metricTopic = metricSession.createTopic(metricTopicName); metricSubscriber = metricSession.createSubscriber(metricTopic); metricSubscriber.setMessageListener(this);
The incoming message is processed in the onMessage() method, as shown in Example 4–7:
public void onMessage(Message m) { try { MapMessage mapMsg = (MapMessage)m; String type = mapMsg.getStringProperty("type"); if (type.equals(metricTopicName)) { String oneRow[] = new String[ 11 ]; int i = 0; /* * Extract destination metrics */ oneRow[i++] = Long.toString(mapMsg.getLong("numMsgsIn")); oneRow[i++] = Long.toString(mapMsg.getLong("numMsgsOut")); oneRow[i++] = Long.toString(mapMsg.getLong("msgBytesIn")); oneRow[i++] = Long.toString(mapMsg.getLong("msgBytesOut")); oneRow[i++] = Long.toString(mapMsg.getLong("numMsgs")); oneRow[i++] = Long.toString(mapMsg.getLong("peakNumMsgs")); oneRow[i++] = Long.toString(mapMsg.getLong("avgNumMsgs")); oneRow[i++] = Long.toString(mapMsg.getLong("totalMsgBytes")/1024); oneRow[i++] = Long.toString (mapMsg.getLong("peakTotalMsgBytes")/1024); oneRow[i++] = Long.toString (mapMsg.getLong("avgTotalMsgBytes")/1024); oneRow[i++] = Long.toString(mapMsg.getLong("peakMsgBytes")/1024); mp.add(oneRow); ... } } catch (Exception e) { System.err.println("onMessage: Exception caught: " + e); } }
Notice how the metrics type is extracted, using the getStringProperty() method as in the previous examples, and is checked. Also notice how various destination data are extracted, using the getLong() method of mapMsg.
You can run this example monitoring client with one of the following commands:
java DestMetrics -t t -n topic_name java DestMetrics -t q -n queue_name
Using a queue named SimpleQueue as an example, the command would be:
java DestMetrics -t q -n SimpleQueue
The output looks like the following:
------------------------------------------------------------------------------ Msgs Msg Bytes Msg Count Tot Msg Bytes(k) Largest Msg In Out In Out Curr Peak Avg Curr Peak Avg (k) ------------------------------------------------------------------------------ 500 0 318000 0 500 500 250 310 310 155 0 |