HBASE-21207 Add client side sorting functionality in master web UI for table and region server details
Signed-off-by: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
parent
668a179882
commit
801fc05e9c
|
@ -396,8 +396,22 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
|
|||
</div> <!-- /container -->
|
||||
|
||||
<script src="/static/js/jquery.min.js" type="text/javascript"></script>
|
||||
<script src="/static/js/jquery.tablesorter.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>
|
||||
<script>
|
||||
$(document).ready(function()
|
||||
{
|
||||
$("#baseStatsTable").tablesorter();
|
||||
$("#memoryStatsTable").tablesorter();
|
||||
$("#requestStatsTable").tablesorter();
|
||||
$("#storeStatsTable").tablesorter();
|
||||
$("#compactionStatsTable").tablesorter();
|
||||
|
||||
$("#userTables").tablesorter();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -462,7 +476,8 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
|
|||
</%if>
|
||||
|
||||
<%if (tables != null && tables.size() > 0)%>
|
||||
<table class="table table-striped">
|
||||
<table id="userTables" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Namespace</th>
|
||||
<th>Name</th>
|
||||
|
@ -477,6 +492,8 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
|
|||
<th>Other (CLOSED, etc.)</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%for TableDescriptor desc : tables%>
|
||||
<%java>
|
||||
HTableDescriptor htDesc = new HTableDescriptor(desc);
|
||||
|
@ -515,6 +532,7 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
|
|||
</tr>
|
||||
</%for>
|
||||
<p><% tables.size() %> table(s) in set. [<a href=tablesDetailed.jsp>Details</a>]</p>
|
||||
</tbody>
|
||||
</table>
|
||||
</%if>
|
||||
</%def>
|
||||
|
|
|
@ -82,7 +82,8 @@ Arrays.sort(serverNames);
|
|||
<%args>
|
||||
ServerName [] serverNames;
|
||||
</%args>
|
||||
<table class="table table-striped">
|
||||
<table id="baseStatsTable" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ServerName</th>
|
||||
<th>Start time</th>
|
||||
|
@ -91,6 +92,8 @@ Arrays.sort(serverNames);
|
|||
<th>Requests Per Second</th>
|
||||
<th>Num. Regions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%java>
|
||||
int totalRegions = 0;
|
||||
int totalRequestsPerSecond = 0;
|
||||
|
@ -128,6 +131,7 @@ Arrays.sort(serverNames);
|
|||
<%java>
|
||||
}
|
||||
</%java>
|
||||
</tbody>
|
||||
<tr><td>Total:<% servers.size() %></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
@ -146,7 +150,8 @@ Arrays.sort(serverNames);
|
|||
<%args>
|
||||
ServerName [] serverNames;
|
||||
</%args>
|
||||
<table class="table table-striped">
|
||||
<table id="memoryStatsTable" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ServerName</th>
|
||||
<th>Used Heap</th>
|
||||
|
@ -154,6 +159,8 @@ Arrays.sort(serverNames);
|
|||
<th>Memstore Size</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%java>
|
||||
for (ServerName serverName: serverNames) {
|
||||
|
||||
|
@ -182,6 +189,7 @@ for (ServerName serverName: serverNames) {
|
|||
}
|
||||
}
|
||||
</%java>
|
||||
</tbody>
|
||||
</table>
|
||||
</%def>
|
||||
|
||||
|
@ -190,7 +198,8 @@ for (ServerName serverName: serverNames) {
|
|||
<%args>
|
||||
ServerName [] serverNames;
|
||||
</%args>
|
||||
<table class="table table-striped">
|
||||
<table id="requestStatsTable" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ServerName</th>
|
||||
<th>Request Per Second</th>
|
||||
|
@ -198,6 +207,8 @@ for (ServerName serverName: serverNames) {
|
|||
<th>Filtered Read Request Count</th>
|
||||
<th>Write Request Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%java>
|
||||
for (ServerName serverName: serverNames) {
|
||||
|
||||
|
@ -227,6 +238,7 @@ if (sl != null) {
|
|||
}
|
||||
}
|
||||
</%java>
|
||||
</tbody>
|
||||
</table>
|
||||
</%def>
|
||||
|
||||
|
@ -235,7 +247,8 @@ if (sl != null) {
|
|||
<%args>
|
||||
ServerName [] serverNames;
|
||||
</%args>
|
||||
<table class="table table-striped">
|
||||
<table id="storeStatsTable" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ServerName</th>
|
||||
<th>Num. Stores</th>
|
||||
|
@ -245,6 +258,8 @@ if (sl != null) {
|
|||
<th>Index Size</th>
|
||||
<th>Bloom Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%java>
|
||||
for (ServerName serverName: serverNames) {
|
||||
|
||||
|
@ -286,6 +301,7 @@ if (sl != null) {
|
|||
}
|
||||
}
|
||||
</%java>
|
||||
</tbody>
|
||||
</table>
|
||||
</%def>
|
||||
|
||||
|
@ -293,7 +309,8 @@ if (sl != null) {
|
|||
<%args>
|
||||
ServerName [] serverNames;
|
||||
</%args>
|
||||
<table class="table table-striped">
|
||||
<table id="compactionStatsTable" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ServerName</th>
|
||||
<th>Num. Compacting Cells</th>
|
||||
|
@ -301,6 +318,8 @@ if (sl != null) {
|
|||
<th>Remaining Cells</th>
|
||||
<th>Compaction Progress</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%java>
|
||||
for (ServerName serverName: serverNames) {
|
||||
|
||||
|
@ -333,6 +352,7 @@ if (totalCompactingCells > 0) {
|
|||
}
|
||||
}
|
||||
</%java>
|
||||
</tbody>
|
||||
</table>
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
import="java.util.ArrayList"
|
||||
import="java.util.Collection"
|
||||
import="java.util.Collections"
|
||||
import="java.util.Comparator"
|
||||
import="java.util.HashMap"
|
||||
import="java.util.LinkedHashMap"
|
||||
import="java.util.List"
|
||||
|
@ -82,11 +81,6 @@
|
|||
MetaTableLocator metaTableLocator = new MetaTableLocator();
|
||||
String fqtn = request.getParameter("name");
|
||||
final String escaped_fqtn = StringEscapeUtils.escapeHtml4(fqtn);
|
||||
String sortKey = request.getParameter("sort");
|
||||
String reverse = request.getParameter("reverse");
|
||||
final boolean reverseOrder = (reverse != null && reverse.equals("true"));
|
||||
String showWholeKey = request.getParameter("showwhole");
|
||||
final boolean showWhole = (showWholeKey!=null && showWholeKey.equals("true"));
|
||||
Table table;
|
||||
String tableHeader;
|
||||
boolean withReplica = false;
|
||||
|
@ -140,10 +134,10 @@ if ( fqtn != null ) {
|
|||
try {
|
||||
table = master.getConnection().getTable(TableName.valueOf(fqtn));
|
||||
if (table.getTableDescriptor().getRegionReplication() > 1) {
|
||||
tableHeader = "<h2>Table Regions</h2><table class=\"table table-striped\" style=\"table-layout: fixed; word-wrap: break-word;\"><tr><th>Name</th><th>Region Server</th><th>ReadRequests</th><th>WriteRequests</th><th>StorefileSize</th><th>Num.Storefiles</th><th>MemSize</th><th>Locality</th><th>Start Key</th><th>End Key</th><th>ReplicaID</th></tr>";
|
||||
tableHeader = "<h2>Table Regions</h2><table id=\"tableRegionTable\" class=\"tablesorter table table-striped\" style=\"table-layout: fixed; word-wrap: break-word;\"><thead><tr><th>Name</th><th>Region Server</th><th>ReadRequests</th><th>WriteRequests</th><th>StorefileSize</th><th>Num.Storefiles</th><th>MemSize</th><th>Locality</th><th>Start Key</th><th>End Key</th><th>ReplicaID</th></tr></thead>";
|
||||
withReplica = true;
|
||||
} else {
|
||||
tableHeader = "<h2>Table Regions</h2><table class=\"table table-striped\" style=\"table-layout: fixed; word-wrap: break-word;\"><tr><th>Name</th><th>Region Server</th><th>ReadRequests</th><th>WriteRequests</th><th>StorefileSize</th><th>Num.Storefiles</th><th>MemSize</th><th>Locality</th><th>Start Key</th><th>End Key</th></tr>";
|
||||
tableHeader = "<h2>Table Regions</h2><table id=\"tableRegionTable\" class=\"tablesorter table table-striped\" style=\"table-layout: fixed; word-wrap: break-word;\"><thead><tr><th>Name</th><th>Region Server</th><th>ReadRequests</th><th>WriteRequests</th><th>StorefileSize</th><th>Num.Storefiles</th><th>MemSize</th><th>Locality</th><th>Start Key</th><th>End Key</th></tr></thead>";
|
||||
}
|
||||
if ( !readOnly && action != null ) {
|
||||
%>
|
||||
|
@ -202,6 +196,7 @@ if ( fqtn != null ) {
|
|||
if(fqtn.equals(TableName.META_TABLE_NAME.getNameAsString())) {
|
||||
%>
|
||||
<%= tableHeader %>
|
||||
<tbody>
|
||||
<%
|
||||
// NOTE: Presumes meta with one or more replicas
|
||||
for (int j = 0; j < numMetaReplicas; j++) {
|
||||
|
@ -256,6 +251,7 @@ if ( fqtn != null ) {
|
|||
</tr>
|
||||
<% } %>
|
||||
<%} %>
|
||||
</tbody>
|
||||
</table>
|
||||
<%} else {
|
||||
Admin admin = master.getConnection().getAdmin();
|
||||
|
@ -444,22 +440,8 @@ if ( fqtn != null ) {
|
|||
|
||||
if(regions != null && regions.size() > 0) { %>
|
||||
<h2>Table Regions</h2>
|
||||
Sort As
|
||||
<select id="sel" style="margin-right: 10px">
|
||||
<option value="regionname">RegionName</option>
|
||||
<option value="readrequest">ReadRequest</option>
|
||||
<option value="writerequest">WriteRequest</option>
|
||||
<option value="size">StorefileSize</option>
|
||||
<option value="filecount">Num.Storefiles</option>
|
||||
<option value="memstore">MemstoreSize</option>
|
||||
<option value="locality">Locality</option>
|
||||
</select>
|
||||
Ascending<input type="checkbox" id="ascending" value="Ascending" style="margin-right:10px">
|
||||
ShowDetailName<input type="checkbox" id="showWhole" style="margin-right:10px">
|
||||
<input type="button" id="submit" value="Reorder" onClick="reloadAsSort()" style="font-size: 12pt; width: 5em; margin-bottom: 5px" class="btn">
|
||||
<p>
|
||||
|
||||
<table class="table table-striped">
|
||||
<table id="regionServerDetailsTable" class="tablesorter table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name(<%= String.format("%,1d", regions.size())%>)</th>
|
||||
<th>Region Server</th>
|
||||
|
@ -479,91 +461,12 @@ ShowDetailName<input type="checkbox" id="showWhole" style="margin-right:10px">
|
|||
<%
|
||||
}
|
||||
%>
|
||||
</thead>
|
||||
</tr>
|
||||
<tbody>
|
||||
|
||||
<%
|
||||
List<Map.Entry<RegionInfo, RegionMetrics>> entryList = new ArrayList<>(regionsToLoad.entrySet());
|
||||
if (Objects.equals(sortKey, "regionname")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
RegionInfo regionInfo1 = entry1.getKey();
|
||||
RegionInfo regionInfo2 = entry2.getKey();
|
||||
String name1 = showWhole ? Bytes.toStringBinary(regionInfo1.getRegionName())
|
||||
: regionInfo1.getEncodedName();
|
||||
String name2 = showWhole ? Bytes.toStringBinary(regionInfo2.getRegionName())
|
||||
: regionInfo2.getEncodedName();
|
||||
return name1.compareTo(name2);
|
||||
});
|
||||
} else if (Objects.equals(sortKey, "readrequest")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
return Long.compare(entry1.getValue().getReadRequestCount(),
|
||||
entry2.getValue().getReadRequestCount());
|
||||
});
|
||||
} else if (Objects.equals(sortKey, "writerequest")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
return Long.compare(entry1.getValue().getWriteRequestCount(),
|
||||
entry2.getValue().getWriteRequestCount());
|
||||
});
|
||||
} else if (Objects.equals(sortKey, "size")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
return Double.compare(entry1.getValue().getStoreFileSize().get(),
|
||||
entry2.getValue().getStoreFileSize().get());
|
||||
});
|
||||
} else if (Objects.equals(sortKey, "filecount")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
return Integer.compare(entry1.getValue().getStoreCount(),
|
||||
entry2.getValue().getStoreCount());
|
||||
});
|
||||
} else if (Objects.equals(sortKey, "memstore")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
return Double.compare(entry1.getValue().getMemStoreSize().get(),
|
||||
entry2.getValue().getMemStoreSize().get());
|
||||
});
|
||||
} else if (Objects.equals(sortKey, "locality")) {
|
||||
Collections.sort(entryList, (entry1, entry2) -> {
|
||||
if (entry1 == null || entry1.getValue() == null) {
|
||||
return -1;
|
||||
} else if (entry2 == null || entry2.getValue() == null) {
|
||||
return 1;
|
||||
}
|
||||
return Double.compare(entry1.getValue().getDataLocality(),
|
||||
entry2.getValue().getDataLocality());
|
||||
});
|
||||
}
|
||||
|
||||
if (reverseOrder) {
|
||||
Collections.reverse(entryList);
|
||||
}
|
||||
|
||||
numRegions = regions.size();
|
||||
int numRegionsRendered = 0;
|
||||
// render all regions
|
||||
|
@ -614,7 +517,7 @@ ShowDetailName<input type="checkbox" id="showWhole" style="margin-right:10px">
|
|||
numRegionsRendered++;
|
||||
%>
|
||||
<tr>
|
||||
<td><%= escapeXml(showWhole?Bytes.toStringBinary(regionInfo.getRegionName()):regionInfo.getEncodedName()) %></td>
|
||||
<td><%= escapeXml(Bytes.toStringBinary(regionInfo.getRegionName())) %></td>
|
||||
<%
|
||||
if (urlRegionServer != null) {
|
||||
%>
|
||||
|
@ -647,6 +550,7 @@ ShowDetailName<input type="checkbox" id="showWhole" style="margin-right:10px">
|
|||
</tr>
|
||||
<% } %>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% if (numRegions > numRegionsRendered) {
|
||||
String allRegionsUrl = "?name=" + URLEncoder.encode(fqtn,"UTF-8") + "&numRegions=all";
|
||||
|
@ -659,11 +563,12 @@ ShowDetailName<input type="checkbox" id="showWhole" style="margin-right:10px">
|
|||
<%
|
||||
if (withReplica) {
|
||||
%>
|
||||
<table class="table table-striped"><tr><th>Region Server</th><th>Region Count</th><th>Primary Region Count</th></tr>
|
||||
<table id="regionServerTable" class="tablesorter table table-striped"><thead><tr><th>Region Server</th><th>Region Count</th><th>Primary Region Count</th></tr></thead>
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
<table class="table table-striped"><tr><th>Region Server</th><th>Region Count</th></tr>
|
||||
<table id="regionServerTable" class="tablesorter table table-striped"><thead><tr><th>Region Server</th><th>Region Count</th></tr></thead>
|
||||
<tbody>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
|
@ -684,6 +589,7 @@ if (withReplica) {
|
|||
%>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }
|
||||
} catch(Exception ex) {
|
||||
|
@ -811,37 +717,16 @@ Actions:
|
|||
<% } %>
|
||||
|
||||
<jsp:include page="footer.jsp" />
|
||||
<script src="/static/js/jquery.min.js" type="text/javascript"></script>
|
||||
<script src="/static/js/jquery.tablesorter.min.js" type="text/javascript"></script>
|
||||
<script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
|
||||
|
||||
<script>
|
||||
var index=0;
|
||||
var sortKeyValue='<%= StringEscapeUtils.escapeEcmaScript(sortKey) %>';
|
||||
if(sortKeyValue=="readrequest")index=1;
|
||||
else if(sortKeyValue=="writerequest")index=2;
|
||||
else if(sortKeyValue=="size")index=3;
|
||||
else if(sortKeyValue=="filecount")index=4;
|
||||
else if(sortKeyValue=="memstore")index=5;
|
||||
else if(sortKeyValue=="locality")index=6;
|
||||
document.getElementById("sel").selectedIndex=index;
|
||||
|
||||
<% // turned into a boolean when we pulled it out of the request. %>
|
||||
var reverse='<%= reverseOrder %>';
|
||||
if(reverse=='false')document.getElementById("ascending").checked=true;
|
||||
|
||||
<% // turned into a boolean when we pulled it out of the request. %>
|
||||
var showWhole='<%= showWhole %>';
|
||||
if(showWhole=='true')document.getElementById("showWhole").checked=true;
|
||||
|
||||
function reloadAsSort(){
|
||||
var url="?name="+'<%= URLEncoder.encode(fqtn) %>';
|
||||
if(document.getElementById("sel").selectedIndex>=0){
|
||||
url=url+"&sort="+document.getElementById("sel").value;
|
||||
}
|
||||
if(document.getElementById("ascending").checked){
|
||||
url=url+"&reverse=false";
|
||||
}
|
||||
if(document.getElementById("showWhole").checked){
|
||||
url=url+"&showwhole=true";
|
||||
}
|
||||
location.href=url;
|
||||
$(document).ready(function()
|
||||
{
|
||||
$("#regionServerTable").tablesorter();
|
||||
$("#regionServerDetailsTable").tablesorter();
|
||||
$("#tableRegionTable").tablesorter();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 54 B |
Binary file not shown.
After Width: | Height: | Size: 64 B |
Binary file not shown.
After Width: | Height: | Size: 54 B |
|
@ -40,3 +40,17 @@ section { margin-bottom: 3em; }
|
|||
}
|
||||
|
||||
/* Region Server page styling */
|
||||
|
||||
/* sortable tables styling */
|
||||
table.tablesorter thead tr .header {
|
||||
background-image: url(bg.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.tablesorter thead tr .headerSortUp {
|
||||
background-image: url(asc.gif);
|
||||
}
|
||||
table.tablesorter thead tr .headerSortDown {
|
||||
background-image: url(desc.gif);
|
||||
}
|
||||
|
|
4
hbase-server/src/main/resources/hbase-webapps/static/js/jquery.tablesorter.min.js
vendored
Normal file
4
hbase-server/src/main/resources/hbase-webapps/static/js/jquery.tablesorter.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue