HBASE-23994: Add WebUI to Canary (#1292)
Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Nick Dimiduk <ndimiduk@apache.org>
This commit is contained in:
parent
cb60d23cb3
commit
38954edb25
|
@ -0,0 +1,156 @@
|
||||||
|
|
||||||
|
<%doc>
|
||||||
|
|
||||||
|
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.
|
||||||
|
</%doc>
|
||||||
|
<%args>
|
||||||
|
RegionStdOutSink sink;
|
||||||
|
</%args>
|
||||||
|
<%import>
|
||||||
|
java.util.Map;
|
||||||
|
java.util.concurrent.atomic.LongAdder;
|
||||||
|
org.apache.hadoop.hbase.ServerName;
|
||||||
|
org.apache.hadoop.hbase.tool.CanaryTool.RegionStdOutSink;
|
||||||
|
</%import>
|
||||||
|
|
||||||
|
<!--[if IE]>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<![endif]-->
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Canary</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">
|
||||||
|
<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="/canary-status"><img src="/static/hbase_logo_small.png" alt="HBase Logo"/></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<section>
|
||||||
|
<h2>Failed Servers</h2>
|
||||||
|
<%java>
|
||||||
|
Map<ServerName, LongAdder> perServerFailuresCount = sink.getPerServerFailuresCount();
|
||||||
|
</%java>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Server</th>
|
||||||
|
<th>Failures Count</th>
|
||||||
|
</tr>
|
||||||
|
<%if (perServerFailuresCount != null && perServerFailuresCount.size() > 0)%>
|
||||||
|
<%for Map.Entry<ServerName, LongAdder> entry : perServerFailuresCount.entrySet() %>
|
||||||
|
<tr>
|
||||||
|
<td><& serverNameLink ; serverName = entry.getKey() &></td>
|
||||||
|
<td><% entry.getValue() %></td>
|
||||||
|
</tr>
|
||||||
|
</%for>
|
||||||
|
</%if>
|
||||||
|
<tr><td>Total Failed Servers: <% (perServerFailuresCount != null) ? perServerFailuresCount.size() : 0 %></td></tr>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Failed Tables</h2>
|
||||||
|
<%java>
|
||||||
|
Map<String, LongAdder> perTableFailuresCount = sink.getPerTableFailuresCount();
|
||||||
|
</%java>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Table</th>
|
||||||
|
<th>Failures Count</th>
|
||||||
|
</tr>
|
||||||
|
<%if (perTableFailuresCount != null && perTableFailuresCount.size() > 0)%>
|
||||||
|
<%for Map.Entry<String, LongAdder> entry : perTableFailuresCount.entrySet()%>
|
||||||
|
<tr>
|
||||||
|
<td><% entry.getKey() %></td>
|
||||||
|
<td><% entry.getValue() %></td>
|
||||||
|
</tr>
|
||||||
|
</%for>
|
||||||
|
</%if>
|
||||||
|
<tr><td>Total Failed Tables: <% (perTableFailuresCount != null) ? perTableFailuresCount.size() : 0 %></td></tr>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Software Attributes</h2>
|
||||||
|
<table id="attributes_table" class="table table-striped">
|
||||||
|
<tr>
|
||||||
|
<th>Attribute Name</th>
|
||||||
|
<th>Value</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>HBase Version</td>
|
||||||
|
<td><% org.apache.hadoop.hbase.util.VersionInfo.getVersion() %>, r<% org.apache.hadoop.hbase.util.VersionInfo.getRevision() %></td><td>HBase version and revision</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>HBase Compiled</td>
|
||||||
|
<td><% org.apache.hadoop.hbase.util.VersionInfo.getDate() %>, <% org.apache.hadoop.hbase.util.VersionInfo.getUser() %></td>
|
||||||
|
<td>When HBase version was compiled and by whom</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Hadoop Version</td>
|
||||||
|
<td><% org.apache.hadoop.util.VersionInfo.getVersion() %>, r<% org.apache.hadoop.util.VersionInfo.getRevision() %></td>
|
||||||
|
<td>Hadoop version and revision</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Hadoop Compiled</td>
|
||||||
|
<td><% org.apache.hadoop.util.VersionInfo.getDate() %>, <% org.apache.hadoop.util.VersionInfo.getUser() %></td>
|
||||||
|
<td>When Hadoop version was compiled and by whom</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div> <!-- /container -->
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<%def serverNameLink>
|
||||||
|
<%args>
|
||||||
|
ServerName serverName;
|
||||||
|
</%args>
|
||||||
|
<%java>
|
||||||
|
int infoPort = serverName.getPort() + 1;
|
||||||
|
String url = "//" + serverName.getHostname() + ":" + infoPort + "/";
|
||||||
|
</%java>
|
||||||
|
|
||||||
|
<%if (infoPort > 0) %>
|
||||||
|
<a href="<% url %>"><% serverName.getServerName() %></a>
|
||||||
|
<%else>
|
||||||
|
<% serverName.getServerName() %>
|
||||||
|
</%if>
|
||||||
|
</%def>
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.tool;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.hadoop.hbase.tmpl.tool.CanaryStatusTmpl;
|
||||||
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
|
||||||
|
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
public class CanaryStatusServlet extends HttpServlet {
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
CanaryTool.RegionStdOutSink sink =
|
||||||
|
(CanaryTool.RegionStdOutSink) getServletContext().getAttribute(
|
||||||
|
"sink");
|
||||||
|
if (sink == null) {
|
||||||
|
throw new ServletException(
|
||||||
|
"RegionStdOutSink is null! The CanaryTool's InfoServer is not initialized correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.setContentType("text/html");
|
||||||
|
|
||||||
|
CanaryStatusTmpl tmpl = new CanaryStatusTmpl();
|
||||||
|
tmpl.render(resp.getWriter(), sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import static org.apache.hadoop.hbase.HConstants.ZOOKEEPER_ZNODE_PARENT;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.BindException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -39,6 +40,7 @@ import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -81,6 +83,7 @@ import org.apache.hadoop.hbase.client.Table;
|
||||||
import org.apache.hadoop.hbase.client.TableDescriptor;
|
import org.apache.hadoop.hbase.client.TableDescriptor;
|
||||||
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
|
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
|
||||||
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
|
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
|
||||||
|
import org.apache.hadoop.hbase.http.InfoServer;
|
||||||
import org.apache.hadoop.hbase.tool.CanaryTool.RegionTask.TaskType;
|
import org.apache.hadoop.hbase.tool.CanaryTool.RegionTask.TaskType;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
||||||
|
@ -122,6 +125,37 @@ import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
|
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
|
||||||
public class CanaryTool implements Tool, Canary {
|
public class CanaryTool implements Tool, Canary {
|
||||||
|
public static final String HBASE_CANARY_INFO_PORT = "hbase.canary.info.port";
|
||||||
|
|
||||||
|
public static final int DEFAULT_CANARY_INFOPORT = 16050;
|
||||||
|
|
||||||
|
public static final String HBASE_CANARY_INFO_BINDADDRESS = "hbase.canary.info.bindAddress";
|
||||||
|
|
||||||
|
private InfoServer infoServer;
|
||||||
|
|
||||||
|
private void putUpWebUI() throws IOException {
|
||||||
|
int port = conf.getInt(HBASE_CANARY_INFO_PORT, DEFAULT_CANARY_INFOPORT);
|
||||||
|
// -1 is for disabling info server
|
||||||
|
if (port < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (zookeeperMode) {
|
||||||
|
LOG.info("WebUI is not supported in Zookeeper mode");
|
||||||
|
} else if (regionServerMode) {
|
||||||
|
LOG.info("WebUI is not supported in RegionServer mode");
|
||||||
|
} else {
|
||||||
|
String addr = conf.get(HBASE_CANARY_INFO_BINDADDRESS, "0.0.0.0");
|
||||||
|
try {
|
||||||
|
infoServer = new InfoServer("canary", addr, port, false, conf);
|
||||||
|
infoServer.addUnprivilegedServlet("canary", "/canary-status", CanaryStatusServlet.class);
|
||||||
|
infoServer.setAttribute("sink", this.sink);
|
||||||
|
infoServer.start();
|
||||||
|
LOG.info("Bind Canary http info server to {}:{} ", addr, port);
|
||||||
|
} catch (BindException e) {
|
||||||
|
LOG.warn("Failed binding Canary http info server to {}:{}", addr, port, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int checkRegions(String[] targets) throws Exception {
|
public int checkRegions(String[] targets) throws Exception {
|
||||||
|
@ -273,10 +307,45 @@ public class CanaryTool implements Tool, Canary {
|
||||||
public static class RegionStdOutSink extends StdOutSink {
|
public static class RegionStdOutSink extends StdOutSink {
|
||||||
private Map<String, LongAdder> perTableReadLatency = new HashMap<>();
|
private Map<String, LongAdder> perTableReadLatency = new HashMap<>();
|
||||||
private LongAdder writeLatency = new LongAdder();
|
private LongAdder writeLatency = new LongAdder();
|
||||||
private final Map<String, List<RegionTaskResult>> regionMap = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, List<RegionTaskResult>> regionMap =
|
||||||
|
new ConcurrentHashMap<>();
|
||||||
|
private ConcurrentMap<ServerName, LongAdder> perServerFailuresCount =
|
||||||
|
new ConcurrentHashMap<>();
|
||||||
|
private ConcurrentMap<String, LongAdder> perTableFailuresCount = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public ConcurrentMap<ServerName, LongAdder> getPerServerFailuresCount() {
|
||||||
|
return perServerFailuresCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentMap<String, LongAdder> getPerTableFailuresCount() {
|
||||||
|
return perTableFailuresCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetFailuresCountDetails() {
|
||||||
|
perServerFailuresCount.clear();
|
||||||
|
perTableFailuresCount.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void incFailuresCountDetails(ServerName serverName, RegionInfo region) {
|
||||||
|
perServerFailuresCount.compute(serverName, (server, count) -> {
|
||||||
|
if (count == null) {
|
||||||
|
count = new LongAdder();
|
||||||
|
}
|
||||||
|
count.increment();
|
||||||
|
return count;
|
||||||
|
});
|
||||||
|
perTableFailuresCount.compute(region.getTable().getNameAsString(), (tableName, count) -> {
|
||||||
|
if (count == null) {
|
||||||
|
count = new LongAdder();
|
||||||
|
}
|
||||||
|
count.increment();
|
||||||
|
return count;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void publishReadFailure(ServerName serverName, RegionInfo region, Exception e) {
|
public void publishReadFailure(ServerName serverName, RegionInfo region, Exception e) {
|
||||||
incReadFailureCount();
|
incReadFailureCount();
|
||||||
|
incFailuresCountDetails(serverName, region);
|
||||||
LOG.error("Read from {} on serverName={} failed",
|
LOG.error("Read from {} on serverName={} failed",
|
||||||
region.getRegionNameAsString(), serverName, e);
|
region.getRegionNameAsString(), serverName, e);
|
||||||
}
|
}
|
||||||
|
@ -284,6 +353,7 @@ public class CanaryTool implements Tool, Canary {
|
||||||
public void publishReadFailure(ServerName serverName, RegionInfo region,
|
public void publishReadFailure(ServerName serverName, RegionInfo region,
|
||||||
ColumnFamilyDescriptor column, Exception e) {
|
ColumnFamilyDescriptor column, Exception e) {
|
||||||
incReadFailureCount();
|
incReadFailureCount();
|
||||||
|
incFailuresCountDetails(serverName, region);
|
||||||
LOG.error("Read from {} on serverName={}, columnFamily={} failed",
|
LOG.error("Read from {} on serverName={}, columnFamily={} failed",
|
||||||
region.getRegionNameAsString(), serverName,
|
region.getRegionNameAsString(), serverName,
|
||||||
column.getNameAsString(), e);
|
column.getNameAsString(), e);
|
||||||
|
@ -304,12 +374,14 @@ public class CanaryTool implements Tool, Canary {
|
||||||
|
|
||||||
public void publishWriteFailure(ServerName serverName, RegionInfo region, Exception e) {
|
public void publishWriteFailure(ServerName serverName, RegionInfo region, Exception e) {
|
||||||
incWriteFailureCount();
|
incWriteFailureCount();
|
||||||
|
incFailuresCountDetails(serverName, region);
|
||||||
LOG.error("Write to {} on {} failed", region.getRegionNameAsString(), serverName, e);
|
LOG.error("Write to {} on {} failed", region.getRegionNameAsString(), serverName, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void publishWriteFailure(ServerName serverName, RegionInfo region,
|
public void publishWriteFailure(ServerName serverName, RegionInfo region,
|
||||||
ColumnFamilyDescriptor column, Exception e) {
|
ColumnFamilyDescriptor column, Exception e) {
|
||||||
incWriteFailureCount();
|
incWriteFailureCount();
|
||||||
|
incFailuresCountDetails(serverName, region);
|
||||||
LOG.error("Write to {} on {} {} failed", region.getRegionNameAsString(), serverName,
|
LOG.error("Write to {} on {} {} failed", region.getRegionNameAsString(), serverName,
|
||||||
column.getNameAsString(), e);
|
column.getNameAsString(), e);
|
||||||
}
|
}
|
||||||
|
@ -345,7 +417,7 @@ public class CanaryTool implements Tool, Canary {
|
||||||
return this.writeLatency;
|
return this.writeLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, List<RegionTaskResult>> getRegionMap() {
|
public ConcurrentMap<String, List<RegionTaskResult>> getRegionMap() {
|
||||||
return this.regionMap;
|
return this.regionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,6 +980,7 @@ public class CanaryTool implements Tool, Canary {
|
||||||
System.arraycopy(args, index, monitorTargets, 0, length);
|
System.arraycopy(args, index, monitorTargets, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
putUpWebUI();
|
||||||
if (zookeeperMode) {
|
if (zookeeperMode) {
|
||||||
return checkZooKeeper();
|
return checkZooKeeper();
|
||||||
} else if (regionServerMode) {
|
} else if (regionServerMode) {
|
||||||
|
@ -1352,6 +1425,7 @@ public class CanaryTool implements Tool, Canary {
|
||||||
try {
|
try {
|
||||||
List<Future<Void>> taskFutures = new LinkedList<>();
|
List<Future<Void>> taskFutures = new LinkedList<>();
|
||||||
RegionStdOutSink regionSink = this.getSink();
|
RegionStdOutSink regionSink = this.getSink();
|
||||||
|
regionSink.resetFailuresCountDetails();
|
||||||
if (this.targets != null && this.targets.length > 0) {
|
if (this.targets != null && this.targets.length > 0) {
|
||||||
String[] tables = generateMonitorTables(this.targets);
|
String[] tables = generateMonitorTables(this.targets);
|
||||||
// Check to see that each table name passed in the -readTableTimeouts argument is also
|
// Check to see that each table name passed in the -readTableTimeouts argument is also
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<%--
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
--%>
|
||||||
|
<meta HTTP-EQUIV="REFRESH" content="0;url=/canary-status"/>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<meta HTTP-EQUIV="REFRESH" content="0;url=/canary-status"/>
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* 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.tool;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
|
import org.apache.hadoop.hbase.ServerName;
|
||||||
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
import org.apache.hadoop.hbase.client.RegionInfo;
|
||||||
|
import org.apache.hadoop.hbase.client.RegionInfoBuilder;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
||||||
|
import org.apache.hadoop.hbase.tmpl.tool.CanaryStatusTmpl;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
|
||||||
|
|
||||||
|
@Category({ SmallTests.class })
|
||||||
|
public class TestCanaryStatusServlet {
|
||||||
|
@ClassRule
|
||||||
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
|
HBaseClassTestRule.forClass(TestCanaryStatusServlet.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailures() throws IOException {
|
||||||
|
CanaryTool.RegionStdOutSink regionStdOutSink = new CanaryTool.RegionStdOutSink();
|
||||||
|
|
||||||
|
ServerName serverName1 = ServerName.valueOf("staging-st04.server:22600",
|
||||||
|
1584180761635L);
|
||||||
|
TableName fakeTableName1 = TableName.valueOf("fakeTableName1");
|
||||||
|
RegionInfo regionInfo1 = RegionInfoBuilder.newBuilder(fakeTableName1).build();
|
||||||
|
|
||||||
|
ServerName serverName2 = ServerName.valueOf("staging-st05.server:22600",
|
||||||
|
1584180761636L);
|
||||||
|
TableName fakeTableName2 = TableName.valueOf("fakeTableName2");
|
||||||
|
RegionInfo regionInfo2 = RegionInfoBuilder.newBuilder(fakeTableName2).build();
|
||||||
|
|
||||||
|
regionStdOutSink.publishReadFailure(serverName1, regionInfo1, new IOException());
|
||||||
|
regionStdOutSink.publishWriteFailure(serverName2, regionInfo2, new IOException());
|
||||||
|
CanaryStatusTmpl tmpl = new CanaryStatusTmpl();
|
||||||
|
StringWriter renderResultWriter = new StringWriter();
|
||||||
|
tmpl.render(renderResultWriter, regionStdOutSink);
|
||||||
|
String renderResult = renderResultWriter.toString();
|
||||||
|
Assert.assertTrue(renderResult.contains("staging-st04.server,22600"));
|
||||||
|
Assert.assertTrue(renderResult.contains("fakeTableName1"));
|
||||||
|
Assert.assertTrue(renderResult.contains("staging-st05.server,22600"));
|
||||||
|
Assert.assertTrue(renderResult.contains("fakeTableName2"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadFailuresOnly() throws IOException {
|
||||||
|
CanaryTool.RegionStdOutSink regionStdOutSink = new CanaryTool.RegionStdOutSink();
|
||||||
|
|
||||||
|
ServerName serverName1 = ServerName.valueOf("staging-st04.server:22600",
|
||||||
|
1584180761635L);
|
||||||
|
TableName fakeTableName1 = TableName.valueOf("fakeTableName1");
|
||||||
|
RegionInfo regionInfo1 = RegionInfoBuilder.newBuilder(fakeTableName1).build();
|
||||||
|
|
||||||
|
regionStdOutSink.publishReadFailure(serverName1, regionInfo1, new IOException());
|
||||||
|
CanaryStatusTmpl tmpl = new CanaryStatusTmpl();
|
||||||
|
StringWriter renderResultWriter = new StringWriter();
|
||||||
|
tmpl.render(renderResultWriter, regionStdOutSink);
|
||||||
|
String renderResult = renderResultWriter.toString();
|
||||||
|
Assert.assertTrue(renderResult.contains("staging-st04.server,22600"));
|
||||||
|
Assert.assertTrue(renderResult.contains("fakeTableName1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteFailuresOnly() throws IOException {
|
||||||
|
CanaryTool.RegionStdOutSink regionStdOutSink = new CanaryTool.RegionStdOutSink();
|
||||||
|
|
||||||
|
ServerName serverName2 = ServerName.valueOf("staging-st05.server:22600",
|
||||||
|
1584180761636L);
|
||||||
|
TableName fakeTableName2 = TableName.valueOf("fakeTableName2");
|
||||||
|
RegionInfo regionInfo2 = RegionInfoBuilder.newBuilder(fakeTableName2).build();
|
||||||
|
|
||||||
|
regionStdOutSink.publishReadFailure(serverName2, regionInfo2, new IOException());
|
||||||
|
CanaryStatusTmpl tmpl = new CanaryStatusTmpl();
|
||||||
|
StringWriter renderResultWriter = new StringWriter();
|
||||||
|
tmpl.render(renderResultWriter, regionStdOutSink);
|
||||||
|
String renderResult = renderResultWriter.toString();
|
||||||
|
Assert.assertTrue(renderResult.contains("staging-st05.server,22600"));
|
||||||
|
Assert.assertTrue(renderResult.contains("fakeTableName2"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoFailures() throws IOException {
|
||||||
|
CanaryTool.RegionStdOutSink regionStdOutSink = new CanaryTool.RegionStdOutSink();
|
||||||
|
CanaryStatusTmpl tmpl = new CanaryStatusTmpl();
|
||||||
|
StringWriter renderResultWriter = new StringWriter();
|
||||||
|
tmpl.render(renderResultWriter, regionStdOutSink);
|
||||||
|
String renderResult = renderResultWriter.toString();
|
||||||
|
Assert.assertTrue(renderResult.contains("Total Failed Servers: 0"));
|
||||||
|
Assert.assertTrue(renderResult.contains("Total Failed Tables: 0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue