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 if (tokens.contains("topics")) { 070 displayTopicStats(); 071 } else if (tokens.contains("queues")) { 072 displayQueueStats(); 073 } else { 074 displayAllDestinations(); 075 } 076 } 077 078 @SuppressWarnings("unchecked") 079 private void displayAllDestinations() throws Exception { 080 081 String query = JmxMBeansUtil.createQueryString(queryString, "*"); 082 List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 083 084 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s"; 085 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d"; 086 087 // sort list so the names is A..Z 088 Collections.sort(queueList, new ObjectInstanceComparator()); 089 090 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %")); 091 092 // Iterate through the queue result 093 for (Object view : queueList) { 094 ObjectInstance obj = (ObjectInstance) view; 095 if (!filterMBeans(obj)) { 096 continue; 097 } 098 ObjectName queueName = obj.getObjectName(); 099 100 QueueViewMBean queueView = MBeanServerInvocationHandler. 101 newProxyInstance(createJmxConnection(), queueName, QueueViewMBean.class, true); 102 103 context.print(String.format(Locale.US, tableRow, 104 queueView.getName(), 105 queueView.getQueueSize(), 106 queueView.getProducerCount(), 107 queueView.getConsumerCount(), 108 queueView.getEnqueueCount(), 109 queueView.getDequeueCount(), 110 queueView.getForwardCount(), 111 queueView.getMemoryPercentUsage())); 112 } 113 } 114 115 @SuppressWarnings("unchecked") 116 private void displayQueueStats() throws Exception { 117 118 String query = JmxMBeansUtil.createQueryString(queryString, "Queue"); 119 List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 120 121 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s %10s"; 122 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d %10d"; 123 124 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %", "Inflight #")); 125 126 Collections.sort(queueList, new ObjectInstanceComparator()); 127 128 // Iterate through the queue result 129 for (Object view : queueList) { 130 ObjectInstance obj = (ObjectInstance) view; 131 if (!filterMBeans(obj)) { 132 continue; 133 } 134 ObjectName queueName = obj.getObjectName(); 135 136 QueueViewMBean queueView = MBeanServerInvocationHandler. 137 newProxyInstance(createJmxConnection(), queueName, QueueViewMBean.class, true); 138 139 context.print(String.format(Locale.US, tableRow, 140 queueView.getName(), 141 queueView.getQueueSize(), 142 queueView.getProducerCount(), 143 queueView.getConsumerCount(), 144 queueView.getEnqueueCount(), 145 queueView.getDequeueCount(), 146 queueView.getForwardCount(), 147 queueView.getMemoryPercentUsage(), 148 queueView.getInFlightCount())); 149 } 150 } 151 152 @SuppressWarnings("unchecked") 153 private void displayTopicStats() throws Exception { 154 155 String query = JmxMBeansUtil.createQueryString(queryString, "Topic"); 156 List topicsList = JmxMBeansUtil.queryMBeans(createJmxConnection(), query); 157 158 final String header = "%-50s %10s %10s %10s %10s %10s %10s %10s"; 159 final String tableRow = "%-50s %10d %10d %10d %10d %10d %10d %10d"; 160 161 // sort list so the names is A..Z 162 Collections.sort(topicsList, new ObjectInstanceComparator()); 163 164 context.print(String.format(Locale.US, header, "Name", "Queue Size", "Producer #", "Consumer #", "Enqueue #", "Dequeue #", "Forward #", "Memory %")); 165 166 // Iterate through the topics result 167 for (Object view : topicsList) { 168 ObjectInstance obj = (ObjectInstance) view; 169 if (!filterMBeans(obj)) { 170 continue; 171 } 172 ObjectName topicName = obj.getObjectName(); 173 174 TopicViewMBean topicView = MBeanServerInvocationHandler. 175 newProxyInstance(createJmxConnection(), topicName, TopicViewMBean.class, true); 176 177 context.print(String.format(Locale.US, tableRow, 178 topicView.getName(), 179 topicView.getQueueSize(), 180 topicView.getProducerCount(), 181 topicView.getConsumerCount(), 182 topicView.getEnqueueCount(), 183 topicView.getDequeueCount(), 184 topicView.getForwardCount(), 185 topicView.getMemoryPercentUsage())); 186 } 187 } 188 189 @Override 190 public String getName() { 191 return "dstat"; 192 } 193 194 @Override 195 public String getOneLineDescription() { 196 return "Performs a predefined query that displays useful tabular statistics regarding the specified destination type"; 197 } 198 199 /** 200 * Print the help messages for this command 201 */ 202 @Override 203 protected void printHelp() { 204 context.printHelp(helpFile); 205 } 206 207 protected boolean filterMBeans(ObjectInstance obj) { 208 String className = obj.getClassName(); 209 return className.equals(QueueView.class.getName()) || className.equals(TopicView.class.getName()); 210 } 211 212 private static class ObjectInstanceComparator implements Comparator<ObjectInstance> { 213 214 @Override 215 public int compare(ObjectInstance o1, ObjectInstance o2) { 216 return o1.getObjectName().compareTo(o2.getObjectName()); 217 } 218 } 219 220}