HBASE-15675 Add more details about region on table.jsp
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/082d1934 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/082d1934 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/082d1934 Branch: refs/heads/hbase-12439 Commit: 082d193455125f451d3fc1a63146ca024899dd0f Parents: c77a153 Author: Yu Li <l...@apache.org> Authored: Tue May 3 12:00:09 2016 +0800 Committer: Yu Li <l...@apache.org> Committed: Tue May 3 20:18:48 2016 +0800 ---------------------------------------------------------------------- .../resources/hbase-webapps/master/table.jsp | 361 +++++++++++++++++-- 1 file changed, 335 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/082d1934/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 693a663..ee2a7ba 100644 --- a/hbase-server/src/main/resources/hbase-webapps/master/table.jsp +++ b/hbase-server/src/main/resources/hbase-webapps/master/table.jsp @@ -19,13 +19,19 @@ --%> <%@ page contentType="text/html;charset=UTF-8" import="static org.apache.commons.lang.StringEscapeUtils.escapeXml" + import="com.google.protobuf.ByteString" + import="java.util.ArrayList" import="java.util.TreeMap" import="java.util.List" + import="java.util.LinkedHashMap" import="java.util.Map" import="java.util.Set" import="java.util.Collection" + import="java.util.Collections" + import="java.util.Comparator" import="org.owasp.esapi.ESAPI" import="org.apache.hadoop.conf.Configuration" + import="org.apache.hadoop.util.StringUtils" import="org.apache.hadoop.hbase.client.HTable" import="org.apache.hadoop.hbase.client.Admin" import="org.apache.hadoop.hbase.client.CompactionState" @@ -40,6 +46,8 @@ import="org.apache.hadoop.hbase.zookeeper.MetaTableLocator" import="org.apache.hadoop.hbase.util.Bytes" import="org.apache.hadoop.hbase.util.FSUtils" + import="org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos" + import="org.apache.hadoop.hbase.protobuf.generated.HBaseProtos" import="org.apache.hadoop.hbase.TableName" import="org.apache.hadoop.hbase.HColumnDescriptor" import="org.apache.hadoop.hbase.client.RegionReplicaUtil" @@ -51,6 +59,11 @@ MetaTableLocator metaTableLocator = new MetaTableLocator(); String fqtn = request.getParameter("name"); + String sortKey = request.getParameter("sort"); + String reverse = request.getParameter("reverse"); + final boolean reverseOrder = (reverse==null||!reverse.equals("false")); + String showWholeKey = request.getParameter("showwhole"); + final boolean showWhole = (showWholeKey!=null && showWholeKey.equals("true")); HTable table = null; String tableHeader; boolean withReplica = false; @@ -130,10 +143,10 @@ if ( fqtn != null ) { try { table = (HTable) 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 style=\"width:22%\">Name</th><th>Region Server</th><th style=\"width:22%\">Start Key</th><th style=\"width:22%\">End Key</th><th>Locality</th><th>Requests</th><th>ReplicaID</th></tr>"; + 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>"; withReplica = true; } else { - tableHeader = "<h2>Table Regions</h2><table class=\"table table-striped\" style=\"table-layout: fixed; word-wrap: break-word;\"><tr><th style=\"width:22%\">Name</th><th>Region Server</th><th style=\"width:22%\">Start Key</th><th style=\"width:22%\">End Key</th><th>Locality</th><th>Requests</th></tr>"; + 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>"; } if ( !readOnly && action != null ) { %> @@ -187,16 +200,42 @@ if ( fqtn != null ) { HRegionInfo.FIRST_META_REGIONINFO, j); ServerName metaLocation = metaTableLocator.waitMetaRegionLocation(master.getZooKeeper(), j, 1); for (int i = 0; i < 1; i++) { - String url = "//" + metaLocation.getHostname() + ":" + - master.getRegionServerInfoPort(metaLocation) + "/"; + String url = ""; + String readReq = "N/A"; + String writeReq = "N/A"; + String fileSize = "N/A"; + String fileCount = "N/A"; + String memSize = "N/A"; + float locality = 0.0f; + + if (metaLocation != null) { + ServerLoad sl = master.getServerManager().getLoad(metaLocation); + url = "//" + metaLocation.getHostname() + ":" + master.getRegionServerInfoPort(metaLocation) + "/"; + if (sl != null) { + Map<byte[], RegionLoad> map = sl.getRegionsLoad(); + if (map.containsKey(meta.getRegionName())) { + RegionLoad load = map.get(meta.getRegionName()); + readReq = String.format("%,1d", load.getReadRequestsCount()); + writeReq = String.format("%,1d", load.getWriteRequestsCount()); + fileSize = StringUtils.byteDesc(load.getStorefileSizeMB()*1024l*1024); + fileCount = String.format("%,1d", load.getStorefiles()); + memSize = StringUtils.byteDesc(load.getMemStoreSizeMB()*1024l*1024); + locality = load.getDataLocality(); + } + } + } %> <tr> <td><%= escapeXml(meta.getRegionNameAsString()) %></td> <td><a href="<%= url %>"><%= metaLocation.getHostname().toString() + ":" + master.getRegionServerInfoPort(metaLocation) %></a></td> + <td><%= readReq%></td> + <td><%= writeReq%></td> + <td><%= fileSize%></td> + <td><%= fileCount%></td> + <td><%= memSize%></td> + <td><%= locality%></td> <td><%= escapeXml(Bytes.toString(meta.getStartKey())) %></td> <td><%= escapeXml(Bytes.toString(meta.getEndKey())) %></td> - <td>-</td> - <td>-</td> </tr> <% } %> <%} %> @@ -280,27 +319,265 @@ if ( fqtn != null ) { <% } %> </table> <% + long totalReadReq = 0; + long totalWriteReq = 0; + long totalSize = 0; + long totalStoreFileCount = 0; + long totalMemSize = 0; + String urlRegionServer = null; Map<ServerName, Integer> regDistribution = new TreeMap<ServerName, Integer>(); Map<ServerName, Integer> primaryRegDistribution = new TreeMap<ServerName, Integer>(); List<HRegionLocation> regions = r.getAllRegionLocations(); - if(regions != null && regions.size() > 0) { %> -<%= tableHeader %> -<% + Map<HRegionInfo, RegionLoad> regionsToLoad = new LinkedHashMap<HRegionInfo, RegionLoad>(); + Map<HRegionInfo, ServerName> regionsToServer = new LinkedHashMap<HRegionInfo, ServerName>(); for (HRegionLocation hriEntry : regions) { HRegionInfo regionInfo = hriEntry.getRegionInfo(); ServerName addr = hriEntry.getServerName(); - long req = 0; - float locality = 0.0f; - String urlRegionServer = null; + regionsToServer.put(regionInfo, addr); if (addr != null) { ServerLoad sl = master.getServerManager().getLoad(addr); if (sl != null) { Map<byte[], RegionLoad> map = sl.getRegionsLoad(); - if (map.containsKey(regionInfo.getRegionName())) { - req = map.get(regionInfo.getRegionName()).getRequestsCount(); - locality = map.get(regionInfo.getRegionName()).getDataLocality(); + RegionLoad regionload = map.get(regionInfo.getRegionName()); + regionsToLoad.put(regionInfo, regionload); + if(regionload != null) { + totalReadReq += regionload.getReadRequestsCount(); + totalWriteReq += regionload.getWriteRequestsCount(); + totalSize += regionload.getStorefileSizeMB(); + totalStoreFileCount += regionload.getStorefiles(); + totalMemSize += regionload.getMemStoreSizeMB(); + } else { + RegionLoad load0 = new RegionLoad(ClusterStatusProtos.RegionLoad.newBuilder().setRegionSpecifier(HBaseProtos.RegionSpecifier.newBuilder().setValue(ByteString.copyFrom(regionInfo.getRegionName())).build()).build()); + regionsToLoad.put(regionInfo, load0); } + }else{ + RegionLoad load0 = new RegionLoad(ClusterStatusProtos.RegionLoad.newBuilder().setRegionSpecifier(HBaseProtos.RegionSpecifier.newBuilder().setValue(ByteString.copyFrom(regionInfo.getRegionName())).build()).build()); + regionsToLoad.put(regionInfo, load0); + } + }else{ + RegionLoad load0 = new RegionLoad(ClusterStatusProtos.RegionLoad.newBuilder().setRegionSpecifier(HBaseProtos.RegionSpecifier.newBuilder().setValue(ByteString.copyFrom(regionInfo.getRegionName())).build()).build()); + regionsToLoad.put(regionInfo, load0); + } + } + + 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&Start/End Key<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"> +<tr> +<th>Name(<%= String.format("%,1d", regions.size())%>)</th> +<th>Region Server</th> +<th>ReadRequests<br>(<%= String.format("%,1d", totalReadReq)%>)</th> +<th>WriteRequests<br>(<%= String.format("%,1d", totalWriteReq)%>)</th> +<th>StorefileSize<br>(<%= StringUtils.byteDesc(totalSize*1024l*1024)%>)</th> +<th>Num.Storefiles<br>(<%= String.format("%,1d", totalStoreFileCount)%>)</th> +<th>MemSize<br>(<%= StringUtils.byteDesc(totalMemSize*1024l*1024)%>)</th> +<th>Locality</th> +<th>Start Key</th> +<th>End Key</th> +<% + if (withReplica) { +%> +<th>ReplicaID</th> +<% + } +%> +</tr> + +<% + List<Map.Entry<HRegionInfo, RegionLoad>> entryList = new ArrayList<Map.Entry<HRegionInfo, RegionLoad>>(regionsToLoad.entrySet()); + if(sortKey != null) { + if (sortKey.equals("readrequest")) { + Collections.sort(entryList, + new Comparator<Map.Entry<HRegionInfo, RegionLoad>>() { + public int compare( + Map.Entry<HRegionInfo, RegionLoad> entry1, + Map.Entry<HRegionInfo, RegionLoad> entry2) { + if (entry1 == null || entry1.getValue() == null) { + return -1; + } else if (entry2 == null || entry2.getValue() == null) { + return 1; + } + int result = 0; + if (entry1.getValue().getReadRequestsCount() < entry2.getValue().getReadRequestsCount()) { + result = -1; + } else if (entry1.getValue().getReadRequestsCount() > entry2.getValue().getReadRequestsCount()) { + result = 1; + } + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); + } else if (sortKey.equals("writerequest")) { + Collections.sort(entryList, + new Comparator<Map.Entry<HRegionInfo, RegionLoad>>() { + public int compare( + Map.Entry<HRegionInfo, RegionLoad> entry1, + Map.Entry<HRegionInfo, RegionLoad> entry2) { + if (entry1 == null || entry1.getValue() == null) { + return -1; + } else if (entry2 == null || entry2.getValue() == null) { + return 1; + } + int result = 0; + if (entry1.getValue().getWriteRequestsCount() < entry2.getValue() + .getWriteRequestsCount()) { + result = -1; + } else if (entry1.getValue().getWriteRequestsCount() > entry2.getValue() + .getWriteRequestsCount()) { + result = 1; + } + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); + } else if (sortKey.equals("size")) { + Collections.sort(entryList, + new Comparator<Map.Entry<HRegionInfo, RegionLoad>>() { + public int compare( + Map.Entry<HRegionInfo, RegionLoad> entry1, + Map.Entry<HRegionInfo, RegionLoad> entry2) { + if (entry1 == null || entry1.getValue() == null) { + return -1; + } else if (entry2 == null || entry2.getValue() == null) { + return 1; + } + int result = 0; + if (entry1.getValue().getStorefileSizeMB() < entry2.getValue() + .getStorefileSizeMB()) { + result = -1; + } else if (entry1.getValue().getStorefileSizeMB() > entry2 + .getValue().getStorefileSizeMB()) { + result = 1; + } + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); + } else if (sortKey.equals("filecount")) { + Collections.sort(entryList, + new Comparator<Map.Entry<HRegionInfo, RegionLoad>>() { + public int compare( + Map.Entry<HRegionInfo, RegionLoad> entry1, + Map.Entry<HRegionInfo, RegionLoad> entry2) { + if (entry1 == null || entry1.getValue() == null) { + return -1; + } else if (entry2 == null || entry2.getValue() == null) { + return 1; + } + int result = 0; + if (entry1.getValue().getStorefiles() < entry2.getValue() + .getStorefiles()) { + result = -1; + } else if (entry1.getValue().getStorefiles() > entry2.getValue() + .getStorefiles()) { + result = 1; + } + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); + } else if (sortKey.equals("memstore")) { + Collections.sort(entryList, + new Comparator<Map.Entry<HRegionInfo, RegionLoad>>() { + public int compare( + Map.Entry<HRegionInfo, RegionLoad> entry1, + Map.Entry<HRegionInfo, RegionLoad> entry2) { + if (entry1 == null || entry1.getValue()==null) { + return -1; + } else if (entry2 == null || entry2.getValue()==null) { + return 1; + } + int result = 0; + if (entry1.getValue().getMemStoreSizeMB() < entry2.getValue() + .getMemStoreSizeMB()) { + result = -1; + } else if (entry1.getValue().getMemStoreSizeMB() > entry2 + .getValue().getMemStoreSizeMB()) { + result = 1; + } + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); + } else if (sortKey.equals("locality")) { + Collections.sort(entryList, + new Comparator<Map.Entry<HRegionInfo, RegionLoad>>() { + public int compare( + Map.Entry<HRegionInfo, RegionLoad> entry1, + Map.Entry<HRegionInfo, RegionLoad> entry2) { + if (entry1 == null || entry1.getValue()==null) { + return -1; + } else if (entry2 == null || entry2.getValue()==null) { + return 1; + } + int result = 0; + if (entry1.getValue().getDataLocality() < entry2.getValue() + .getDataLocality()) { + result = -1; + } else if (entry1.getValue().getDataLocality() > entry2 + .getValue().getDataLocality()) { + result = 1; + } + if (reverseOrder) { + result = -1 * result; + } + return result; + } + }); + } + } + + for (Map.Entry<HRegionInfo, RegionLoad> hriEntry : entryList) { + HRegionInfo regionInfo = hriEntry.getKey(); + ServerName addr = regionsToServer.get(regionInfo); + RegionLoad load = hriEntry.getValue(); + String readReq = "N/A"; + String writeReq = "N/A"; + String regionSize = "N/A"; + String fileCount = "N/A"; + String memSize = "N/A"; + float locality = 0.0f; + if(load != null) { + readReq = String.format("%,1d", load.getReadRequestsCount()); + writeReq = String.format("%,1d", load.getWriteRequestsCount()); + regionSize = StringUtils.byteDesc(load.getStorefileSizeMB()*1024l*1024); + fileCount = String.format("%,1d", load.getStorefiles()); + memSize = StringUtils.byteDesc(load.getMemStoreSizeMB()*1024l*1024); + locality = load.getDataLocality(); + } + + if (addr != null) { + ServerLoad sl = master.getServerManager().getLoad(addr); + // This port might be wrong if RS actually ended up using something else. + urlRegionServer = + "//" + addr.getHostname() + ":" + master.getRegionServerInfoPort(addr) + "/"; + if(sl != null) { Integer i = regDistribution.get(addr); if (null == i) i = Integer.valueOf(0); regDistribution.put(addr, i + 1); @@ -313,14 +590,12 @@ if ( fqtn != null ) { } %> <tr> - <td><%= escapeXml(Bytes.toStringBinary(HRegionInfo.getRegionNameForDisplay(regionInfo, - conf))) %></td> + <td><%= escapeXml(showWhole?Bytes.toStringBinary(regionInfo.getRegionName()):regionInfo.getEncodedName()) %></td> <% - if (addr != null) { - String url = "//" + addr.getHostname() + ":" + master.getRegionServerInfoPort(addr) + "/rs-status"; + if (urlRegionServer != null) { %> <td> - <a href="<%= url %>"><%= addr.getHostname().toString() + ":" + addr.getPort() %></a> + <a href="<%= urlRegionServer %>"><%= addr.getHostname().toString() + ":" + master.getRegionServerInfoPort(addr) %></a> </td> <% } else { @@ -329,12 +604,14 @@ if ( fqtn != null ) { <% } %> - <td><%= escapeXml(Bytes.toStringBinary(HRegionInfo.getStartKeyForDisplay(regionInfo, - conf))) %></td> - <td><%= escapeXml(Bytes.toStringBinary(HRegionInfo.getEndKeyForDisplay(regionInfo, - conf))) %></td> + <td><%= readReq%></td> + <td><%= writeReq%></td> + <td><%= regionSize%></td> + <td><%= fileCount%></td> + <td><%= memSize%></td> <td><%= locality%></td> - <td><%= req%></td> + <td><%= escapeXml(showWhole?Bytes.toStringBinary(regionInfo.getStartKey()):"-")%></td> + <td><%= escapeXml(showWhole?Bytes.toStringBinary(regionInfo.getEndKey()):"-")%></td> <% if (withReplica) { %> @@ -363,7 +640,7 @@ if (withReplica) { String url = "//" + addr.getHostname() + ":" + master.getRegionServerInfoPort(addr) + "/"; %> <tr> - <td><a href="<%= url %>"><%= addr.getHostname().toString() + ":" + addr.getPort() %></a></td> + <td><a href="<%= url %>"><%= addr.getHostname().toString() + ":" + master.getRegionServerInfoPort(addr) %></a></td> <td><%= rdEntry.getValue()%></td> <% if (withReplica) { @@ -465,3 +742,35 @@ Actions: </body> </html> + +<script> +var index=0; +var sortKeyValue='<%= 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; + +var reverse='<%= reverseOrder %>'; +if(reverse=='false')document.getElementById("ascending").checked=true; + +var showWhole='<%= showWhole %>'; +if(showWhole=='true')document.getElementById("showWhole").checked=true; + +function reloadAsSort(){ + var url="?name="+'<%= 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; +} +</script>