You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2021/08/05 01:06:14 UTC

[hbase] branch branch-1 updated: HBASE-25469 Add detailed RIT info in JSON format for consumption as metrics (#3557)

This is an automated email from the ASF dual-hosted git repository.

apurtell pushed a commit to branch branch-1
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-1 by this push:
     new 8c18563  HBASE-25469 Add detailed RIT info in JSON format for consumption as metrics (#3557)
8c18563 is described below

commit 8c18563cad3fcf9e743deff74474a11c1f0b5fd8
Author: caroliney14 <ca...@berkeley.edu>
AuthorDate: Wed Aug 4 18:05:39 2021 -0700

    HBASE-25469 Add detailed RIT info in JSON format for consumption as metrics (#3557)
    
    Signed-off-by: Andrew Purtell <ap...@apache.org>
---
 .../tmpl/master/AssignmentManagerStatusTmpl.jamon  |   2 +-
 .../hbase/tmpl/master/MasterStatusTmpl.jamon       |  13 +-
 .../main/resources/hbase-webapps/master/rits.jsp   | 180 +++++++++++++++++++++
 3 files changed, 191 insertions(+), 4 deletions(-)

diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
index f97860b..8ca80a6 100644
--- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
+++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/AssignmentManagerStatusTmpl.jamon
@@ -73,7 +73,7 @@ int numOfPages = (int) Math.ceil(numOfRITs * 1.0 / ritsPerPage);
 </%java>
     <section>
     <h2>Regions in Transition</h2>
-     <p><% numOfRITs %> region(s) in transition.
+     <p><a href="/rits.jsp"><% numOfRITs %> region(s) in transition.</a>
      <%if !ritsTwiceThreshold.isEmpty()  %>
          <span class="label label-danger" style="font-size:100%;font-weight:normal">
      <%elseif !ritsOverThreshold.isEmpty() %>
diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
index 0d02f99..0b331b8 100644
--- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
+++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/master/MasterStatusTmpl.jamon
@@ -195,6 +195,10 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
           </div>
         </%if>
 
+        <%if master.getAssignmentManager() != null %>
+        <& AssignmentManagerStatusTmpl; assignmentManager=master.getAssignmentManager()&>
+        </%if>
+
         <section>
             <h2>Region Servers</h2>
             <& RegionServerListTmpl; master= master; servers = servers &>
@@ -241,9 +245,6 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
             <h2>Peers</h2>
             <& peerConfigs &>
         </section>
-        <%if master.getAssignmentManager() != null %>
-        <& AssignmentManagerStatusTmpl; assignmentManager=master.getAssignmentManager()&>
-        </%if>
 	<%else>
         <section>
             <& BackupMasterStatusTmpl; master = master &>
@@ -472,6 +473,9 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
           master.getAssignmentManager().getRegionStates()
             .getRegionByStateOfTable(tableName);
       int openRegionsCount = tableRegions.get(RegionState.State.OPEN).size();
+      int openingRegionsCount = tableRegions.get(RegionState.State.OPENING).size();
+      int closedRegionsCount = tableRegions.get(RegionState.State.CLOSED).size();
+      int closingRegionsCount = tableRegions.get(RegionState.State.CLOSING).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()
@@ -492,6 +496,9 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
             <td align="center"><% frags.get(tableName.getNameAsString()) != null ? frags.get(tableName.getNameAsString()).intValue() + "%" : "n/a" %></td>
         </%if>
         <td><% openRegionsCount %></td>
+        <%if (openingRegionsCount > 0) %> <td><a href="/rits.jsp?table=<% tableName.getNameAsString() %>&state=OPENING"><% openingRegionsCount %></td> <%else><td><% openingRegionsCount %></td> </%if>
+        <td><% closedRegionsCount %></td>
+        <%if (closingRegionsCount > 0) %> <td><a href="/rits.jsp?table=<% tableName.getNameAsString() %>&state=CLOSING"><% closingRegionsCount %></td> <%else><td><% closingRegionsCount %></td> </%if>
         <td><% offlineRegionsCount %></td>
         <td><% failedRegionsCount %></td>
         <td><% splitRegionsCount %></td>
diff --git a/hbase-server/src/main/resources/hbase-webapps/master/rits.jsp b/hbase-server/src/main/resources/hbase-webapps/master/rits.jsp
new file mode 100644
index 0000000..cf21acb
--- /dev/null
+++ b/hbase-server/src/main/resources/hbase-webapps/master/rits.jsp
@@ -0,0 +1,180 @@
+<%--
+/**
+ * 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.List"
+         import="java.util.HashMap"
+         import="java.util.HashSet"
+         import="java.util.Map"
+         import="java.util.Set"
+         import="org.apache.hadoop.hbase.HBaseConfiguration"
+         import="org.apache.hadoop.hbase.master.HMaster"
+         import="org.apache.hadoop.hbase.master.RegionState"
+         import="org.apache.hadoop.hbase.util.GsonUtil"
+         import="org.apache.hbase.thirdparty.com.google.gson.Gson"
+%>
+<%
+    HMaster master = (HMaster) getServletContext().getAttribute(HMaster.MASTER);
+    Set<RegionState> rit = master.getAssignmentManager().getRegionStates().getRegionsInTransition();
+    String table = request.getParameter("table");
+    String state = request.getParameter("state");
+    if (table != null && state != null && !table.equals("null") && !state.equals("null")) {
+        Set<RegionState> ritFiltered = new HashSet<>();
+        for (RegionState regionState: rit) {
+            if (regionState.getRegion().getTable().getNameAsString().equals(table) &&
+              regionState.getState().name().equals(state)){
+                ritFiltered.add(regionState);
+            }
+        }
+        rit = ritFiltered;
+    }
+
+    String format = request.getParameter("format");
+    if(format == null || format.isEmpty()){
+        format = "html";
+    }
+    String filter = request.getParameter("filter");
+%>
+
+
+<% if (format.equals("html")) { %>
+<!--[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>HBase Master Procedures: <%= master.getServerName() %></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="/master-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="/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>
+        <li><a href="/prof">Profiler</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>Regions in transition</h1>
+        </div>
+    </div>
+    <div class="row">
+        <div class="page-header">
+            <a href="/rits.jsp?format=txt&filter=region&table=<%=table%>&state=<%=state%>" class="btn btn-primary">Regions in text format</a>
+            <a href="/rits.jsp?format=json&table=<%=table%>&state=<%=state%>" class="btn btn-info">RIT info as JSON</a>
+            <p>regions in text format can be copied and passed to command-line utils such as hbck2</p>
+        </div>
+    </div>
+
+    <% if (rit != null && rit.size() > 0) { %>
+        <table class="table table-striped">
+            <tr>
+                <th>Region</th>
+                <th>Table</th>
+                <th>RegionState</th>
+                <th>Server</th>
+                <th>Start Time</th>
+                <th>Duration (ms)</th>
+            </tr>
+            <% for (RegionState regionState : rit) { %>
+            <tr>
+                <td><%= regionState.getRegion().getEncodedName() %></td>
+                <td><%= regionState.getRegion().getTable() %></td>
+                <td><%= regionState.getState() %></td>
+                <td><%= regionState.getServerName() %></td>
+                <td><%= regionState.getStamp() %></td>
+                <td><%= regionState.getRitDuration() %></td>
+            </tr>
+            <% } %>
+            <p><%= rit.size() %> region(s) in transition.</p>
+        </table>
+    <% } else { %>
+        <p> no region in transition right now. </p>
+    <% } %>
+</div>
+<script src="/static/js/jquery.min.js" type="text/javascript"></script>
+<script src="/static/js/bootstrap.min.js" type="text/javascript"></script>
+
+</body>
+</html>
+<% } else if (format.equals("json")) { %>
+    <%
+        Gson GSON = GsonUtil.createGson().create();
+        Map<String, List<Map<String, Object>>> map = new HashMap<>();
+        List<Map<String, Object>> rits = new ArrayList<>();
+        map.put("rits", rits);
+        for (RegionState regionState : rit) {
+            Map<String, Object> r = new HashMap<>();
+            r.put("region", regionState.getRegion().getEncodedName());
+            r.put("table", regionState.getRegion().getTable().getNameAsString());
+            r.put("state", regionState.getState());
+            r.put("server", regionState.getServerName());
+            r.put("startTime", regionState.getStamp());
+            r.put("duration", regionState.getRitDuration());
+            rits.add(r);
+        }
+    %>
+    <%= GSON.toJson(map) %>
+<% } else { %>
+<div class="container-fluid content">
+  <div class="row">
+    <p>
+      <%
+        if (filter.equals("region")) {
+          for (RegionState regionState : rit) { %>
+            <%= regionState.getRegion().getEncodedName() %><br>
+      <%  }
+      } else { %>
+      "Not a valid filter"
+      <% } %>
+    </p>
+  </div>
+</div>
+<% } %>