HBASE-15943 Add page displaying JVM process metrics
Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
parent
84a5d29391
commit
dcfd319b5b
|
@ -128,6 +128,7 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
|
||||||
<%if master.isActiveMaster() %>
|
<%if master.isActiveMaster() %>
|
||||||
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
||||||
</%if>
|
</%if>
|
||||||
|
<li><a href="/processMaster.jsp">Process Metrics</a></li>
|
||||||
<li><a href="/logs/">Local Logs</a></li>
|
<li><a href="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -81,6 +81,7 @@ org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
|
||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="active"><a href="/">Home</a></li>
|
<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="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -91,6 +91,7 @@
|
||||||
<li><a href="/master-status">Home</a></li>
|
<li><a href="/master-status">Home</a></li>
|
||||||
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
||||||
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
||||||
|
<li><a href="/processMaster.jsp">Process Metrics</a></li>
|
||||||
<li><a href="/logs/">Local Logs</a></li>
|
<li><a href="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -97,6 +97,7 @@
|
||||||
<li><a href="/master-status">Home</a></li>
|
<li><a href="/master-status">Home</a></li>
|
||||||
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
||||||
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
||||||
|
<li><a href="/processMaster.jsp">Process Metrics</a></li>
|
||||||
<li><a href="/logs/">Local Logs</a></li>
|
<li><a href="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -164,6 +164,7 @@
|
||||||
<li><a href="/master-status">Home</a></li>
|
<li><a href="/master-status">Home</a></li>
|
||||||
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
||||||
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
||||||
|
<li><a href="/processMaster.jsp">Process Metrics</a></li>
|
||||||
<li><a href="/logs/">Local Logs</a></li>
|
<li><a href="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
<%if (master.isActiveMaster()) { %>
|
<%if (master.isActiveMaster()) { %>
|
||||||
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
<li><a href="/processMaster.jsp">Process Metrics</a></li>
|
||||||
<li><a href="/logs/">Local Logs</a></li>
|
<li><a href="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
<li><a href="/master-status">Home</a></li>
|
<li><a href="/master-status">Home</a></li>
|
||||||
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
<li><a href="/tablesDetailed.jsp">Table Details</a></li>
|
||||||
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
<li><a href="/procedures.jsp">Procedures & Locks</a></li>
|
||||||
|
<li><a href="/processMaster.jsp">Process Metrics</a></li>
|
||||||
<li><a href="/logs/">Local Logs</a></li>
|
<li><a href="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -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>
|
|
@ -73,6 +73,7 @@
|
||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="active"><a href="/rs-status">Home</a></li>
|
<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="/logs/">Local Logs</a></li>
|
||||||
<li><a href="/logLevel">Log Level</a></li>
|
<li><a href="/logLevel">Log Level</a></li>
|
||||||
<li><a href="/dump">Debug Dump</a></li>
|
<li><a href="/dump">Debug Dump</a></li>
|
||||||
|
|
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue