blob: 7b7e227045dcca6d85f930e613ce68545baa9b0b [file] [log] [blame]
<%--
/**
* 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.ArrayList"
import="java.util.Collections"
import="java.util.Date"
import="java.util.List"
import="java.util.Map"
import="java.util.regex.Pattern"
import="java.util.stream.Stream"
import="java.util.stream.Collectors"
import="org.apache.hadoop.hbase.HTableDescriptor"
import="org.apache.hadoop.hbase.RSGroupTableAccessor"
import="org.apache.hadoop.hbase.ServerName"
import="org.apache.hadoop.hbase.TableName"
import="org.apache.hadoop.hbase.client.Admin"
import="org.apache.hadoop.hbase.client.RegionInfo"
import="org.apache.hadoop.hbase.client.TableState"
import="org.apache.hadoop.hbase.client.TableDescriptor"
import="org.apache.hadoop.hbase.master.HMaster"
import="org.apache.hadoop.hbase.master.RegionState"
import="org.apache.hadoop.hbase.net.Address"
import="org.apache.hadoop.hbase.rsgroup.RSGroupInfo"
import="org.apache.hadoop.hbase.util.Bytes"
import="org.apache.hadoop.hbase.util.VersionInfo"
import="org.apache.hadoop.util.StringUtils.TraditionalBinaryPrefix"%>
<%@ page import="org.apache.hadoop.hbase.ServerMetrics" %>
<%@ page import="org.apache.hadoop.hbase.Size" %>
<%@ page import="org.apache.hadoop.hbase.RegionMetrics" %>
<%
HMaster master = (HMaster)getServletContext().getAttribute(HMaster.MASTER);
String rsGroupName = request.getParameter("name");
List<Address> rsGroupServers = new ArrayList<>();
List<TableName> rsGroupTables = new ArrayList<>();
RSGroupInfo rsGroupInfo = null;
if (rsGroupName != null && !rsGroupName.isEmpty()) {
rsGroupInfo = RSGroupTableAccessor.getRSGroupInfo(
master.getConnection(), Bytes.toBytes(rsGroupName));
if (rsGroupInfo != null) {
rsGroupServers.addAll(rsGroupInfo.getServers());
rsGroupTables.addAll(rsGroupInfo.getTables());
}
}
Collections.sort(rsGroupServers);
rsGroupTables.sort((o1, o2) -> {
int compare = Bytes.compareTo(o1.getNamespace(), o2.getNamespace());
if (compare != 0)
return compare;
compare = Bytes.compareTo(o1.getQualifier(), o2.getQualifier());
if (compare != 0)
return compare;
return 0;
});
Map<Address, ServerMetrics> onlineServers = Collections.emptyMap();
Map<Address, ServerName> serverMaping = Collections.emptyMap();
if (master.getServerManager() != null) {
onlineServers = master.getServerManager().getOnlineServers().entrySet().stream()
.collect(Collectors.toMap(p -> p.getKey().getAddress(), Map.Entry::getValue));
serverMaping =
master.getServerManager().getOnlineServers().entrySet().stream()
.collect(Collectors.toMap(p -> p.getKey().getAddress(), Map.Entry::getKey));
}
pageContext.setAttribute("pageTitle", "RSGroup: " + rsGroupName);
%>
<jsp:include page="header.jsp">
<jsp:param name="pageTitle" value="${pageTitle}"/>
</jsp:include>
<div class="container-fluid content">
<% if (rsGroupName == null || rsGroupName.isEmpty() || rsGroupInfo == null) { %>
<div class="row inner_header">
<div class="page-header">
<h1>RSGroup: "<%= rsGroupName %>" does not exist</h1>
</div>
</div>
<p>Go <a href="javascript:history.back()">Back</a>, or wait for the redirect.
<% } else { %>
<div class="container-fluid content">
<div class="row">
<div class="page-header">
<h1>RSGroup: <%= rsGroupName %></h1>
</div>
</div>
</div>
<div class="container-fluid content">
<div class="row">
<div class="inner_header">
<h1>Region Servers</h1>
</div>
</div>
<div class="tabbable">
<% if (rsGroupServers != null && rsGroupServers.size() > 0) { %>
<ul class="nav nav-pills">
<li class="active">
<a href="#tab_baseStats" data-toggle="tab">Base Stats</a>
</li>
<li class="">
<a href="#tab_memoryStats" data-toggle="tab">Memory</a>
</li>
<li class="">
<a href="#tab_requestStats" data-toggle="tab">Requests</a>
</li>
<li class="">
<a href="#tab_storeStats" data-toggle="tab">Storefiles</a>
</li>
<li class="">
<a href="#tab_compactStats" data-toggle="tab">Compactions</a>
</li>
</ul>
<div class="tab-content" style="padding-bottom: 9px; border-bottom: 1px solid #ddd;">
<div class="tab-pane active" id="tab_baseStats">
<table class="table table-striped">
<tr>
<th>ServerName</th>
<th>Start time</th>
<th>Last contact</th>
<th>Version</th>
<th>Requests Per Second</th>
<th>Num. Regions</th>
</tr>
<% int totalRegions = 0;
int totalRequests = 0;
int inconsistentNodeNum = 0;
String masterVersion = VersionInfo.getVersion();
for (Address server: rsGroupServers) {
ServerName serverName = serverMaping.get(server);
if (serverName != null) {
ServerMetrics sl = onlineServers.get(server);
String version = master.getRegionServerVersion(serverName);
if (!masterVersion.equals(version)) {
inconsistentNodeNum ++;
}
double requestsPerSecond = 0.0;
int numRegionsOnline = 0;
long lastContact = 0;
if (sl != null) {
requestsPerSecond = sl.getRequestCountPerSecond();
numRegionsOnline = sl.getRegionMetrics().size();
totalRegions += sl.getRegionMetrics().size();
totalRequests += sl.getRequestCount();
lastContact = (System.currentTimeMillis() - sl.getReportTimestamp())/1000;
}
long startcode = serverName.getStartcode();
int infoPort = master.getRegionServerInfoPort(serverName);
String url = "//" + serverName.getHostname() + ":" + infoPort + "/rs-status";%>
<tr>
<td><a href="<%= url %>"><%= serverName.getServerName() %></a></td>
<td><%= new Date(startcode) %></td>
<td><%= lastContact %></td>
<td><%= version %></td>
<td><%= String.format("%.0f", requestsPerSecond) %></td>
<td><%= numRegionsOnline %></td>
</tr>
<% } else { %>
<tr>
<td style="color:rgb(192,192,192);"><%= server %></td>
<td style="color:rgb(192,192,192);"><%= "Dead" %></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<% } %>
<% } %>
<tr><td>Total:<%= rsGroupServers.size() %></td>
<td></td>
<td></td>
<%if (inconsistentNodeNum > 0) { %>
<td style="color:red;"><%= inconsistentNodeNum %> nodes with inconsistent version</td>
<%} else { %>
<td></td>
<%} %>
<td><%= totalRequests %></td>
<td><%= totalRegions %></td>
</tr>
</table>
</div>
<div class="tab-pane" id="tab_memoryStats">
<table class="table table-striped">
<tr>
<th>ServerName</th>
<th>Used Heap</th>
<th>Max Heap</th>
<th>Memstore Size</th>
</tr>
<% for (Address server: rsGroupServers) {
ServerName serverName = serverMaping.get(server);
ServerMetrics sl = onlineServers.get(server);
if (sl != null && serverName != null) {
double memStoreSizeMB = sl.getRegionMetrics().values()
.stream().mapToDouble(rm -> rm.getMemStoreSize().get(Size.Unit.MEGABYTE))
.sum();
int infoPort = master.getRegionServerInfoPort(serverName);
String url = "//" + serverName.getHostname() + ":" + infoPort + "/rs-status";
%>
<tr>
<td><a href="<%= url %>"><%= serverName.getServerName() %></a></td>
<td><%= TraditionalBinaryPrefix.long2String((long) sl.getUsedHeapSize().get(Size.Unit.MEGABYTE)
* TraditionalBinaryPrefix.MEGA.value, "B", 1) %></td>
<td><%= TraditionalBinaryPrefix.long2String((long) sl.getMaxHeapSize().get(Size.Unit.MEGABYTE)
* TraditionalBinaryPrefix.MEGA.value, "B", 1) %></td>
<td><%= TraditionalBinaryPrefix.long2String((long) memStoreSizeMB
* TraditionalBinaryPrefix.MEGA.value, "B", 1) %></td>
</tr>
<% } else { %>
<tr>
<td style="color:rgb(192,192,192);"><%= server %></td>
<td></td>
<td></td>
<td></td>
</tr>
<% }
} %>
</table>
</div>
<div class="tab-pane" id="tab_requestStats">
<table class="table table-striped">
<tr>
<th>ServerName</th>
<th>Request Per Second</th>
<th>Read Request Count</th>
<th>Write Request Count</th>
</tr>
<% for (Address server: rsGroupServers) {
ServerName serverName = serverMaping.get(server);
ServerMetrics sl = onlineServers.get(server);
if (sl != null && serverName != null) {
int infoPort = master.getRegionServerInfoPort(serverName);
long readRequestCount = 0;
long writeRequestCount = 0;
for (RegionMetrics rm : sl.getRegionMetrics().values()) {
readRequestCount += rm.getReadRequestCount();
writeRequestCount += rm.getWriteRequestCount();
}
String url = "//" + serverName.getHostname() + ":" + infoPort + "/rs-status";
%>
<tr>
<td><a href="<%= url %>"><%= serverName.getServerName() %></a></td>
<td><%= String.format("%.0f", sl.getRequestCountPerSecond()) %></td>
<td><%= readRequestCount %></td>
<td><%= writeRequestCount %></td>
</tr>
<% } else { %>
<tr>
<td style="color:rgb(192,192,192);"><%= server %></td>
<td></td>
<td></td>
<td></td>
</tr>
<% }
} %>
</table>
</div>
<div class="tab-pane" id="tab_storeStats">
<table class="table table-striped">
<tr>
<th>ServerName</th>
<th>Num. Stores</th>
<th>Num. Storefiles</th>
<th>Storefile Size Uncompressed</th>
<th>Storefile Size</th>
<th>Index Size</th>
<th>Bloom Size</th>
</tr>
<% for (Address server: rsGroupServers) {
ServerName serverName = serverMaping.get(server);
ServerMetrics sl = onlineServers.get(server);
if (sl != null && serverName != null) {
long storeCount = 0;
long storeFileCount = 0;
double storeUncompressedSizeMB = 0;
double storeFileSizeMB = 0;
double totalStaticIndexSizeKB = 0;
double totalStaticBloomSizeKB = 0;
for (RegionMetrics rm : sl.getRegionMetrics().values()) {
storeCount += rm.getStoreCount();
storeFileCount += rm.getStoreFileCount();
storeUncompressedSizeMB += rm.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
storeFileSizeMB += rm.getStoreFileSize().get(Size.Unit.MEGABYTE);
totalStaticIndexSizeKB += rm.getStoreFileUncompressedDataIndexSize().get(Size.Unit.KILOBYTE);
totalStaticBloomSizeKB += rm.getBloomFilterSize().get(Size.Unit.KILOBYTE);
}
int infoPort = master.getRegionServerInfoPort(serverName);
String url = "//" + serverName.getHostname() + ":" + infoPort + "/rs-status";
%>
<tr>
<td><a href="<%= url %>"><%= serverName.getServerName() %></a></td>
<td><%= storeCount %></td>
<td><%= storeFileCount %></td>
<td><%= TraditionalBinaryPrefix.long2String(
(long) storeUncompressedSizeMB * TraditionalBinaryPrefix.MEGA.value, "B", 1) %></td>
<td><%= TraditionalBinaryPrefix.long2String((long) storeFileSizeMB
* TraditionalBinaryPrefix.MEGA.value, "B", 1) %></td>
<td><%= TraditionalBinaryPrefix.long2String((long) totalStaticIndexSizeKB
* TraditionalBinaryPrefix.KILO.value, "B", 1) %></td>
<td><%= TraditionalBinaryPrefix.long2String((long) totalStaticBloomSizeKB
* TraditionalBinaryPrefix.KILO.value, "B", 1) %></td>
</tr>
<% } else { %>
<tr>
<td style="color:rgb(192,192,192);"><%= server %></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<% }
} %>
</table>
</div>
<div class="tab-pane" id="tab_compactStats">
<table class="table table-striped">
<tr>
<th>ServerName</th>
<th>Num. Compacting KVs</th>
<th>Num. Compacted KVs</th>
<th>Remaining KVs</th>
<th>Compaction Progress</th>
</tr>
<% for (Address server: rsGroupServers) {
ServerName serverName = serverMaping.get(server);
ServerMetrics sl = onlineServers.get(server);
if (sl != null && serverName != null) {
long totalCompactingCells = 0;
long currentCompactedCells = 0;
for (RegionMetrics rm : sl.getRegionMetrics().values()) {
totalCompactingCells += rm.getCompactingCellCount();
currentCompactedCells += rm.getCompactedCellCount();
}
String percentDone = "";
if (totalCompactingCells > 0) {
percentDone = String.format("%.2f", 100 *
((float) currentCompactedCells / totalCompactingCells)) + "%";
}
int infoPort = master.getRegionServerInfoPort(serverName);
String url = "//" + serverName.getHostname() + ":" + infoPort + "/rs-status";
%>
<tr>
<td><a href="<%= url %>"><%= serverName.getServerName() %></a></td>
<td><%= totalCompactingCells %></td>
<td><%= currentCompactedCells %></td>
<td><%= totalCompactingCells - currentCompactedCells %></td>
<td><%= percentDone %></td>
</tr>
<% } else { %>
<tr>
<td style="color:rgb(192,192,192);"><%= server %></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<% }
} %>
</table>
</div>
</div>
<% } else { %>
<p> No Region Servers</p>
<% } %>
</div>
</div>
<br />
<div class="container-fluid content">
<div class="row inner_header">
<div class="page-header">
<h1>Tables</h1>
</div>
</div>
<% if (rsGroupTables != null && rsGroupTables.size() > 0) {
HTableDescriptor[] tables = null;
try (Admin admin = master.getConnection().getAdmin()) {
tables = master.isInitialized() ? admin.listTables((Pattern)null, true) : null;
}
Map<TableName, HTableDescriptor> tableDescriptors
= Stream.of(tables).collect(Collectors.toMap(TableDescriptor::getTableName, p -> p));
%>
<table class="table table-striped">
<tr>
<th>Namespace</th>
<th>Table</th>
<th>Stats</th>
<th>Online Regions</th>
<th>Offline Regions</th>
<th>Failed Regions</th>
<th>Split Regions</th>
<th>Other Regions</th>
<th>Description</th>
</tr>
<% for(TableName tableName : rsGroupTables) {
HTableDescriptor htDesc = tableDescriptors.get(tableName);
if(htDesc == null) {
%>
<tr>
<td><%= tableName.getNamespaceAsString() %></td>
<td><%= tableName.getQualifierAsString() %></td>
<td style="color:rgb(0,0,255);"><%= "DELETED" %></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<% } else { %>
<tr>
<td><%= tableName.getNamespaceAsString() %></td>
<td><a href="/table.jsp?name=<%= tableName.getNameAsString() %>"><%= tableName.getQualifierAsString() %></a></td>
<% TableState.State tableState = master.getTableStateManager().getTableState(tableName);
if(TableState.isInStates(tableState,
TableState.State.DISABLED, TableState.State.DISABLING)) {
%>
<td style="color:red;"><%= tableState.name() %></td>
<% } else { %>
<td><%= tableState.name() %></td>
<% } %>
<% Map<RegionState.State, List<RegionInfo>> tableRegions =
master.getAssignmentManager().getRegionStates().getRegionByStateOfTable(tableName);
int openRegionsCount = tableRegions.get(RegionState.State.OPEN).size();
int offlineRegionsCount = tableRegions.get(RegionState.State.OFFLINE).size();
int splitRegionsCount = tableRegions.get(RegionState.State.SPLIT).size();
int failedRegionsCount = tableRegions.get(RegionState.State.FAILED_OPEN).size()
+ tableRegions.get(RegionState.State.FAILED_CLOSE).size();
int otherRegionsCount = 0;
for (List<RegionInfo> list: tableRegions.values()) {
otherRegionsCount += list.size();
}
// now subtract known states
otherRegionsCount = otherRegionsCount - openRegionsCount
- failedRegionsCount - offlineRegionsCount
- splitRegionsCount;
%>
<td><%= openRegionsCount %></td>
<td><%= offlineRegionsCount %></td>
<td><%= failedRegionsCount %></td>
<td><%= splitRegionsCount %></td>
<td><%= otherRegionsCount %></td>
<td><%= htDesc.toStringCustomizedValues() %></td>
</tr>
<% }
} %>
<p> <%= rsGroupTables.size() %> table(s) in set.</p>
</table>
<% } else { %>
<p> No Tables</p>
<% } %>
</div>
<% } %>
</div>
<jsp:include page="footer.jsp" />