diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSourceImpl.java index 7d765749ff6..6756a21e1bc 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/BaseSourceImpl.java @@ -42,14 +42,12 @@ public class BaseSourceImpl implements BaseSource, MetricsSource { private static enum DefaultMetricsSystemInitializer { INSTANCE; private boolean inited = false; - private JvmMetrics jvmMetricsSource; synchronized void init(String name) { if (inited) return; inited = true; DefaultMetricsSystem.initialize(HBASE_METRICS_SYSTEM_NAME); - jvmMetricsSource = JvmMetrics.initSingleton(name, ""); - + JvmMetrics.initSingleton(name, ""); } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java index 765b8fdffe7..74fcd86691f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java @@ -36,7 +36,6 @@ import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeErrorException; -import javax.management.RuntimeMBeanException; import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeType; import javax.management.openmbean.TabularData; @@ -124,6 +123,12 @@ public class JMXJsonServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String CALLBACK_PARAM = "callback"; + /** + * If query string includes 'description', then we will emit bean and attribute descriptions to + * output IFF they are not null and IFF the description is not the same as the attribute name: + * i.e. specify an URL like so: /jmx?description=true + */ + private static final String INCLUDE_DESCRIPTION = "description"; /** * MBean server. @@ -155,8 +160,7 @@ public class JMXJsonServlet extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) { try { - if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), - request, response)) { + if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response)) { return; } JsonGenerator jg = null; @@ -173,6 +177,9 @@ public class JMXJsonServlet extends HttpServlet { } else { response.setContentType("application/json; charset=utf8"); } + // Should we output description on each attribute and bean? + String tmpStr = request.getParameter(INCLUDE_DESCRIPTION); + boolean description = tmpStr != null && tmpStr.length() > 0; jg = jsonFactory.createJsonGenerator(writer); jg.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); @@ -190,8 +197,7 @@ public class JMXJsonServlet extends HttpServlet { response.setStatus(HttpServletResponse.SC_BAD_REQUEST); return; } - listBeans(jg, new ObjectName(splitStrings[0]), splitStrings[1], - response); + listBeans(jg, new ObjectName(splitStrings[0]), splitStrings[1], description, response); return; } @@ -200,7 +206,7 @@ public class JMXJsonServlet extends HttpServlet { if (qry == null) { qry = "*:*"; } - listBeans(jg, new ObjectName(qry), null, response); + listBeans(jg, new ObjectName(qry), null, description, response); } finally { if (jg != null) { jg.close(); @@ -222,23 +228,24 @@ public class JMXJsonServlet extends HttpServlet { } // --------------------------------------------------------- Private Methods - private void listBeans(JsonGenerator jg, ObjectName qry, String attribute, - HttpServletResponse response) + private void listBeans(JsonGenerator jg, ObjectName qry, String attribute, + final boolean description, final HttpServletResponse response) throws IOException { LOG.trace("Listing beans for "+qry); Set names = null; names = mBeanServer.queryNames(qry, null); - jg.writeArrayFieldStart("beans"); Iterator it = names.iterator(); while (it.hasNext()) { ObjectName oname = it.next(); MBeanInfo minfo; String code = ""; + String descriptionStr = null; Object attributeinfo = null; try { minfo = mBeanServer.getMBeanInfo(oname); code = minfo.getClassName(); + if (description) descriptionStr = minfo.getDescription(); String prs = ""; try { if ("org.apache.commons.modeler.BaseModelMBean".equals(code)) { @@ -302,12 +309,13 @@ public class JMXJsonServlet extends HttpServlet { jg.writeStartObject(); jg.writeStringField("name", oname.toString()); - + if (description && descriptionStr != null && descriptionStr.length() > 0) { + jg.writeStringField("description", descriptionStr); + } jg.writeStringField("modelerType", code); - if ((attribute != null) && (attributeinfo == null)) { + if (attribute != null && attributeinfo == null) { jg.writeStringField("result", "ERROR"); - jg.writeStringField("message", "No attribute with name " + attribute - + " was found."); + jg.writeStringField("message", "No attribute with name " + attribute + " was found."); jg.writeEndObject(); jg.writeEndArray(); jg.close(); @@ -316,11 +324,11 @@ public class JMXJsonServlet extends HttpServlet { } if (attribute != null) { - writeAttribute(jg, attribute, attributeinfo); + writeAttribute(jg, attribute, descriptionStr, attributeinfo); } else { MBeanAttributeInfo attrs[] = minfo.getAttributes(); for (int i = 0; i < attrs.length; i++) { - writeAttribute(jg, oname, attrs[i]); + writeAttribute(jg, oname, description, attrs[i]); } } jg.writeEndObject(); @@ -328,7 +336,8 @@ public class JMXJsonServlet extends HttpServlet { jg.writeEndArray(); } - private void writeAttribute(JsonGenerator jg, ObjectName oname, MBeanAttributeInfo attr) + private void writeAttribute(JsonGenerator jg, ObjectName oname, final boolean description, + MBeanAttributeInfo attr) throws IOException { if (!attr.isReadable()) { return; @@ -337,10 +346,10 @@ public class JMXJsonServlet extends HttpServlet { if ("modelerType".equals(attName)) { return; } - if (attName.indexOf("=") >= 0 || attName.indexOf(":") >= 0 - || attName.indexOf(" ") >= 0) { + if (attName.indexOf("=") >= 0 || attName.indexOf(":") >= 0 || attName.indexOf(" ") >= 0) { return; } + String descriptionStr = description? attr.getDescription(): null; Object value = null; try { value = mBeanServer.getAttribute(oname, attName); @@ -387,15 +396,30 @@ public class JMXJsonServlet extends HttpServlet { return; } - writeAttribute(jg, attName, value); + writeAttribute(jg, attName, descriptionStr, value); } - private void writeAttribute(JsonGenerator jg, String attName, Object value) throws IOException { - jg.writeFieldName(attName); - writeObject(jg, value); + private void writeAttribute(JsonGenerator jg, String attName, final String descriptionStr, + Object value) + throws IOException { + boolean description = false; + if (descriptionStr != null && descriptionStr.length() > 0 && !attName.equals(descriptionStr)) { + description = true; + jg.writeFieldName(attName); + jg.writeStartObject(); + jg.writeFieldName("description"); + jg.writeString(descriptionStr); + jg.writeFieldName("value"); + writeObject(jg, description, value); + jg.writeEndObject(); + } else { + jg.writeFieldName(attName); + writeObject(jg, description, value); + } } - private void writeObject(JsonGenerator jg, Object value) throws IOException { + private void writeObject(JsonGenerator jg, final boolean description, Object value) + throws IOException { if(value == null) { jg.writeNull(); } else { @@ -405,7 +429,7 @@ public class JMXJsonServlet extends HttpServlet { int len = Array.getLength(value); for (int j = 0; j < len; j++) { Object item = Array.get(value, j); - writeObject(jg, item); + writeObject(jg, description, item); } jg.writeEndArray(); } else if(value instanceof Number) { @@ -419,15 +443,15 @@ public class JMXJsonServlet extends HttpServlet { CompositeType comp = cds.getCompositeType(); Set keys = comp.keySet(); jg.writeStartObject(); - for(String key: keys) { - writeAttribute(jg, key, cds.get(key)); + for (String key: keys) { + writeAttribute(jg, key, null, cds.get(key)); } jg.writeEndObject(); } else if(value instanceof TabularData) { TabularData tds = (TabularData)value; jg.writeStartArray(); for(Object entry : tds.values()) { - writeObject(jg, entry); + writeObject(jg, description, entry); } jg.writeEndArray(); } else { @@ -435,4 +459,4 @@ public class JMXJsonServlet extends HttpServlet { } } } -} +} \ No newline at end of file diff --git a/src/main/docbkx/ops_mgt.xml b/src/main/docbkx/ops_mgt.xml index 230c7230278..cce92f65176 100644 --- a/src/main/docbkx/ops_mgt.xml +++ b/src/main/docbkx/ops_mgt.xml @@ -1015,26 +1015,38 @@ $ for i in `cat conf/regionservers|sort`; do ./bin/graceful_stop.sh --restart -- uncommented lines. Restart the region server for the changes to take effect. -
+
Discovering Available Metrics Rather than listing each metric which HBase emits by default, you can browse through the - available metrics, either as a JSON output or via JMX. At this time, the JSON output does - not include the description field which is included in the JMX view. Different metrics are + available metrics, either as a JSON output or via JMX. Different metrics are exposed for the Master process and each region server process. Access a JSON Output of Available Metrics After starting HBase, access the region server's web UI, at - http://localhost:60030 by default. + http://REGIONSERVER_HOSTNAME:60030 by default (or port 16030 in HBase 1.0+). Click the Metrics Dump link near the top. The metrics for the region server are - presented as a dump of the JMX bean in JSON format. + presented as a dump of the JMX bean in JSON format. This will dump out all metrics names and their + values. + To include metrics descriptions in the listing — this can be useful when you are exploring + what is available — add a query string of + ?description=true so your URL becomes + http://REGIONSERVER_HOSTNAME:60030/jmx?description=true. + Not all beans and attributes have descriptions. + To view metrics for the Master, connect to the Master's web UI instead (defaults to - http://localhost:60010) and click its Metrics - Dump link. + http://localhost:60010 or port 16010 in HBase 1.0+) and click its Metrics + Dump link. + To include metrics descriptions in the listing — this can be useful when you are exploring + what is available — add a query string of + ?description=true so your URL becomes + http://REGIONSERVER_HOSTNAME:60010/jmx?description=true. + Not all beans and attributes have descriptions. +