001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.console.command; 018 019import java.util.Collections; 020import java.util.Comparator; 021import java.util.List; 022import java.util.Locale; 023import javax.management.MBeanServerInvocationHandler; 024import javax.management.ObjectInstance; 025import javax.management.ObjectName; 026 027import org.apache.activemq.broker.jmx.QueueView; 028import org.apache.activemq.broker.jmx.QueueViewMBean; 029import org.apache.activemq.broker.jmx.TopicView; 030import org.apache.activemq.broker.jmx.TopicViewMBean; 031import org.apache.activemq.console.util.JmxMBeansUtil; 032 033public class DstatCommand extends AbstractJmxCommand { 034 035 private static final String queryString = 036 "type=Broker,brokerName=*,destinationType=%1,destinationName=*,*"; 037 038 protected String[] helpFile = new String[] { 039 "Task Usage: activemq-admin dstat [dstat-options] [destination-type]", 040 "Description: Performs a predefined query that displays useful statistics regarding the specified .", 041 " destination type (Queues or Topics) and displays those results in a tabular format.", 042 " If no broker name is specified, it will try and select from all registered brokers.", 043 "", 044 "dstat Options:", 045 " --jmxurl <url> Set the JMX URL to connect to.", 046 " --pid <pid> Set the pid to connect to (only on Sun JVM).", 047 " --jmxuser <user> Set the JMX user used for authenticating.", 048 " --jmxpassword <password> Set the JMX password used for authenticating.", 049 " --jmxlocal Use the local JMX server instead of a remote one.", 050 " --version Display the version information.", 051 " -h,-?,--help Display the query broker help information.", 052 "", 053 "Examples:", 054 " activemq-admin dstat queues", 055 " - Display a tabular summary of statistics for the queues on the broker.", 056 " activemq-admin dstat topics", 057 " - Display a tabular summary of statistics for the queues on the broker." 058 }; 059 060 /** 061 * Execute the dstat command, which allows you to display information for topics or queue in 062 * a tabular format. 063 * 064 * @param tokens - command arguments 065 * @throws Exception 066 */ 067 @Override 068 protected void runTask(List<String> tokens) throws Exception { 069 try { 070 071 if (tokens.contains("topics")) { 072 displayTopicStats(); 073 } else if (tokens.contains("queues")) { 074 displayQueueStats(); 075 } else { 076 displayAllDestinations(); 077 } 078 079 // Iterate through the queue names 080 } catch (Exception e) { 081 context.printException(new RuntimeException("Failed to execute dstat task. Reason: " + e.getMessage(), e)); 082 throw new Exception(e); 083 } 084 } 085 086 @SuppressWarnings("unchecked") 087 private void displayAllDestinations() throws Exception { 088 089 String query = JmxMBeansUtil.createQueryString(queryString, "*"); 090 List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 091 092 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s"; 093 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d"; 094 095 // sort list so the names is A..Z 096 Collections.sort(queueList, new ObjectInstanceComparator()); 097 098 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %")); 099 100 // Iterate through the queue result 101 for (Object view : queueList) { 102 ObjectInstance obj = (ObjectInstance) view; 103 if (!filterMBeans(obj)) { 104 continue; 105 } 106 ObjectName queueName = obj.getObjectName(); 107 108 QueueViewMBean queueView = MBeanServerInvocationHandler. 109 newProxyInstance(createJmxConnection(), queueName, QueueViewMBean.class, true); 110 111 context.print(String.format(Locale.US, tableRow, 112 queueView.getName(), 113 queueView.getQueueSize(), 114 queueView.getProducerCount(), 115 queueView.getConsumerCount(), 116 queueView.getEnqueueCount(), 117 queueView.getDequeueCount(), 118 queueView.getForwardCount(), 119 queueView.getMemoryPercentUsage())); 120 } 121 } 122 123 @SuppressWarnings("unchecked") 124 private void displayQueueStats() throws Exception { 125 126 String query = JmxMBeansUtil.createQueryString(queryString, "Queue"); 127 List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 128 129 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s %10s"; 130 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d %10d"; 131 132 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %", "Inflight #")); 133 134 Collections.sort(queueList, new ObjectInstanceComparator()); 135 136 // Iterate through the queue result 137 for (Object view : queueList) { 138 ObjectInstance obj = (ObjectInstance) view; 139 if (!filterMBeans(obj)) { 140 continue; 141 } 142 ObjectName queueName = obj.getObjectName(); 143 144 QueueViewMBean queueView = MBeanServerInvocationHandler. 145 newProxyInstance(createJmxConnection(), queueName, QueueViewMBean.class, true); 146 147 context.print(String.format(Locale.US, tableRow, 148 queueView.getName(), 149 queueView.getQueueSize(), 150 queueView.getProducerCount(), 151 queueView.getConsumerCount(), 152 queueView.getEnqueueCount(), 153 queueView.getDequeueCount(), 154 queueView.getForwardCount(), 155 queueView.getMemoryPercentUsage(), 156 queueView.getInFlightCount())); 157 } 158 } 159 160 @SuppressWarnings("unchecked") 161 private void displayTopicStats() throws Exception { 162 163 String query = JmxMBeansUtil.createQueryString(queryString, "Topic"); 164 List topicsList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 165 166 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s"; 167 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d"; 168 169 // sort list so the names is A..Z 170 Collections.sort(topicsList, new ObjectInstanceComparator()); 171 172 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %")); 173 174 // Iterate through the topics result 175 for (Object view : topicsList) { 176 ObjectInstance obj = (ObjectInstance) view; 177 if (!filterMBeans(obj)) { 178 continue; 179 } 180 ObjectName topicName = obj.getObjectName(); 181 182 TopicViewMBean topicView = MBeanServerInvocationHandler. 183 newProxyInstance(createJmxConnection(), topicName, TopicViewMBean.class, true); 184 185 context.print(String.format(Locale.US, tableRow, 186 topicView.getName(), 187 topicView.getQueueSize(), 188 topicView.getProducerCount(), 189 topicView.getConsumerCount(), 190 topicView.getEnqueueCount(), 191 topicView.getDequeueCount(), 192 topicView.getForwardCount(), 193 topicView.getMemoryPercentUsage())); 194 } 195 } 196 197 @Override 198 public String getName() { 199 return "dstat"; 200 } 201 202 @Override 203 public String getOneLineDescription() { 204 return "Performs a predefined query that displays useful tabular statistics regarding the specified destination type"; 205 } 206 207 /** 208 * Print the help messages for this command 209 */ 210 @Override 211 protected void printHelp() { 212 context.printHelp(helpFile); 213 } 214 215 protected boolean filterMBeans(ObjectInstance obj) { 216 String className = obj.getClassName(); 217 return className.equals(QueueView.class.getName()) || className.equals(TopicView.class.getName()); 218 } 219 220 private static class ObjectInstanceComparator implements Comparator<ObjectInstance> { 221 222 @Override 223 public int compare(ObjectInstance o1, ObjectInstance o2) { 224 return o1.getObjectName().compareTo(o2.getObjectName()); 225 } 226 } 227 228}