/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.agent.promptcmd; import java.io.PrintWriter; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanServer; import javax.management.ObjectName; import mazz.i18n.Msg; import org.rhq.enterprise.agent.AgentMain; import org.rhq.enterprise.agent.StringUtil; import org.rhq.enterprise.agent.AgentManagement; import org.rhq.enterprise.agent.i18n.AgentI18NFactory; import org.rhq.enterprise.agent.i18n.AgentI18NResourceKeys; /** * Displays the current metrics emitted by the agent itself. * * @author John Mazzitelli */ public class MetricsPromptCommand implements AgentPromptCommand { private static final Msg MSG = AgentI18NFactory.getMsg(); /** * @see AgentPromptCommand#getPromptCommandString() */ public String getPromptCommandString() { return MSG.getMsg(AgentI18NResourceKeys.METRICS); } /** * @see AgentPromptCommand#execute(AgentMain, String[]) */ public boolean execute(AgentMain agent, String[] args) { PrintWriter out = agent.getOut(); // There are other, easier ways to do this, but I want to go through the JMX interface. // Since this is the interface used by the agent plugin to get metric data, this prompt // command can be used to verify the exact data the agent plugin is getting. AgentManagement agent_mbean = agent.getAgentManagementMBean(); if (agent_mbean != null) { try { MBeanServer the_mbs = agent_mbean.getMBeanServer(); displayMetrics(agent_mbean.getObjectName(), out, the_mbs); } catch (Exception e) { out.println(MSG.getMsg(AgentI18NResourceKeys.METRICS_EXCEPTION, e)); } } else { out.println(MSG.getMsg(AgentI18NResourceKeys.METRICS_NO_SERVICES)); } return true; } /** * Queries all the agent management MBean attributes and displays them. * * @param object_name the name of the management MBean * @param out the output to write the information * @param the_mbs the MBeanServer where the management MBean services are * * @throws Exception */ private void displayMetrics(ObjectName object_name, PrintWriter out, MBeanServer the_mbs) throws Exception { // get all the attributes the management MBean exposes and then ask for all their values MBeanInfo mbeaninfo = the_mbs.getMBeanInfo(object_name); MBeanAttributeInfo[] attrib_infos = mbeaninfo.getAttributes(); String[] attrib_names = new String[attrib_infos.length]; for (int i = 0; i < attrib_infos.length; i++) { attrib_names[i] = attrib_infos[i].getName(); } HashMap<String, Object> name_value_pairs = new HashMap<String, Object>(); AttributeList attribs = the_mbs.getAttributes(object_name, attrib_names); for (Iterator iter = attribs.iterator(); iter.hasNext();) { Attribute attrib = (Attribute) iter.next(); String name = attrib.getName(); Object value = attrib.getValue(); // some attributes we do not want to display; skip them as we find them if (name.equals("AgentConfiguration")) { continue; // skip because this makes the output too big and noisy - user can use getconfig to see this data } // we might want to format some attributes into more human readable forms if (name.equals("CurrentTime")) { value = new Date(((Long) value).longValue()); } else if (name.equals("Uptime")) { value = formatSeconds(((Long) value).longValue()); } else if (name.equals("JVMTotalMemory") || name.equals("JVMFreeMemory")) { //value = formatBytes(((Long) value).longValue()); continue; } name_value_pairs.put(name, value); } MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); name_value_pairs.put("Memory - Heap", "Used: " + formatBytes(memoryBean.getHeapMemoryUsage().getUsed()) + ", Committed: " + formatBytes(memoryBean.getHeapMemoryUsage().getCommitted()) + ", Max: " + formatBytes(memoryBean.getHeapMemoryUsage().getMax())); name_value_pairs.put("Memory - Non Heap", "Used: " + formatBytes(memoryBean.getNonHeapMemoryUsage().getUsed()) + ", Committed: " + formatBytes(memoryBean.getNonHeapMemoryUsage().getCommitted()) + ", Max: " + formatBytes(memoryBean.getNonHeapMemoryUsage().getMax())); out.println(MSG.getMsg(AgentI18NResourceKeys.METRICS_HEADER)); out.println(StringUtil.justifyKeyValueStrings(name_value_pairs)); return; } /** * Formats the given time duration (specified in seconds) into seconds, minutes, hours or days as appropriate. * * @param seconds the time duration to format * * @return the number of seconds in string form and in the most appropriate units (seconds, minutes, hours, days) */ private String formatSeconds(long seconds) { String ret_val = null; if (seconds >= (60 * 60 * 24)) { ret_val = String.format("%.1f ", new Object[] { ((float) seconds / (60L * 60 * 24)) }) + MSG.getMsg(AgentI18NResourceKeys.UNITS_DAYS); } else if (seconds >= (60 * 60)) { ret_val = String.format("%.1f ", new Object[] { ((float) seconds / (60L * 60)) }) + MSG.getMsg(AgentI18NResourceKeys.UNITS_HOURS); } else if (seconds >= (60)) { ret_val = String.format("%.1f ", new Object[] { ((float) seconds / (60L)) }) + MSG.getMsg(AgentI18NResourceKeys.UNITS_MINUTES); } if (ret_val != null) { ret_val += " (" + seconds + ")"; } else { ret_val = seconds + " " + MSG.getMsg(AgentI18NResourceKeys.UNITS_SECONDS); } return ret_val; } /** * Formats a count of bytes into KB, MB, GB or TB as appropriate. * * @param bytes * * @return the number of bytes in string form and in the most appropriate units */ private String formatBytes(long bytes) { String ret_str = ""; // we only understand KB, MB, GB and TB. Anything outside that range is returned in bytes // KB=1,000 : MB=1,000,000 : GB=1,000,000,000 : TB=1,000,000,000,000 if ((bytes >= 1000) && (bytes <= 999999999999999L)) { if (bytes < 1000000) { ret_str += String.format("%.2f", new Object[] { (float) bytes / 1000L }) + " KB"; } else if (bytes < 1000000000) { ret_str += String.format("%.2f", new Object[] { (float) bytes / 1000000L }) + " MB"; } else if (bytes < 1000000000000L) { ret_str += String.format("%.2f", new Object[] { (float) bytes / 1000000L }) + " GB"; } else { ret_str += String.format("%.2f", new Object[] { (float) bytes / 1000000000L }) + " TB"; } //ret_str += " (" + bytes + ")"; } else { ret_str += bytes; } return ret_str; } /** * @see AgentPromptCommand#getSyntax() */ public String getSyntax() { return MSG.getMsg(AgentI18NResourceKeys.METRICS_SYNTAX); } /** * @see AgentPromptCommand#getHelp() */ public String getHelp() { return MSG.getMsg(AgentI18NResourceKeys.METRICS_HELP); } /** * @see AgentPromptCommand#getDetailedHelp() */ public String getDetailedHelp() { return MSG.getMsg(AgentI18NResourceKeys.METRICS_DETAILED_HELP); } }