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"; 130 final String tableRow = "%-50s %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 %")); 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 } 157 } 158 159 @SuppressWarnings("unchecked") 160 private void displayTopicStats() throws Exception { 161 162 String query = JmxMBeansUtil.createQueryString(queryString, "Topic"); 163 List topicsList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 164 165 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s"; 166 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d"; 167 168 // sort list so the names is A..Z 169 Collections.sort(topicsList, new ObjectInstanceComparator()); 170 171 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %")); 172 173 // Iterate through the topics result 174 for (Object view : topicsList) { 175 ObjectInstance obj = (ObjectInstance) view; 176 if (!filterMBeans(obj)) { 177 continue; 178 } 179 ObjectName topicName = obj.getObjectName(); 180 181 TopicViewMBean topicView = MBeanServerInvocationHandler. 182 newProxyInstance(createJmxConnection(), topicName, TopicViewMBean.class, true); 183 184 context.print(String.format(Locale.US, tableRow, 185 topicView.getName(), 186 topicView.getQueueSize(), 187 topicView.getProducerCount(), 188 topicView.getConsumerCount(), 189 topicView.getEnqueueCount(), 190 topicView.getDequeueCount(), 191 topicView.getForwardCount(), 192 topicView.getMemoryPercentUsage())); 193 } 194 } 195 196 @Override 197 public String getName() { 198 return "dstat"; 199 } 200 201 @Override 202 public String getOneLineDescription() { 203 return "Performs a predefined query that displays useful tabular statistics regarding the specified destination type"; 204 } 205 206 /** 207 * Print the help messages for this command 208 */ 209 @Override 210 protected void printHelp() { 211 context.printHelp(helpFile); 212 } 213 214 protected boolean filterMBeans(ObjectInstance obj) { 215 String className = obj.getClassName(); 216 return className.equals(QueueView.class.getName()) || className.equals(TopicView.class.getName()); 217 } 218 219 private static class ObjectInstanceComparator implements Comparator<ObjectInstance> { 220 221 @Override 222 public int compare(ObjectInstance o1, ObjectInstance o2) { 223 return o1.getObjectName().compareTo(o2.getObjectName()); 224 } 225 } 226 227}