You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ni...@apache.org on 2024/01/14 06:42:50 UTC
(hbase) branch branch-3 updated: HBASE-27814 Add support for dump and process metrics servlet in REST InfoServer (#5215)
This is an automated email from the ASF dual-hosted git repository.
nihaljain pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-3 by this push:
new 5129cbe3a6a HBASE-27814 Add support for dump and process metrics servlet in REST InfoServer (#5215)
5129cbe3a6a is described below
commit 5129cbe3a6aa90e8e5112b65d007893bcec126a8
Author: Nihal Jain <ni...@apache.org>
AuthorDate: Sun Jan 14 11:59:26 2024 +0530
HBASE-27814 Add support for dump and process metrics servlet in REST InfoServer (#5215)
Other changes:
- Ensure info server stops during stop()
- Extract header and footer. This would fix the log level page layout for rest web UI (See HBASE-20693)
- Add hostname in the landing page instead of just port similar to other web UIs
Signed-off-by: Nick Dimiduk <nd...@apache.org>
(cherry picked from commit a683fcfbe8c5c84e58fa8670f4414f9d01ff43ed)
---
.../apache/hadoop/hbase/rest/RESTDumpServlet.java | 80 +++++++++
.../org/apache/hadoop/hbase/rest/RESTServer.java | 39 ++++-
.../main/resources/hbase-webapps/rest/footer.jsp | 32 ++++
.../main/resources/hbase-webapps/rest/header.jsp | 74 +++++++++
.../resources/hbase-webapps/rest/processRest.jsp | 184 +++++++++++++++++++++
.../src/main/resources/hbase-webapps/rest/rest.jsp | 80 ++-------
6 files changed, 422 insertions(+), 67 deletions(-)
diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTDumpServlet.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTDumpServlet.java
new file mode 100644
index 00000000000..8bb306f7829
--- /dev/null
+++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTDumpServlet.java
@@ -0,0 +1,80 @@
+/*
+ * 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.rest;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Date;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.http.HttpServer;
+import org.apache.hadoop.hbase.monitoring.StateDumpServlet;
+import org.apache.hadoop.hbase.util.LogMonitoring;
+import org.apache.hadoop.hbase.util.Threads;
+import org.apache.yetus.audience.InterfaceAudience;
+
+@InterfaceAudience.Private
+public class RESTDumpServlet extends StateDumpServlet {
+ private static final long serialVersionUID = 1L;
+ private static final String LINE = "===========================================================";
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response)) {
+ return;
+ }
+
+ RESTServer restServer = (RESTServer) getServletContext().getAttribute(RESTServer.REST_SERVER);
+ assert restServer != null : "No REST Server in context!";
+
+ response.setContentType("text/plain");
+ OutputStream os = response.getOutputStream();
+ try (PrintWriter out = new PrintWriter(os)) {
+
+ out.println("REST Server status for " + restServer.getServerName() + " as of " + new Date());
+
+ out.println("\n\nVersion Info:");
+ out.println(LINE);
+ dumpVersionInfo(out);
+
+ out.println("\n\nStacks:");
+ out.println(LINE);
+ out.flush();
+ PrintStream ps = new PrintStream(response.getOutputStream(), false, "UTF-8");
+ Threads.printThreadInfo(ps, "");
+ ps.flush();
+
+ out.println("\n\nREST Server configuration:");
+ out.println(LINE);
+ Configuration conf = restServer.conf;
+ out.flush();
+ conf.writeXml(os);
+ os.flush();
+
+ out.println("\n\nLogs");
+ out.println(LINE);
+ long tailKb = getTailKbParam(request);
+ LogMonitoring.dumpTailOfLogs(out, tailKb);
+
+ out.flush();
+ }
+ }
+}
diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
index 886c81dc668..42c00480526 100644
--- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
+++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.hbase.rest;
import java.lang.management.ManagementFactory;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
@@ -29,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
+import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.http.ClickjackingPreventionFilter;
import org.apache.hadoop.hbase.http.HttpServerUtil;
import org.apache.hadoop.hbase.http.InfoServer;
@@ -83,6 +85,7 @@ import org.apache.hbase.thirdparty.org.glassfish.jersey.servlet.ServletContainer
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
public class RESTServer implements Constants {
static Logger LOG = LoggerFactory.getLogger("RESTServer");
+ public static final String REST_SERVER = "rest";
static final String REST_CSRF_ENABLED_KEY = "hbase.rest.csrf.enabled";
static final boolean REST_CSRF_ENABLED_DEFAULT = false;
@@ -112,6 +115,7 @@ public class RESTServer implements Constants {
private final UserProvider userProvider;
private Server server;
private InfoServer infoServer;
+ private ServerName serverName;
public RESTServer(Configuration conf) {
RESTServer.conf = conf;
@@ -163,8 +167,7 @@ public class RESTServer implements Constants {
loginServerPrincipal(UserProvider userProvider, Configuration conf) throws Exception {
Class<? extends ServletContainer> containerClass = ServletContainer.class;
if (userProvider.isHadoopSecurityEnabled() && userProvider.isHBaseSecurityEnabled()) {
- String machineName = Strings.domainNamePointerToHostName(DNS.getDefaultHost(
- conf.get(REST_DNS_INTERFACE, "default"), conf.get(REST_DNS_NAMESERVER, "default")));
+ String machineName = getHostName(conf);
String keytabFilename = conf.get(REST_KEYTAB_FILE);
Preconditions.checkArgument(keytabFilename != null && !keytabFilename.isEmpty(),
REST_KEYTAB_FILE + " should be set if security is enabled");
@@ -402,9 +405,14 @@ public class RESTServer implements Constants {
// Put up info server.
int port = conf.getInt("hbase.rest.info.port", 8085);
if (port >= 0) {
- conf.setLong("startcode", EnvironmentEdgeManager.currentTime());
- String a = conf.get("hbase.rest.info.bindAddress", "0.0.0.0");
- this.infoServer = new InfoServer("rest", a, port, false, conf);
+ final long startCode = EnvironmentEdgeManager.currentTime();
+ conf.setLong("startcode", startCode);
+ this.serverName = ServerName.valueOf(getHostName(conf), servicePort, startCode);
+
+ String addr = conf.get("hbase.rest.info.bindAddress", "0.0.0.0");
+ this.infoServer = new InfoServer(REST_SERVER, addr, port, false, conf);
+ this.infoServer.addPrivilegedServlet("dump", "/dump", RESTDumpServlet.class);
+ this.infoServer.setAttribute(REST_SERVER, this);
this.infoServer.setAttribute("hbase.conf", conf);
this.infoServer.start();
}
@@ -412,6 +420,11 @@ public class RESTServer implements Constants {
server.start();
}
+ private static String getHostName(Configuration conf) throws UnknownHostException {
+ return Strings.domainNamePointerToHostName(DNS.getDefaultHost(
+ conf.get(REST_DNS_INTERFACE, "default"), conf.get(REST_DNS_NAMESERVER, "default")));
+ }
+
public synchronized void join() throws Exception {
if (server == null) {
throw new IllegalStateException("Server is not running");
@@ -419,7 +432,19 @@ public class RESTServer implements Constants {
server.join();
}
+ private void stopInfoServer() {
+ if (this.infoServer != null) {
+ LOG.info("Stop info server");
+ try {
+ this.infoServer.stop();
+ } catch (Exception e) {
+ LOG.error("Failed to stop infoServer", e);
+ }
+ }
+ }
+
public synchronized void stop() throws Exception {
+ stopInfoServer();
if (server == null) {
throw new IllegalStateException("Server is not running");
}
@@ -443,6 +468,10 @@ public class RESTServer implements Constants {
return infoServer.getPort();
}
+ public ServerName getServerName() {
+ return serverName;
+ }
+
public Configuration getConf() {
return conf;
}
diff --git a/hbase-rest/src/main/resources/hbase-webapps/rest/footer.jsp b/hbase-rest/src/main/resources/hbase-webapps/rest/footer.jsp
new file mode 100644
index 00000000000..a642ac36eff
--- /dev/null
+++ b/hbase-rest/src/main/resources/hbase-webapps/rest/footer.jsp
@@ -0,0 +1,32 @@
+<%--
+/**
+* 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.
+*/
+--%>
+
+ <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>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $('div.navbar li.active').removeClass('active');
+ $('a[href="' + location.pathname + '"]').closest('li').addClass('active');
+ });
+ </script>
+</body>
+</html>
+
diff --git a/hbase-rest/src/main/resources/hbase-webapps/rest/header.jsp b/hbase-rest/src/main/resources/hbase-webapps/rest/header.jsp
new file mode 100644
index 00000000000..67f7656de59
--- /dev/null
+++ b/hbase-rest/src/main/resources/hbase-webapps/rest/header.jsp
@@ -0,0 +1,74 @@
+<%--
+/**
+* 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="org.apache.hadoop.hbase.HBaseConfiguration"%>
+
+<!DOCTYPE html>
+<?xml version="1.0" encoding="UTF-8" ?>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title><%= request.getParameter("pageTitle")%></title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="description" 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="/rest.jsp"><img src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
+ </div>
+ <div class="collapse navbar-collapse">
+ <ul class="nav navbar-nav">
+ <li class="active"><a href="/rest.jsp">Home</a></li>
+ <li><a href="/logs/">Local logs</a></li>
+ <li><a href="/processRest.jsp">Process Metrics</a></li>
+ <li><a href="/logLevel">Log Level</a></li>
+ <li><a href="/dump">Debug Dump</a></li>
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Metrics <span class="caret"></span>
+ </a>
+ <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
+ <li><a target="_blank" href="/jmx">JMX</a></li>
+ <li><a target="_blank" href="/jmx?description=true">JMX with description</a></li>
+ <li><a target="_blank" href="/prometheus">Prometheus</a></li>
+ <li><a target="_blank" href="/prometheus?description=true">Prometheus with description</a></li>
+ </ul>
+ </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>
+
diff --git a/hbase-rest/src/main/resources/hbase-webapps/rest/processRest.jsp b/hbase-rest/src/main/resources/hbase-webapps/rest/processRest.jsp
new file mode 100644
index 00000000000..2b2d35fbfb3
--- /dev/null
+++ b/hbase-rest/src/main/resources/hbase-webapps/rest/processRest.jsp
@@ -0,0 +1,184 @@
+<%--
+/**
+ * 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="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.apache.hadoop.util.StringUtils.TraditionalBinaryPrefix"
+%>
+
+<%
+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();
+pageContext.setAttribute("pageTitle", "Process info for PID: " + JSONMetricUtil.getProcessPID());
+%>
+
+<jsp:include page="header.jsp">
+ <jsp:param name="pageTitle" value="${pageTitle}"/>
+</jsp:include>
+
+<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()) %></td>
+ <td><%= StringUtils.humanTimeDiff(runtimeBean.getUptime()) %></td>
+ <td><%= JSONMetricUtil.getProcessPID() %></td>
+ <td><%= runtimeBean.getSystemProperties().get("user.name") %></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") %></td>
+ <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsRunnable")%></td>
+ <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsBlocked")%></td>
+ <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsWaiting")%></td>
+ <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTimedWaiting")%></td>
+ <td><%= JSONMetricUtil.getValueFromMBean(jvmMetrics, "ThreadsTerminated")%></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><%= TraditionalBinaryPrefix.long2String(mp.getUsage().getCommitted(), "B", 1) %></td>
+ <td><%= TraditionalBinaryPrefix.long2String(mp.getUsage().getInit(), "B", 1) %></td>
+ <td><%= TraditionalBinaryPrefix.long2String(mp.getUsage().getMax(), "B", 1) %></td>
+ <td><%= TraditionalBinaryPrefix.long2String(mp.getUsage().getUsed(), "B", 1) %></td>
+ <td><%= JSONMetricUtil.calcPercentage(mp.getUsage().getUsed(),
+ mp.getUsage().getCommitted()) %></td>
+ </tr>
+ </table>
+</div>
+<% } %>
+
+<jsp:include page="footer.jsp" />
diff --git a/hbase-rest/src/main/resources/hbase-webapps/rest/rest.jsp b/hbase-rest/src/main/resources/hbase-webapps/rest/rest.jsp
index df8f0838d6c..ce6725f283a 100644
--- a/hbase-rest/src/main/resources/hbase-webapps/rest/rest.jsp
+++ b/hbase-rest/src/main/resources/hbase-webapps/rest/rest.jsp
@@ -18,70 +18,29 @@
*/
--%>
<%@ page contentType="text/html;charset=UTF-8"
- import="org.apache.hadoop.conf.Configuration"
- import="org.apache.hadoop.hbase.HBaseConfiguration"
- import="org.apache.hadoop.hbase.rest.model.VersionModel"
- import="org.apache.hadoop.hbase.util.VersionInfo"
- import="java.util.Date"%>
+ import="org.apache.hadoop.conf.Configuration"
+ import="org.apache.hadoop.hbase.rest.RESTServer"
+ import="org.apache.hadoop.hbase.rest.model.VersionModel"
+ import="org.apache.hadoop.hbase.util.VersionInfo"
+ import="java.util.Date"%>
+
<%
-Configuration conf = (Configuration)getServletContext().getAttribute("hbase.conf");
-long startcode = conf.getLong("startcode", System.currentTimeMillis());
-String listenPort = conf.get("hbase.rest.port", "8080");
-%>
-<!DOCTYPE html>
-<?xml version="1.0" encoding="UTF-8" ?>
-<html lang="en">
- <head>
- <meta charset="utf-8">
- <title>HBase REST Server: <%= listenPort %></title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="">
+ Configuration conf = (Configuration) getServletContext().getAttribute("hbase.conf");
+ long startcode = conf.getLong("startcode", System.currentTimeMillis());
- <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>
+ final RESTServer restServer = (RESTServer) getServletContext().getAttribute(RESTServer.REST_SERVER);
+ final String hostName = restServer.getServerName().getHostname();
+ pageContext.setAttribute("pageTitle", "HBase REST Server" + hostName);
+%>
- <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="/rest.jsp"><img src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
- </div>
- <div class="collapse navbar-collapse">
- <ul class="nav navbar-nav">
- <li class="active"><a href="/rest.jsp">Home</a></li>
- <li><a href="/logs/">Local logs</a></li>
- <li><a href="/logLevel">Log Level</a></li>
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
- Metrics <span class="caret"></span>
- </a>
- <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
- <li><a target="_blank" href="/jmx">JMX</a></li>
- <li><a target="_blank" href="/jmx?description=true">JMX with description</a></li>
- <li><a target="_blank" href="/prometheus">Prometheus</a></li>
- <li><a target="_blank" href="/prometheus?description=true">Prometheus with description</a></li>
- </ul>
- </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>
+<jsp:include page="header.jsp">
+ <jsp:param name="pageTitle" value="${pageTitle}"/>
+</jsp:include>
<div class="container-fluid content">
<div class="row inner_header">
<div class="page-header">
- <h1>RESTServer <small><%= listenPort %></small></h1>
+ <h1>RESTServer <small><%= hostName %></small></h1>
</div>
</div>
<div class="row">
@@ -124,9 +83,6 @@ String listenPort = conf.get("hbase.rest.port", "8080");
</section>
</div>
</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>
+
+<jsp:include page="footer.jsp" />