1 /*
2  * Copyright (c) 2000, 2017 Oracle and/or its affiliates. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Distribution License v. 1.0, which is available at
6  * http://www.eclipse.org/org/documents/edl-v10.php.
7  *
8  * SPDX-License-Identifier: BSD-3-Clause
9  */
10 
11 import java.util.Enumeration;
12 import java.util.Properties;
13 import javax.jms.*;
14 
15 /**
16  * The BrokerMetrics example is a JMS application that monitors the
17  * Oracle GlassFish(tm) Server Message Queue broker. It does so by subscribing to a
18  * topic named 'mq.metrics.broker'. The messages that arrive contain
19  * Broker metric information such as number of messages flowing in/out
20  * of the broker, size in bytes of messages flowing in/out etc.
21  *
22  * This application also shows how to use the timestamp in each metric
23  * message to calculate rates e.g. rate at which messages are flowing
24  * into the broker.
25  *
26  * This application takes the following arguments:
27  *	-m ttl		Show totals e.g. total/accumulative number of msgs
28  *			that flowed in/out of the broker. This is the
29  *			default.
30  *	-m rts		Show rates e.g. rate of mesasge flow in/out of
31  *			broker.
32  *
33  * By default BrokerMetrics will connect to the broker running on localhost:7676.
34  * You can use -DimqAddressList attribute to change the host, port and
35  * transport:
36  *
37  *	java -DimqAddressList=mq://<host>:<port>/jms DestListMetrics
38 *
39  */
40 public class BrokerMetrics implements MessageListener  {
41     ConnectionFactory        metricConnectionFactory;
42     Connection               metricConnection;
43     Session                  metricSession;
44     MessageConsumer          metricConsumer;
45     Topic                    metricTopic;
46     MetricsPrinter           mp;
47     int                      rowsPrinted = 0;
48     boolean                  showTotals = true;
49     MapMessage               previous = null;
50 
main(String args[])51     public static void main(String args[])  {
52 	boolean		totals = true;
53 
54 	for (int i = 0; i < args.length; ++i)  {
55             if (args[i].equals("-m"))  {
56 		String type = args[i+1];
57 
58 		if (type.equals("ttl"))  {
59 	            totals = true;
60 		} else if (type.equals("rts"))  {
61 	            totals = false;
62 		}
63 	    }
64 	}
65 	BrokerMetrics bm = new BrokerMetrics();
66 
67 	bm.showTotals = totals;
68         bm.initPrinter();
69         bm.initJMS();
70         bm.subscribeToMetric();
71     }
72 
73     /*
74      * Initializes the class that does the printing, MetricsPrinter.
75      * See the MetricsPrinter class for details.
76      */
initPrinter()77     private void initPrinter() {
78 	String oneRow[] = new String[ 8 ];
79 	int    span[] = new int[ 8 ];
80 	int i = 0;
81 
82 	mp = new MetricsPrinter(8, 2, "-", MetricsPrinter.CENTER);
83 	mp.setTitleAlign(MetricsPrinter.CENTER);
84 
85 	span[i++] = 2;
86 	span[i++] = 0;
87 	span[i++] = 2;
88 	span[i++] = 0;
89 	span[i++] = 2;
90 	span[i++] = 0;
91 	span[i++] = 2;
92 	span[i++] = 0;
93 
94 	i = 0;
95 	if (showTotals)  {
96 	    oneRow[i++] = "Msgs";
97 	    oneRow[i++] = "";
98 	    oneRow[i++] = "Msg Bytes";
99 	    oneRow[i++] = "";
100 	    oneRow[i++] = "Pkts";
101 	    oneRow[i++] = "";
102 	    oneRow[i++] = "Pkt Bytes";
103 	    oneRow[i++] = "";
104 	} else  {
105 	    oneRow[i++] = "Msgs/sec";
106 	    oneRow[i++] = "";
107 	    oneRow[i++] = "Msg Bytes/sec";
108 	    oneRow[i++] = "";
109 	    oneRow[i++] = "Pkts/sec";
110 	    oneRow[i++] = "";
111 	    oneRow[i++] = "Pkt Bytes/sec";
112 	    oneRow[i++] = "";
113 	}
114 	mp.addTitle(oneRow, span);
115 
116 	i = 0;
117 	oneRow[i++] = "In";
118 	oneRow[i++] = "Out";
119 	oneRow[i++] = "In";
120 	oneRow[i++] = "Out";
121 	oneRow[i++] = "In";
122 	oneRow[i++] = "Out";
123 	oneRow[i++] = "In";
124 	oneRow[i++] = "Out";
125 
126 	mp.addTitle(oneRow);
127     }
128 
129     /**
130      * Create the Connection and Session etc.
131      */
initJMS()132     public void initJMS() {
133         try {
134             metricConnectionFactory = new com.sun.messaging.ConnectionFactory();
135             metricConnection = metricConnectionFactory.createConnection();
136             metricConnection.start();
137 
138             //  creating Session
139             //	Transaction Mode: None
140             //	Acknowledge Mode: Automatic
141             metricSession = metricConnection.createSession(false,
142 				Session.AUTO_ACKNOWLEDGE);
143         } catch(Exception e) {
144             System.err.println("Cannot create metric connection or session: "
145 			+ e.getMessage());
146             e.printStackTrace();
147 	    System.exit(1);
148         }
149     }
150 
subscribeToMetric()151     public void subscribeToMetric() {
152         try {
153             metricTopic = metricSession.createTopic("mq.metrics.broker");
154 
155             metricConsumer = metricSession.createConsumer(metricTopic);
156             metricConsumer.setMessageListener(this);
157         } catch(JMSException e) {
158             System.err.println("Cannot subscribe to metric topic: "
159 			+ e.getMessage());
160             e.printStackTrace();
161 	    System.exit(1);
162         }
163     }
164 
165     /*
166      * When a metric message arrives
167      *	- verify it's type
168      *	- extract it's fields
169      *  - print one row of output
170      */
onMessage(Message m)171     public void onMessage(Message m)  {
172 	try  {
173 	    MapMessage mapMsg = (MapMessage)m;
174 	    String type = mapMsg.getStringProperty("type");
175 
176 	    if (type.equals("mq.metrics.broker"))  {
177 		if (showTotals)  {
178 		    doTotals(mapMsg);
179 		} else  {
180 		    doRates(mapMsg);
181 		}
182 
183 	    } else  {
184 	        System.err.println("Msg received: not broker metric type");
185 	    }
186 	} catch (Exception e)  {
187 	    System.err.println("onMessage: Exception caught: " + e);
188 	}
189     }
190 
doTotals(MapMessage mapMsg)191     private void doTotals(MapMessage mapMsg)  {
192 	try  {
193 	    String oneRow[] = new String[ 8 ];
194 	    int i = 0;
195 
196 	    /*
197 	     * Extract broker metrics
198 	     */
199 	    oneRow[i++] = Long.toString(mapMsg.getLong("numMsgsIn"));
200 	    oneRow[i++] = Long.toString(mapMsg.getLong("numMsgsOut"));
201 	    oneRow[i++] = Long.toString(mapMsg.getLong("msgBytesIn"));
202 	    oneRow[i++] = Long.toString(mapMsg.getLong("msgBytesOut"));
203 	    oneRow[i++] = Long.toString(mapMsg.getLong("numPktsIn"));
204 	    oneRow[i++] = Long.toString(mapMsg.getLong("numPktsOut"));
205 	    oneRow[i++] = Long.toString(mapMsg.getLong("pktBytesIn"));
206 	    oneRow[i++] = Long.toString(mapMsg.getLong("pktBytesOut"));
207 
208 	    mp.add(oneRow);
209 
210 	    if ((rowsPrinted % 20) == 0)  {
211 	        mp.print();
212 	    } else  {
213 	        mp.print(false);
214 	    }
215 
216 	    rowsPrinted++;
217 
218 	    mp.clear();
219 	} catch (Exception e)  {
220 	    System.err.println("onMessage: Exception caught: " + e);
221 	}
222     }
223 
doRates(MapMessage mapMsg)224     private void doRates(MapMessage mapMsg)  {
225 	String oneRow[] = new String[ 8 ];
226 	int i = 0;
227 
228 	try  {
229 	    if (previous == null)  {
230 	        oneRow[i++] = "0";
231 	        oneRow[i++] = "0";
232 	        oneRow[i++] = "0";
233 	        oneRow[i++] = "0";
234 	        oneRow[i++] = "0";
235 	        oneRow[i++] = "0";
236 	        oneRow[i++] = "0";
237 	        oneRow[i++] = "0";
238 	    } else  {
239 	        long prevVal, newVal, prevSecs, newSecs, tmp;
240 		float secs;
241 
242 	        prevSecs = previous.getLongProperty("timestamp");
243 	        newSecs = mapMsg.getLongProperty("timestamp");
244 		secs = (float)(newSecs - prevSecs)/(float)1000;
245 
246 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "numMsgsIn"));
247 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "numMsgsOut"));
248 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "msgBytesIn"));
249 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "msgBytesOut"));
250 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "numPktsIn"));
251 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "numPktsOut"));
252 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "pktBytesIn"));
253 	        oneRow[i++] = Long.toString(getRate(previous, mapMsg, secs, "pktBytesOut"));
254 	    }
255 
256 	    previous = mapMsg;
257 
258 	    mp.add(oneRow);
259 
260 	    if ((rowsPrinted % 20) == 0)  {
261 	        mp.print();
262 	    } else  {
263 	        mp.print(false);
264 	    }
265 
266 	    rowsPrinted++;
267 
268 	    mp.clear();
269 	} catch (Exception e)  {
270 	    System.err.println("onMessage: Exception caught: " + e);
271 	    e.printStackTrace();
272 	}
273     }
274 
getRate(MapMessage previous, MapMessage mapMsg, float secs, String propName)275     private long getRate(MapMessage previous, MapMessage mapMsg, float secs,
276 				String propName) throws JMSException {
277 
278         long prevVal, newVal, prevSecs, newSecs, tmp;
279 
280 	prevVal = previous.getLong(propName);
281 	newVal = mapMsg.getLong(propName);
282 
283 	tmp = (long)((newVal - prevVal)/secs);
284 
285 	return (tmp);
286     }
287 }
288