hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From st...@apache.org
Subject hbase git commit: HBASE-15943 Add page displaying JVM process metrics
Date Tue, 04 Jul 2017 04:36:06 GMT
Repository: hbase
Updated Branches:
  refs/heads/branch-2 84a5d2939 -> dcfd319b5


HBASE-15943 Add page displaying JVM process metrics

Signed-off-by: Michael Stack <stack@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/dcfd319b
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/dcfd319b
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/dcfd319b

Branch: refs/heads/branch-2
Commit: dcfd319b5b5648e559030249e38e684757a6f673
Parents: 84a5d29
Author: samirMop <samir.ahmic@ministryofprogramming.com>
Authored: Mon Jul 3 13:00:45 2017 +0200
Committer: Michael Stack <stack@apache.org>
Committed: Mon Jul 3 21:35:59 2017 -0700

----------------------------------------------------------------------
 .../hbase/tmpl/master/MasterStatusTmpl.jamon    |   1 +
 .../hbase/tmpl/regionserver/RSStatusTmpl.jamon  |   1 +
 .../hadoop/hbase/util/JSONMetricUtil.java       | 214 +++++++++++++++++
 .../hbase-webapps/master/procedures.jsp         |   1 +
 .../hbase-webapps/master/processMaster.jsp      | 228 ++++++++++++++++++
 .../hbase-webapps/master/processRS.jsp          | 230 +++++++++++++++++++
 .../resources/hbase-webapps/master/snapshot.jsp |   1 +
 .../resources/hbase-webapps/master/table.jsp    |   1 +
 .../hbase-webapps/master/tablesDetailed.jsp     |   1 +
 .../main/resources/hbase-webapps/master/zk.jsp  |   1 +
 .../hbase-webapps/regionserver/processRS.jsp    | 230 +++++++++++++++++++
 .../hbase-webapps/regionserver/region.jsp       |   1 +
 .../hadoop/hbase/util/TestJSONMetricUtil.java   | 106 +++++++++
 13 files changed, 1016 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
index 58ae3eb..708e72d 100644
--- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
+++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
@@ -128,6 +128,7 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
                 <%if master.isActiveMaster() %>
                 <li><a href="/procedures.jsp">Procedures &amp; Locks</a></li>
                 </%if>
+                <li><a href="/processMaster.jsp">Process Metrics</a></li>
                 <li><a href="/logs/">Local Logs</a></li>
                 <li><a href="/logLevel">Log Level</a></li>
                 <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
index 3a68d96..7219c0a 100644
--- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
+++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/regionserver/RSStatusTmpl.jamon
@@ -81,6 +81,7 @@ org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
             <div class="collapse navbar-collapse">
                 <ul class="nav navbar-nav">
                 <li class="active"><a href="/">Home</a></li>
+                <li><a href="/processRS.jsp">Process Metrics</a></li>
                 <li><a href="/logs/">Local Logs</a></li>
                 <li><a href="/logLevel">Log Level</a></li>
                 <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/JSONMetricUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/JSONMetricUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/JSONMetricUtil.java
new file mode 100644
index 0000000..f64934e
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/JSONMetricUtil.java
@@ -0,0 +1,214 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * */
+package org.apache.hadoop.hbase.util;
+
+import java.beans.IntrospectionException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.openmbean.CompositeData;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jettison.json.JSONException;
+
+public final class JSONMetricUtil {
+
+  private static final Log LOG = LogFactory.getLog(JSONMetricUtil.class);
+
+  private static MBeanServer mbServer = ManagementFactory.getPlatformMBeanServer();
+  //MBeans ObjectName domain names
+  public static final String JAVA_LANG_DOMAIN = "java.lang";
+  public static final String JAVA_NIO_DOMAIN = "java.nio";
+  public static final String SUN_MGMT_DOMAIN = "com.sun.management";
+  public static final String HADOOP_DOMAIN = "Hadoop";
+
+  //MBeans ObjectName properties key names
+  public static final String TYPE_KEY = "type";
+  public static final String NAME_KEY = "name";
+  public static final String SERVICE_KEY = "service";
+  public static final String SUBSYSTEM_KEY = "sub";
+
+/**
+ * Utility for getting metric values. Collection of static methods intended for
+ * easier access to metric values.
+ */
+  private JSONMetricUtil() {
+    // Not to be called
+  }
+
+  public static MBeanAttributeInfo[] getMBeanAttributeInfo(ObjectName bean)
+      throws IntrospectionException, InstanceNotFoundException, ReflectionException,
+      IntrospectionException, javax.management.IntrospectionException {
+    MBeanInfo mbinfo = mbServer.getMBeanInfo(bean);
+    return mbinfo.getAttributes();
+  }
+
+  public static Object getValueFromMBean(ObjectName bean, String attribute) {
+    Object value = null;
+    try {
+      value = mbServer.getAttribute(bean, attribute);
+    }
+    catch(Exception e) {
+      LOG.error("Unable to get value from MBean= "+ bean.toString() +
+        "for attribute=" + attribute + " " + e.getMessage());
+    }
+    return value;
+  }
+
+  /**
+   * Returns a subset of mbeans defined by qry.
+   * Modeled after {@link JSONBean#dumpRegionServerMetrics()}
+   * Example: String qry= "java.lang:type=Memory"
+   * @throws MalformedObjectNameException if json have bad format
+   * @throws IOException /
+   * @return String representation of json array.
+   */
+  public static String dumpBeanToString(String qry) throws MalformedObjectNameException,
+  IOException {
+    StringWriter sw = new StringWriter(1024 * 100); // Guess this size
+    try (PrintWriter writer = new PrintWriter(sw)) {
+      JSONBean dumper = new JSONBean();
+      try (JSONBean.Writer jsonBeanWriter = dumper.open(writer)) {
+        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+        jsonBeanWriter.write(mbeanServer,
+          new ObjectName(qry), null, false);
+      }
+    }
+    sw.close();
+    return sw.toString();
+  }
+
+  public static JsonNode mappStringToJsonNode(String jsonString) throws
+  JsonProcessingException, IOException {
+    ObjectMapper mapper = new ObjectMapper();
+    JsonNode node = mapper.readTree(jsonString);
+    return node;
+  }
+
+
+  public static JsonNode searchJson(JsonNode tree, String searchKey)
+      throws JsonProcessingException, IOException {
+    if (tree == null) {
+      return null;
+    }
+    if(tree.has(searchKey)) {
+      return tree.get(searchKey);
+    }
+    if(tree.isContainerNode()) {
+      for(JsonNode branch: tree) {
+        JsonNode branchResult = searchJson(branch, searchKey);
+        if (branchResult != null && !branchResult.isMissingNode()) {
+          return branchResult;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method for building hashtable used for constructing ObjectName.
+   * Mapping is done with arrays indices
+   * @param keys Hashtable keys
+   * @param values Hashtable values
+   * @return Hashtable or null if arrays are empty * or have different number of elements
+   */
+  public static Hashtable<String, String> buldKeyValueTable(String[] keys, String[] values) {
+    if (keys.length != values.length) {
+      LOG.error("keys and values arrays must be same size");
+      return null;
+    }
+    if (keys.length == 0 || values.length == 0) {
+      LOG.error("keys and values arrays can not be empty;");
+      return null;
+    }
+    Hashtable<String, String> table = new Hashtable<String, String>();
+    for(int i = 0; i < keys.length; i++) {
+      table.put(keys[i], values[i]);
+    }
+    return table;
+  }
+
+  public static ObjectName buildObjectName(String pattern) throws MalformedObjectNameException {
+    return new ObjectName(pattern);
+  }
+
+  public static ObjectName buildObjectName(String domain, Hashtable<String, String> keyValueTable)
+      throws MalformedObjectNameException {
+    return new ObjectName(domain, keyValueTable);
+  }
+
+  public static Set<ObjectName> getRegistredMBeans(ObjectName name, MBeanServer mbs) {
+    return mbs.queryNames(name, null);
+  }
+
+  public static String getProcessPID() {
+    return ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
+  }
+
+  public static String getCommmand() throws MalformedObjectNameException,
+  IOException, JSONException {
+    RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+    return runtimeBean.getSystemProperties().get("sun.java.command");
+  }
+
+  public static List<GarbageCollectorMXBean> getGcCollectorBeans() {
+    List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
+    return gcBeans;
+  }
+
+  public static long getLastGcDuration(ObjectName gcCollector) {
+    long lastGcDuration = 0;
+    Object lastGcInfo = getValueFromMBean(gcCollector, "LastGcInfo");
+    if (lastGcInfo != null && lastGcInfo instanceof CompositeData) {
+      CompositeData cds = (CompositeData)lastGcInfo;
+      lastGcDuration = (long) cds.get("duration");
+    }
+    return lastGcDuration;
+  }
+
+  public static List<MemoryPoolMXBean> getMemoryPools() {
+    List<MemoryPoolMXBean> mPools = ManagementFactory.getMemoryPoolMXBeans();
+    return mPools;
+  }
+
+  public static float calcPercentage(long a, long b) {
+    if (a == 0 || b == 0) {
+      return 0;
+    }
+    return ((float)a / (float)b) *100;
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/procedures.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/procedures.jsp b/hbase-server/src/main/resources/hbase-webapps/master/procedures.jsp
index b686114..00d8ead 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/procedures.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/procedures.jsp
@@ -91,6 +91,7 @@
                 <li><a href="/master-status">Home</a></li>
                 <li><a href="/tablesDetailed.jsp">Table Details</a></li>
                 <li><a href="/procedures.jsp">Procedures &amp; Locks</a></li>
+                <li><a href="/processMaster.jsp">Process Metrics</a></li>
                 <li><a href="/logs/">Local Logs</a></li>
                 <li><a href="/logLevel">Log Level</a></li>
                 <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/processMaster.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/processMaster.jsp b/hbase-server/src/main/resources/hbase-webapps/master/processMaster.jsp
new file mode 100644
index 0000000..b1211b9
--- /dev/null
+++ b/hbase-server/src/main/resources/hbase-webapps/master/processMaster.jsp
@@ -0,0 +1,228 @@
+<%--
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+--%>
+<%@ page contentType="text/html;charset=UTF-8"
+  import="java.util.Date"
+  import="java.util.List"
+  import="org.apache.hadoop.hbase.HBaseConfiguration"
+  import="static org.apache.commons.lang.StringEscapeUtils.escapeXml"
+  import="javax.management.ObjectName"
+  import="java.lang.management.ManagementFactory"
+  import="java.lang.management.MemoryPoolMXBean"
+  import="java.lang.management.RuntimeMXBean"
+  import="java.lang.management.GarbageCollectorMXBean"
+  import="org.apache.hadoop.hbase.util.JSONMetricUtil"
+  import="org.apache.hadoop.hbase.procedure2.util.StringUtils"
+  import="org.codehaus.jackson.JsonNode"
+%>
+<%
+RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+ObjectName jvmMetrics = new ObjectName("Hadoop:service=HBase,name=JvmMetrics");
+
+// There is always two of GC collectors
+List<GarbageCollectorMXBean> gcBeans = JSONMetricUtil.getGcCollectorBeans();
+GarbageCollectorMXBean collector1 = null;
+GarbageCollectorMXBean collector2 = null;
+try {
+collector1 = gcBeans.get(0);
+collector2 = gcBeans.get(1);
+} catch(IndexOutOfBoundsException e) {}
+List<MemoryPoolMXBean> mPools = JSONMetricUtil.getMemoryPools();
+%>
+<!--[if IE]>
+<!DOCTYPE html>
+<![endif]-->
+<?xml version="1.0" encoding="UTF-8" ?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta charset="utf-8">
+    <title>Process info for PID: <%= JSONMetricUtil.getProcessPID() %></title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <link href="/static/css/bootstrap.min.css" rel="stylesheet">
+    <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
+    <link href="/static/css/hbase.css" rel="stylesheet">
+</head>
+<body>
+<div class="navbar  navbar-fixed-top navbar-default">
+    <div class="container-fluid">
+        <div class="navbar-header">
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+            </button>
+            <a class="navbar-brand" href="/rs-status"><img src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
+        </div>
+        <div class="collapse navbar-collapse">
+            <ul class="nav navbar-nav">
+            <li><a href="/master-status">Home</a></li>
+                <li><a href="/tablesDetailed.jsp">Table Details</a></li>
+                <li><a href="/procedures.jsp">Procedures</a></li>
+                <li><a href="/processMaster.jsp">Process Metrics</a></li>
+                <li><a href="/logs/">Local Logs</a></li>
+                <li><a href="/logLevel">Log Level</a></li>
+                <li><a href="/dump">Debug Dump</a></li>
+                <li><a href="/jmx">Metrics Dump</a></li>
+                <% if (HBaseConfiguration.isShowConfInServlet()) { %>
+                <li><a href="/conf">HBase Configuration</a></li>
+                <% } %>
+            </ul>
+        </div><!--/.nav-collapse -->
+    </div>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+      <div class="page-header">
+          <h1><%= JSONMetricUtil.getCommmand().split(" ")[0] %></h1>
+      </div>
+  </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>Started</th>
+        <th>Uptime</th>
+        <th>PID</th>
+        <th>Owner</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= new Date(runtimeBean.getStartTime()) %></a></td>
+        <td><%= StringUtils.humanTimeDiff(runtimeBean.getUptime()) %></a></td>
+        <td><%= JSONMetricUtil.getProcessPID() %></a></td>
+        <td><%= runtimeBean.getSystemProperties().get("user.name") %></a></td>
+      </tr>
+  </table>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+    <div class="page-header">
+    <h2>Threads</h2>
+    </div>
+    </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>ThreadsNew</th>
+        <th>ThreadsRunable</th>
+        <th>ThreadsBlocked</th>
+        <th>ThreadsWaiting</th>
+        <th>ThreadsTimeWaiting</th>
+        <th>ThreadsTerminated</th>
+    </tr>
+     <tr>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsNew")  %></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsRunnable")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsBlocked")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsWaiting")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTimedWaiting")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTerminated")%></a></td>
+     </tr>
+  </table>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+    <div class="page-header">
+    <h2>GC Collectors</h2>
+    </div>
+    </div>
+    <% if (gcBeans.size() == 2) { %>
+<div class="tabbable">
+  <ul class="nav nav-pills">
+    <li class="active">
+      <a href="#tab_gc1" data-toggle="tab"><%=collector1.getName() %></a>
+    </li>
+    <li class="">
+      <a href="#tab_gc2" data-toggle="tab"><%=collector2.getName() %></a>
+     </li>
+  </ul>
+    <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px solid #ddd;">
+      <div class="tab-pane active" id="tab_gc1">
+          <table class="table table-striped">
+            <tr>
+              <th>Collection Count</th>
+              <th>Collection Time</th>
+              <th>Last duration</th>
+            </tr>
+            <tr>
+              <td> <%= collector1.getCollectionCount() %></td>
+              <td> <%= StringUtils.humanTimeDiff(collector1.getCollectionTime()) %> </td>
+              <td> <%= StringUtils.humanTimeDiff(JSONMetricUtil.getLastGcDuration(
+                collector1.getObjectName())) %></td>
+            </tr>
+          </table>
+      </div>
+      <div class="tab-pane" id="tab_gc2">
+        <table class="table table-striped">
+          <tr>
+            <th>Collection Count</th>
+            <th>Collection Time</th>
+             <th>Last duration</th>
+          </tr>
+          <tr>
+            <td> <%= collector2.getCollectionCount()  %></td>
+            <td> <%= StringUtils.humanTimeDiff(collector2.getCollectionTime()) %> </td>
+            <td> <%= StringUtils.humanTimeDiff(JSONMetricUtil.getLastGcDuration(
+              collector2.getObjectName())) %></td>
+          </tr>
+          </table>
+      </div>
+      </div>
+  </div>
+  <%} else { %>
+  <p> Can not display GC Collector stats.</p>
+  <%} %>
+  Total GC Collection time: <%= StringUtils.humanTimeDiff(collector1.getCollectionTime() +
+    collector2.getCollectionTime())%>
+</div>
+<% for(MemoryPoolMXBean mp:mPools) {
+if(mp.getName().contains("Cache")) continue;%>
+<div class="container-fluid content">
+  <div class="row">
+      <div class="page-header">
+          <h2><%= mp.getName() %></h2>
+      </div>
+  </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>Commited</th>
+        <th>Init</th>
+        <th>Max</th>
+        <th>Used</th>
+        <th>Utilization [%]</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= StringUtils.humanSize(mp.getUsage().getCommitted()) %></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getInit())%></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getMax())%></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getUsed())%></a></td>
+        <td><%= JSONMetricUtil.calcPercentage(mp.getUsage().getUsed(),
+          mp.getUsage().getCommitted()) %></a></td>
+      </tr>
+  </table>
+</div>
+<% } %>
+
+<script src="/static/js/jquery.min.js" type="text/javascript"></script>
+<script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
+<script src="/static/js/tab.js" type="text/javascript"></script>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/processRS.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/processRS.jsp b/hbase-server/src/main/resources/hbase-webapps/master/processRS.jsp
new file mode 100644
index 0000000..fa1f7d1
--- /dev/null
+++ b/hbase-server/src/main/resources/hbase-webapps/master/processRS.jsp
@@ -0,0 +1,230 @@
+<%--
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+--%>
+<%@ page contentType="text/html;charset=UTF-8"
+  import="java.util.Date"
+  import="java.util.List"
+  import="org.apache.hadoop.hbase.HBaseConfiguration"
+  import="static org.apache.commons.lang.StringEscapeUtils.escapeXml"
+  import="javax.management.ObjectName"
+  import="java.lang.management.ManagementFactory"
+  import="java.lang.management.MemoryPoolMXBean"
+  import="java.lang.management.RuntimeMXBean"
+  import="java.lang.management.GarbageCollectorMXBean"
+  import="org.apache.hadoop.hbase.util.JSONMetricUtil"
+  import="org.apache.hadoop.hbase.procedure2.util.StringUtils"
+  import="org.codehaus.jackson.JsonNode"
+%>
+<%
+RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+ObjectName jvmMetrics = new ObjectName("Hadoop:service=HBase,name=JvmMetrics");
+ObjectName rsMetrics = new ObjectName("Hadoop:service=HBase,name=RegionServer,sub=Server");
+
+// There is always two of GC collectors
+List<GarbageCollectorMXBean> gcBeans = JSONMetricUtil.getGcCollectorBeans();
+GarbageCollectorMXBean collector1 = null;
+GarbageCollectorMXBean collector2 = null;
+try {
+collector1 = gcBeans.get(0);
+collector2 = gcBeans.get(1);
+} catch(IndexOutOfBoundsException e) {}
+List<MemoryPoolMXBean> mPools = JSONMetricUtil.getMemoryPools();
+%>
+<!--[if IE]>
+<!DOCTYPE html>
+<![endif]-->
+<?xml version="1.0" encoding="UTF-8" ?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta charset="utf-8">
+    <title>Process info for PID: <%= JSONMetricUtil.getProcessPID() %></title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <link href="/static/css/bootstrap.min.css" rel="stylesheet">
+    <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
+    <link href="/static/css/hbase.css" rel="stylesheet">
+</head>
+<body>
+<div class="navbar  navbar-fixed-top navbar-default">
+    <div class="container-fluid">
+        <div class="navbar-header">
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+            </button>
+            <a class="navbar-brand" href="/rs-status"><img src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
+        </div>
+        <div class="collapse navbar-collapse">
+            <ul class="nav navbar-nav">
+                <li><a href="/rs-status">Home</a></li>
+                <li><a href="/processRS.jsp">Process Metrics</a></li>
+                <li><a href="/logs/">Local Logs</a></li>
+                <li><a href="/dump">Debug Dump</a></li>
+                <li><a href="/jmx">Metrics Dump</a></li>
+                <% if (HBaseConfiguration.isShowConfInServlet()) { %>
+                <li><a href="/conf">HBase Configuration</a></li>
+                <% } %>
+            </ul>
+        </div><!--/.nav-collapse -->
+    </div>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+      <div class="page-header">
+          <h1><%= JSONMetricUtil.getCommmand().split(" ")[0] %></h1>
+      </div>
+  </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>Started</th>
+        <th>Uptime</th>
+        <th>PID</th>
+        <th>JvmPauseMonitor Count </th>
+        <th>Owner</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= new Date(runtimeBean.getStartTime()) %></a></td>
+        <td><%= StringUtils.humanTimeDiff(runtimeBean.getUptime()) %></a></td>
+        <td><%= JSONMetricUtil.getProcessPID() %></a></td>
+        <td><%= (long)JSONMetricUtil.getValueFromMBean(rsMetrics, "pauseWarnThresholdExceeded")
+          + (long)JSONMetricUtil.getValueFromMBean(rsMetrics, "pauseInfoThresholdExceeded") %></a></td>
+        <td><%= runtimeBean.getSystemProperties().get("user.name") %></a></td>
+      </tr>
+  </table>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+    <div class="page-header">
+    <h2>Threads</h2>
+    </div>
+    </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>ThreadsNew</th>
+        <th>ThreadsRunable</th>
+        <th>ThreadsBlocked</th>
+        <th>ThreadsWaiting</th>
+        <th>ThreadsTimeWaiting</th>
+        <th>ThreadsTerminated</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsNew")  %></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsRunnable")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsBlocked")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsWaiting")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTimedWaiting")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTerminated")%></a></td>
+      </tr>
+  </table>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+    <div class="page-header">
+    <h2>GC Collectors</h2>
+    </div>
+    </div>
+    <% if (gcBeans.size() == 2) { %>
+<div class="tabbable">
+  <ul class="nav nav-pills">
+    <li class="active">
+      <a href="#tab_gc1" data-toggle="tab"><%=collector1.getName() %></a>
+    </li>
+    <li class="">
+      <a href="#tab_gc2" data-toggle="tab"><%=collector2.getName() %></a>
+     </li>
+  </ul>
+    <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px solid #ddd;">
+      <div class="tab-pane active" id="tab_gc1">
+          <table class="table table-striped">
+            <tr>
+              <th>Collection Count</th>
+              <th>Collection Time</th>
+              <th>Last duration</th>
+            </tr>
+            <tr>
+              <td> <%= collector1.getCollectionCount() %></td>
+              <td> <%= StringUtils.humanTimeDiff(collector1.getCollectionTime()) %> </td>
+              <td> <%= StringUtils.humanTimeDiff(JSONMetricUtil.getLastGcDuration(
+                collector1.getObjectName())) %></td>
+            </tr>
+          </table>
+      </div>
+      <div class="tab-pane" id="tab_gc2">
+        <table class="table table-striped">
+          <tr>
+            <th>Collection Count</th>
+            <th>Collection Time</th>
+             <th>Last duration</th>
+          </tr>
+          <tr>
+            <td> <%= collector2.getCollectionCount()  %></td>
+            <td> <%= StringUtils.humanTimeDiff(collector2.getCollectionTime()) %> </td>
+            <td> <%= StringUtils.humanTimeDiff(JSONMetricUtil.getLastGcDuration(
+              collector2.getObjectName())) %></td>
+          </tr>
+          </table>
+      </div>
+      </div>
+  </div>
+  <%} else { %>
+  <p> Can not display GC Collector stats.</p>
+  <%} %>
+  Total GC Collection time: <%= StringUtils.humanTimeDiff(collector1.getCollectionTime() +
+    collector2.getCollectionTime())%>
+</div>
+<% for(MemoryPoolMXBean mp:mPools) {
+if(mp.getName().contains("Cache")) continue;%>
+<div class="container-fluid content">
+  <div class="row">
+      <div class="page-header">
+          <h2><%= mp.getName() %></h2>
+      </div>
+  </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>Commited</th>
+        <th>Init</th>
+        <th>Max</th>
+        <th>Used</th>
+        <th>Utilization [%]</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= StringUtils.humanSize(mp.getUsage().getCommitted()) %></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getInit())%></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getMax())%></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getUsed())%></a></td>
+        <td><%= JSONMetricUtil.calcPercentage(mp.getUsage().getUsed(),
+          mp.getUsage().getCommitted()) %></a></td>
+      </tr>
+  </table>
+</div>
+<% } %>
+
+<script src="/static/js/jquery.min.js" type="text/javascript"></script>
+<script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
+<script src="/static/js/tab.js" type="text/javascript"></script>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/snapshot.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/snapshot.jsp b/hbase-server/src/main/resources/hbase-webapps/master/snapshot.jsp
index ad3ede5..a6ec23d 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/snapshot.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/snapshot.jsp
@@ -97,6 +97,7 @@
                 <li><a href="/master-status">Home</a></li>
                 <li><a href="/tablesDetailed.jsp">Table Details</a></li>
                 <li><a href="/procedures.jsp">Procedures &amp; Locks</a></li>
+                <li><a href="/processMaster.jsp">Process Metrics</a></li>
                 <li><a href="/logs/">Local Logs</a></li>
                 <li><a href="/logLevel">Log Level</a></li>
                 <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
index fd656c6..fbf26d8 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp
@@ -164,6 +164,7 @@
                 <li><a href="/master-status">Home</a></li>
                 <li><a href="/tablesDetailed.jsp">Table Details</a></li>
                 <li><a href="/procedures.jsp">Procedures &amp; Locks</a></li>
+                <li><a href="/processMaster.jsp">Process Metrics</a></li>
                 <li><a href="/logs/">Local Logs</a></li>
                 <li><a href="/logLevel">Log Level</a></li>
                 <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/tablesDetailed.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/tablesDetailed.jsp b/hbase-server/src/main/resources/hbase-webapps/master/tablesDetailed.jsp
index e6bca57..eaa8c8f 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/tablesDetailed.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/tablesDetailed.jsp
@@ -67,6 +67,7 @@
                   <%if (master.isActiveMaster()) { %>
                   <li><a href="/procedures.jsp">Procedures &amp; Locks</a></li>
                   <% } %>
+                  <li><a href="/processMaster.jsp">Process Metrics</a></li>
                   <li><a href="/logs/">Local Logs</a></li>
                   <li><a href="/logLevel">Log Level</a></li>
                   <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/master/zk.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/zk.jsp b/hbase-server/src/main/resources/hbase-webapps/master/zk.jsp
index a2e6733..d08a2c4 100644
--- a/hbase-server/src/main/resources/hbase-webapps/master/zk.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/master/zk.jsp
@@ -61,6 +61,7 @@
                         <li><a href="/master-status">Home</a></li>
                         <li><a href="/tablesDetailed.jsp">Table Details</a></li>
                         <li><a href="/procedures.jsp">Procedures &amp; Locks</a></li>
+                        <li><a href="/processMaster.jsp">Process Metrics</a></li>
                         <li><a href="/logs/">Local Logs</a></li>
                         <li><a href="/logLevel">Log Level</a></li>
                         <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/regionserver/processRS.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/regionserver/processRS.jsp b/hbase-server/src/main/resources/hbase-webapps/regionserver/processRS.jsp
new file mode 100644
index 0000000..fa1f7d1
--- /dev/null
+++ b/hbase-server/src/main/resources/hbase-webapps/regionserver/processRS.jsp
@@ -0,0 +1,230 @@
+<%--
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+--%>
+<%@ page contentType="text/html;charset=UTF-8"
+  import="java.util.Date"
+  import="java.util.List"
+  import="org.apache.hadoop.hbase.HBaseConfiguration"
+  import="static org.apache.commons.lang.StringEscapeUtils.escapeXml"
+  import="javax.management.ObjectName"
+  import="java.lang.management.ManagementFactory"
+  import="java.lang.management.MemoryPoolMXBean"
+  import="java.lang.management.RuntimeMXBean"
+  import="java.lang.management.GarbageCollectorMXBean"
+  import="org.apache.hadoop.hbase.util.JSONMetricUtil"
+  import="org.apache.hadoop.hbase.procedure2.util.StringUtils"
+  import="org.codehaus.jackson.JsonNode"
+%>
+<%
+RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+ObjectName jvmMetrics = new ObjectName("Hadoop:service=HBase,name=JvmMetrics");
+ObjectName rsMetrics = new ObjectName("Hadoop:service=HBase,name=RegionServer,sub=Server");
+
+// There is always two of GC collectors
+List<GarbageCollectorMXBean> gcBeans = JSONMetricUtil.getGcCollectorBeans();
+GarbageCollectorMXBean collector1 = null;
+GarbageCollectorMXBean collector2 = null;
+try {
+collector1 = gcBeans.get(0);
+collector2 = gcBeans.get(1);
+} catch(IndexOutOfBoundsException e) {}
+List<MemoryPoolMXBean> mPools = JSONMetricUtil.getMemoryPools();
+%>
+<!--[if IE]>
+<!DOCTYPE html>
+<![endif]-->
+<?xml version="1.0" encoding="UTF-8" ?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta charset="utf-8">
+    <title>Process info for PID: <%= JSONMetricUtil.getProcessPID() %></title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <link href="/static/css/bootstrap.min.css" rel="stylesheet">
+    <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
+    <link href="/static/css/hbase.css" rel="stylesheet">
+</head>
+<body>
+<div class="navbar  navbar-fixed-top navbar-default">
+    <div class="container-fluid">
+        <div class="navbar-header">
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+            </button>
+            <a class="navbar-brand" href="/rs-status"><img src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
+        </div>
+        <div class="collapse navbar-collapse">
+            <ul class="nav navbar-nav">
+                <li><a href="/rs-status">Home</a></li>
+                <li><a href="/processRS.jsp">Process Metrics</a></li>
+                <li><a href="/logs/">Local Logs</a></li>
+                <li><a href="/dump">Debug Dump</a></li>
+                <li><a href="/jmx">Metrics Dump</a></li>
+                <% if (HBaseConfiguration.isShowConfInServlet()) { %>
+                <li><a href="/conf">HBase Configuration</a></li>
+                <% } %>
+            </ul>
+        </div><!--/.nav-collapse -->
+    </div>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+      <div class="page-header">
+          <h1><%= JSONMetricUtil.getCommmand().split(" ")[0] %></h1>
+      </div>
+  </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>Started</th>
+        <th>Uptime</th>
+        <th>PID</th>
+        <th>JvmPauseMonitor Count </th>
+        <th>Owner</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= new Date(runtimeBean.getStartTime()) %></a></td>
+        <td><%= StringUtils.humanTimeDiff(runtimeBean.getUptime()) %></a></td>
+        <td><%= JSONMetricUtil.getProcessPID() %></a></td>
+        <td><%= (long)JSONMetricUtil.getValueFromMBean(rsMetrics, "pauseWarnThresholdExceeded")
+          + (long)JSONMetricUtil.getValueFromMBean(rsMetrics, "pauseInfoThresholdExceeded") %></a></td>
+        <td><%= runtimeBean.getSystemProperties().get("user.name") %></a></td>
+      </tr>
+  </table>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+    <div class="page-header">
+    <h2>Threads</h2>
+    </div>
+    </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>ThreadsNew</th>
+        <th>ThreadsRunable</th>
+        <th>ThreadsBlocked</th>
+        <th>ThreadsWaiting</th>
+        <th>ThreadsTimeWaiting</th>
+        <th>ThreadsTerminated</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsNew")  %></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsRunnable")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsBlocked")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsWaiting")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTimedWaiting")%></a></td>
+        <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTerminated")%></a></td>
+      </tr>
+  </table>
+</div>
+<div class="container-fluid content">
+  <div class="row">
+    <div class="page-header">
+    <h2>GC Collectors</h2>
+    </div>
+    </div>
+    <% if (gcBeans.size() == 2) { %>
+<div class="tabbable">
+  <ul class="nav nav-pills">
+    <li class="active">
+      <a href="#tab_gc1" data-toggle="tab"><%=collector1.getName() %></a>
+    </li>
+    <li class="">
+      <a href="#tab_gc2" data-toggle="tab"><%=collector2.getName() %></a>
+     </li>
+  </ul>
+    <div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px solid #ddd;">
+      <div class="tab-pane active" id="tab_gc1">
+          <table class="table table-striped">
+            <tr>
+              <th>Collection Count</th>
+              <th>Collection Time</th>
+              <th>Last duration</th>
+            </tr>
+            <tr>
+              <td> <%= collector1.getCollectionCount() %></td>
+              <td> <%= StringUtils.humanTimeDiff(collector1.getCollectionTime()) %> </td>
+              <td> <%= StringUtils.humanTimeDiff(JSONMetricUtil.getLastGcDuration(
+                collector1.getObjectName())) %></td>
+            </tr>
+          </table>
+      </div>
+      <div class="tab-pane" id="tab_gc2">
+        <table class="table table-striped">
+          <tr>
+            <th>Collection Count</th>
+            <th>Collection Time</th>
+             <th>Last duration</th>
+          </tr>
+          <tr>
+            <td> <%= collector2.getCollectionCount()  %></td>
+            <td> <%= StringUtils.humanTimeDiff(collector2.getCollectionTime()) %> </td>
+            <td> <%= StringUtils.humanTimeDiff(JSONMetricUtil.getLastGcDuration(
+              collector2.getObjectName())) %></td>
+          </tr>
+          </table>
+      </div>
+      </div>
+  </div>
+  <%} else { %>
+  <p> Can not display GC Collector stats.</p>
+  <%} %>
+  Total GC Collection time: <%= StringUtils.humanTimeDiff(collector1.getCollectionTime() +
+    collector2.getCollectionTime())%>
+</div>
+<% for(MemoryPoolMXBean mp:mPools) {
+if(mp.getName().contains("Cache")) continue;%>
+<div class="container-fluid content">
+  <div class="row">
+      <div class="page-header">
+          <h2><%= mp.getName() %></h2>
+      </div>
+  </div>
+  <table class="table table-striped" width="90%" >
+    <tr>
+        <th>Commited</th>
+        <th>Init</th>
+        <th>Max</th>
+        <th>Used</th>
+        <th>Utilization [%]</th>
+    </tr>
+    <tr>
+      <tr>
+        <td><%= StringUtils.humanSize(mp.getUsage().getCommitted()) %></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getInit())%></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getMax())%></a></td>
+        <td><%= StringUtils.humanSize(mp.getUsage().getUsed())%></a></td>
+        <td><%= JSONMetricUtil.calcPercentage(mp.getUsage().getUsed(),
+          mp.getUsage().getCommitted()) %></a></td>
+      </tr>
+  </table>
+</div>
+<% } %>
+
+<script src="/static/js/jquery.min.js" type="text/javascript"></script>
+<script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
+<script src="/static/js/tab.js" type="text/javascript"></script>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp b/hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp
index 874ac43..6a7fe7b 100644
--- a/hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp
+++ b/hbase-server/src/main/resources/hbase-webapps/regionserver/region.jsp
@@ -73,6 +73,7 @@
           <div class="collapse navbar-collapse">
               <ul class="nav navbar-nav">
                   <li class="active"><a href="/rs-status">Home</a></li>
+                  <li><a href="/processRS.jsp">Process Metrics</a></li>
                   <li><a href="/logs/">Local Logs</a></li>
                   <li><a href="/logLevel">Log Level</a></li>
                   <li><a href="/dump">Debug Dump</a></li>

http://git-wip-us.apache.org/repos/asf/hbase/blob/dcfd319b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestJSONMetricUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestJSONMetricUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestJSONMetricUtil.java
new file mode 100644
index 0000000..30da26a
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestJSONMetricUtil.java
@@ -0,0 +1,106 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.util;
+
+import java.io.IOException;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category({MiscTests.class, SmallTests.class})
+public class TestJSONMetricUtil {
+
+  private static final Log LOG = LogFactory.getLog(TestJSONMetricUtil.class);
+
+  @Test
+  public void testBuildHashtable() {
+    String[] keys = {"type", "name"};
+    String[] emptyKey = {};
+    String[] values = {"MemoryPool", "Par Eden Space"};
+    String[] values2 = {"MemoryPool", "Par Eden Space", "Test"};
+    String[] emptyValue = {};
+    Hashtable<String, String> properties = JSONMetricUtil.buldKeyValueTable(keys, values);
+    Hashtable<String, String> nullObject = JSONMetricUtil.buldKeyValueTable(keys, values2);
+    Hashtable<String, String> nullObject1 = JSONMetricUtil.buldKeyValueTable(keys, emptyValue);
+    Hashtable<String, String> nullObject2 = JSONMetricUtil.buldKeyValueTable(emptyKey, values2);
+    Hashtable<String, String> nullObject3 = JSONMetricUtil.buldKeyValueTable(emptyKey, emptyValue);
+    assertEquals(properties.get("type"), values[0]);
+    assertEquals(properties.get("name"), values[1]);
+    assertEquals(nullObject, null);
+    assertEquals(nullObject1, null);
+    assertEquals(nullObject2, null);
+    assertEquals(nullObject3, null);
+  }
+
+  @Test
+  public void testSearchJson() throws JsonProcessingException, IOException {
+    String jsonString = "{\"test\":[{\"data1\":100,\"data2\":\"hello\",\"data3\": [1 , 2 , 3]}, "
+        + "{\"data4\":0}]}";
+    JsonNode  node = JSONMetricUtil.mappStringToJsonNode(jsonString);
+    JsonNode r1 = JSONMetricUtil.searchJson(node, "data1");
+    JsonNode r2 = JSONMetricUtil.searchJson(node, "data2");
+    JsonNode r3 = JSONMetricUtil.searchJson(node, "data3");
+    JsonNode r4 = JSONMetricUtil.searchJson(node, "data4");
+    assertEquals(r1.getIntValue(), 100);
+    assertEquals(r2.getTextValue(), "hello");
+    assertEquals(r3.get(0).getIntValue(), 1);
+    assertEquals(r4.getIntValue(), 0);
+  }
+
+  @Test
+  public void testBuildObjectName() throws MalformedObjectNameException {
+    String[] keys = {"type", "name"};
+    String[] values = {"MemoryPool", "Par Eden Space"};
+    Hashtable<String, String> properties = JSONMetricUtil.buldKeyValueTable(keys, values);
+    ObjectName testObject = JSONMetricUtil.buildObjectName(JSONMetricUtil.JAVA_LANG_DOMAIN,
+      properties);
+    assertEquals(testObject.getDomain(), JSONMetricUtil.JAVA_LANG_DOMAIN);
+    assertEquals(testObject.getKeyPropertyList(), properties);
+  }
+
+  @Test
+  public void testGetLastGCInfo() {
+    List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
+    for(GarbageCollectorMXBean bean:gcBeans) {
+      ObjectName on = bean.getObjectName();
+      Object value = JSONMetricUtil.getValueFromMBean(on, "LastGcInfo");
+      LOG.info("Collector Info: "+ value);
+      if (value != null && value instanceof CompositeData) {
+        CompositeData cds = (CompositeData)value;
+        assertNotNull(cds.get("duration"));
+      }
+    }
+  }
+}


Mime
View raw message