From 2e1cf6a2385b6d39b243aee97764d9eae446eea6 Mon Sep 17 00:00:00 2001 From: Zhuoyue Huang <215175212@qq.com> Date: Mon, 16 Mar 2020 09:23:16 +0800 Subject: [PATCH 1/6] HBASE-23994:Add WebUI to Canary --- .../org/apache/hadoop/hbase/HConstants.java | 6 + .../hbase/tmpl/tool/CanaryStatusTmpl.jamon | 156 ++++++++++++++++++ .../hbase/tool/CanaryStatusServlet.java | 50 ++++++ .../apache/hadoop/hbase/tool/CanaryTool.java | 67 ++++++++ .../resources/hbase-webapps/canary/canary.jsp | 20 +++ .../resources/hbase-webapps/canary/index.html | 20 +++ .../hbase/tool/TestCanaryStatusServlet.java | 95 +++++++++++ 7 files changed, 414 insertions(+) create mode 100644 hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java create mode 100644 hbase-server/src/main/resources/hbase-webapps/canary/canary.jsp create mode 100644 hbase-server/src/main/resources/hbase-webapps/canary/index.html create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java index d518d217ba3b..4fdaecfb0a22 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java @@ -1464,6 +1464,12 @@ public enum OperationStatusCode { public static final String HBASE_CANARY_READ_RAW_SCAN_KEY = "hbase.canary.read.raw.enabled"; + 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"; + /** * Configuration keys for programmatic JAAS configuration for secured ZK interaction */ diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon new file mode 100644 index 000000000000..03a33f389e8b --- /dev/null +++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon @@ -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. + +<%args> +RegionStdOutSink sink; + +<%import> +java.util.Map; +java.util.concurrent.atomic.LongAdder; +org.apache.hadoop.hbase.ServerName; +org.apache.hadoop.hbase.tool.CanaryTool.RegionStdOutSink; + + + + + + + + Canary + + + + + + + + + + + +
+
+

Failed Servers

+ <%java> + Map perServerFailuresCount = sink.getPerServerFailuresCount(); + + + + + + + <%if (perServerFailuresCount != null && perServerFailuresCount.size() > 0)%> + <%for Map.Entry entry : perServerFailuresCount.entrySet() %> + + + + + + + +
ServerFailures Count
<& serverNameLink ; serverName = entry.getKey() &><% entry.getValue() %>
Total Failed Servers: <% (perServerFailuresCount != null) ? perServerFailuresCount.size() : 0 %>
+
+
+

Failed Tables

+ <%java> + Map perTableFailuresCount = sink.getPerTableFailuresCount(); + + + + + + + <%if (perTableFailuresCount != null && perTableFailuresCount.size() > 0)%> + <%for Map.Entry entry : perTableFailuresCount.entrySet()%> + + + + + + + +
TableFailures Count
<% entry.getKey() %><% entry.getValue() %>
Total Failed Tables: <% (perTableFailuresCount != null) ? perTableFailuresCount.size() : 0 %>
+
+ +
+

Software Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Attribute NameValueDescription
HBase Version<% org.apache.hadoop.hbase.util.VersionInfo.getVersion() %>, r<% org.apache.hadoop.hbase.util.VersionInfo.getRevision() %>HBase version and revision
HBase Compiled<% org.apache.hadoop.hbase.util.VersionInfo.getDate() %>, <% org.apache.hadoop.hbase.util.VersionInfo.getUser() %>When HBase version was compiled and by whom
Hadoop Version<% org.apache.hadoop.util.VersionInfo.getVersion() %>, r<% org.apache.hadoop.util.VersionInfo.getRevision() %>Hadoop version and revision
Hadoop Compiled<% org.apache.hadoop.util.VersionInfo.getDate() %>, <% org.apache.hadoop.util.VersionInfo.getUser() %>When Hadoop version was compiled and by whom
+
+
+ + + + + + + + +<%def serverNameLink> + <%args> + ServerName serverName; + + <%java> + int infoPort = serverName.getPort() + 1; + String url = "//" + serverName.getHostname() + ":" + infoPort + "/"; + + + <%if (infoPort > 0) %> + <% serverName.getServerName() %> + <%else> + <% serverName.getServerName() %> + + diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java new file mode 100644 index 000000000000..7a698834f99f --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java @@ -0,0 +1,50 @@ +/** + * + * 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 org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.tmpl.tool.CanaryStatusTmpl; +import org.apache.yetus.audience.InterfaceAudience; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.LongAdder; + +@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"); + assert sink != null : "No tool in context!"; + + resp.setContentType("text/html"); + + CanaryStatusTmpl tmpl = new CanaryStatusTmpl(); + tmpl.render(resp.getWriter(), sink); + } + +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java index ef68a082f871..c4d212c15cc8 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java @@ -19,11 +19,14 @@ package org.apache.hadoop.hbase.tool; +import static org.apache.hadoop.hbase.HConstants.DEFAULT_CANARY_INFOPORT; import static org.apache.hadoop.hbase.HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT; +import static org.apache.hadoop.hbase.HConstants.HBASE_CANARY_INFO_BINDADDRESS; import static org.apache.hadoop.hbase.HConstants.ZOOKEEPER_ZNODE_PARENT; import java.io.Closeable; import java.io.IOException; +import java.net.BindException; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Arrays; @@ -81,6 +84,7 @@ import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 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.util.Bytes; import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; @@ -123,6 +127,31 @@ @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) public class CanaryTool implements Tool, Canary { + + private void putUpWebUI() throws IOException { + if (zookeeperMode) { + LOG.info("WebUI is not supported in Zookeeper mode"); + } else if (regionServerMode) { + LOG.info("WebUI is not supported in RegionServer mode"); + } else { + Configuration conf = new Configuration(); + int port = conf.getInt(HConstants.HBASE_CANARY_INFO_PORT, DEFAULT_CANARY_INFOPORT); + // -1 is for disabling info server + if (port < 0) return; + String addr = conf.get(HBASE_CANARY_INFO_BINDADDRESS, "0.0.0.0"); + try { + InfoServer 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 port: " + port); + } catch (BindException e) { + e.printStackTrace(); + LOG.info("Failed binding Canary http info server to port: " + port); + } + } + } + @Override public int checkRegions(String[] targets) throws Exception { String configuredReadTableTimeoutsStr = conf.get(HBASE_CANARY_REGION_READ_TABLE_TIMEOUT); @@ -274,9 +303,42 @@ public static class RegionStdOutSink extends StdOutSink { private Map perTableReadLatency = new HashMap<>(); private LongAdder writeLatency = new LongAdder(); private final Map> regionMap = new ConcurrentHashMap<>(); + private Map perServerFailuresCount = new ConcurrentHashMap<>(); + private Map perTableFailuresCount = new ConcurrentHashMap<>(); + + public Map getPerServerFailuresCount() { + return perServerFailuresCount; + } + + public Map 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) { incReadFailureCount(); + incFailuresCountDetails(serverName, region); LOG.error("Read from {} on serverName={} failed", region.getRegionNameAsString(), serverName, e); } @@ -284,6 +346,7 @@ public void publishReadFailure(ServerName serverName, RegionInfo region, Excepti public void publishReadFailure(ServerName serverName, RegionInfo region, ColumnFamilyDescriptor column, Exception e) { incReadFailureCount(); + incFailuresCountDetails(serverName, region); LOG.error("Read from {} on serverName={}, columnFamily={} failed", region.getRegionNameAsString(), serverName, column.getNameAsString(), e); @@ -304,12 +367,14 @@ public void publishReadTiming(ServerName serverName, RegionInfo region, public void publishWriteFailure(ServerName serverName, RegionInfo region, Exception e) { incWriteFailureCount(); + incFailuresCountDetails(serverName, region); LOG.error("Write to {} on {} failed", region.getRegionNameAsString(), serverName, e); } public void publishWriteFailure(ServerName serverName, RegionInfo region, ColumnFamilyDescriptor column, Exception e) { incWriteFailureCount(); + incFailuresCountDetails(serverName, region); LOG.error("Write to {} on {} {} failed", region.getRegionNameAsString(), serverName, column.getNameAsString(), e); } @@ -908,6 +973,7 @@ public int run(String[] args) throws Exception { System.arraycopy(args, index, monitorTargets, 0, length); } + putUpWebUI(); if (zookeeperMode) { return checkZooKeeper(); } else if (regionServerMode) { @@ -1352,6 +1418,7 @@ public void run() { try { List> taskFutures = new LinkedList<>(); RegionStdOutSink regionSink = this.getSink(); + regionSink.resetFailuresCountDetails(); if (this.targets != null && this.targets.length > 0) { String[] tables = generateMonitorTables(this.targets); // Check to see that each table name passed in the -readTableTimeouts argument is also diff --git a/hbase-server/src/main/resources/hbase-webapps/canary/canary.jsp b/hbase-server/src/main/resources/hbase-webapps/canary/canary.jsp new file mode 100644 index 000000000000..2648ddd8dc50 --- /dev/null +++ b/hbase-server/src/main/resources/hbase-webapps/canary/canary.jsp @@ -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. + */ +--%> + diff --git a/hbase-server/src/main/resources/hbase-webapps/canary/index.html b/hbase-server/src/main/resources/hbase-webapps/canary/index.html new file mode 100644 index 000000000000..7e03fdd764a7 --- /dev/null +++ b/hbase-server/src/main/resources/hbase-webapps/canary/index.html @@ -0,0 +1,20 @@ + + diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java new file mode 100644 index 000000000000..ae5c0bbdca5b --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java @@ -0,0 +1,95 @@ +/** + * 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 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.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.io.IOException; +import java.io.StringWriter; + +@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(); + tmpl.render(new StringWriter(), regionStdOutSink); + } + + @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(); + tmpl.render(new StringWriter(), regionStdOutSink); + } + + @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(); + tmpl.render(new StringWriter(), regionStdOutSink); + } + + @Test + public void testNoFailures() throws IOException { + CanaryTool.RegionStdOutSink regionStdOutSink = new CanaryTool.RegionStdOutSink(); + CanaryStatusTmpl tmpl = new CanaryStatusTmpl(); + tmpl.render(new StringWriter(), regionStdOutSink); + } + +} From b1688474d17619c6b9146bb8025189cc148d7d89 Mon Sep 17 00:00:00 2001 From: Zhuoyue Huang <215175212@qq.com> Date: Tue, 31 Mar 2020 09:55:51 +0800 Subject: [PATCH 2/6] HBASE-23994:Add WebUI to Canary(Modify code) --- .../java/org/apache/hadoop/hbase/HConstants.java | 6 ------ .../org/apache/hadoop/hbase/tool/CanaryTool.java | 12 +++++++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java index 4fdaecfb0a22..d518d217ba3b 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java @@ -1464,12 +1464,6 @@ public enum OperationStatusCode { public static final String HBASE_CANARY_READ_RAW_SCAN_KEY = "hbase.canary.read.raw.enabled"; - 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"; - /** * Configuration keys for programmatic JAAS configuration for secured ZK interaction */ diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java index c4d212c15cc8..b0798ec51a31 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java @@ -19,9 +19,7 @@ package org.apache.hadoop.hbase.tool; -import static org.apache.hadoop.hbase.HConstants.DEFAULT_CANARY_INFOPORT; import static org.apache.hadoop.hbase.HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT; -import static org.apache.hadoop.hbase.HConstants.HBASE_CANARY_INFO_BINDADDRESS; import static org.apache.hadoop.hbase.HConstants.ZOOKEEPER_ZNODE_PARENT; import java.io.Closeable; @@ -126,6 +124,11 @@ */ @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 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 void putUpWebUI() throws IOException { @@ -135,7 +138,7 @@ private void putUpWebUI() throws IOException { LOG.info("WebUI is not supported in RegionServer mode"); } else { Configuration conf = new Configuration(); - int port = conf.getInt(HConstants.HBASE_CANARY_INFO_PORT, DEFAULT_CANARY_INFOPORT); + int port = conf.getInt(HBASE_CANARY_INFO_PORT, DEFAULT_CANARY_INFOPORT); // -1 is for disabling info server if (port < 0) return; String addr = conf.get(HBASE_CANARY_INFO_BINDADDRESS, "0.0.0.0"); @@ -146,8 +149,7 @@ private void putUpWebUI() throws IOException { infoServer.start(); LOG.info("Bind Canary http info server to port: " + port); } catch (BindException e) { - e.printStackTrace(); - LOG.info("Failed binding Canary http info server to port: " + port); + LOG.warn("Failed binding Canary http info server to port: " + port, e); } } } From 717fb3f54106cabd1d2ef7d5374aca1d10e65bec Mon Sep 17 00:00:00 2001 From: Zhuoyue Huang <215175212@qq.com> Date: Thu, 9 Apr 2020 21:10:30 +0800 Subject: [PATCH 3/6] HBASE-23994:Add WebUI to Canary(Map to ConcurrentMap) --- .../org/apache/hadoop/hbase/tool/CanaryTool.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java index b0798ec51a31..1352f75527a4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java @@ -40,6 +40,7 @@ import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -304,15 +305,15 @@ public void publishReadTiming(String znode, String server, long msTime) { public static class RegionStdOutSink extends StdOutSink { private Map perTableReadLatency = new HashMap<>(); private LongAdder writeLatency = new LongAdder(); - private final Map> regionMap = new ConcurrentHashMap<>(); - private Map perServerFailuresCount = new ConcurrentHashMap<>(); - private Map perTableFailuresCount = new ConcurrentHashMap<>(); + private final ConcurrentMap> regionMap = new ConcurrentHashMap<>(); + private ConcurrentMap perServerFailuresCount = new ConcurrentHashMap<>(); + private ConcurrentMap perTableFailuresCount = new ConcurrentHashMap<>(); - public Map getPerServerFailuresCount() { + public ConcurrentMap getPerServerFailuresCount() { return perServerFailuresCount; } - public Map getPerTableFailuresCount() { + public ConcurrentMap getPerTableFailuresCount() { return perTableFailuresCount; } @@ -412,7 +413,7 @@ public LongAdder getWriteLatency() { return this.writeLatency; } - public Map> getRegionMap() { + public ConcurrentMap> getRegionMap() { return this.regionMap; } From 22658fe28f22b4b2e66bd2ff84a52033ee0f8dde Mon Sep 17 00:00:00 2001 From: Zhuoyue Huang <215175212@qq.com> Date: Fri, 10 Apr 2020 11:15:49 +0800 Subject: [PATCH 4/6] HBASE-23994:Add WebUI to Canary(Checkstyle) --- .../hadoop/hbase/tool/CanaryStatusServlet.java | 13 +++++-------- .../org/apache/hadoop/hbase/tool/CanaryTool.java | 10 +++++++--- .../hadoop/hbase/tool/TestCanaryStatusServlet.java | 10 +++++----- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java index 7a698834f99f..510ee4b228b2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java @@ -18,18 +18,15 @@ */ package org.apache.hadoop.hbase.tool; -import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.tmpl.tool.CanaryStatusTmpl; -import org.apache.yetus.audience.InterfaceAudience; - +import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.LongAdder; +import org.apache.hadoop.hbase.tmpl.tool.CanaryStatusTmpl; +import org.apache.yetus.audience.InterfaceAudience; + + @InterfaceAudience.Private public class CanaryStatusServlet extends HttpServlet { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java index 1352f75527a4..db11e3ade0ae 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java @@ -141,7 +141,9 @@ private void putUpWebUI() throws IOException { Configuration conf = new Configuration(); int port = conf.getInt(HBASE_CANARY_INFO_PORT, DEFAULT_CANARY_INFOPORT); // -1 is for disabling info server - if (port < 0) return; + if (port < 0) { + return; + } String addr = conf.get(HBASE_CANARY_INFO_BINDADDRESS, "0.0.0.0"); try { InfoServer infoServer = new InfoServer("canary", addr, port, false, conf); @@ -305,8 +307,10 @@ public void publishReadTiming(String znode, String server, long msTime) { public static class RegionStdOutSink extends StdOutSink { private Map perTableReadLatency = new HashMap<>(); private LongAdder writeLatency = new LongAdder(); - private final ConcurrentMap> regionMap = new ConcurrentHashMap<>(); - private ConcurrentMap perServerFailuresCount = new ConcurrentHashMap<>(); + private final ConcurrentMap> regionMap = + new ConcurrentHashMap<>(); + private ConcurrentMap perServerFailuresCount = + new ConcurrentHashMap<>(); private ConcurrentMap perTableFailuresCount = new ConcurrentHashMap<>(); public ConcurrentMap getPerServerFailuresCount() { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java index ae5c0bbdca5b..92176861b7f0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java @@ -6,9 +6,9 @@ * 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 - * + *

+ * 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. @@ -17,6 +17,8 @@ */ 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; @@ -28,8 +30,6 @@ import org.junit.Test; import org.junit.experimental.categories.Category; -import java.io.IOException; -import java.io.StringWriter; @Category({ SmallTests.class }) public class TestCanaryStatusServlet { From 102c8e3385a603c12a14051c75b9a1c95b4bc73b Mon Sep 17 00:00:00 2001 From: Zhuoyue Huang <215175212@qq.com> Date: Fri, 10 Apr 2020 22:11:57 +0800 Subject: [PATCH 5/6] HBASE-23994:Add WebUI to Canary(Revise according to comments) --- .../hadoop/hbase/tool/CanaryStatusServlet.java | 7 +++++-- .../apache/hadoop/hbase/tool/CanaryTool.java | 18 +++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java index 510ee4b228b2..1ea6abbddd78 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java @@ -27,7 +27,6 @@ import org.apache.yetus.audience.InterfaceAudience; - @InterfaceAudience.Private public class CanaryStatusServlet extends HttpServlet { @Override @@ -36,7 +35,11 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) CanaryTool.RegionStdOutSink sink = (CanaryTool.RegionStdOutSink) getServletContext().getAttribute( "sink"); - assert sink != null : "No tool in context!"; + + if (sink == null) { + throw new ServletException( + "RegionStdOutSink is null! The CanaryTool's InfoServer is not initialized correctly"); + } resp.setContentType("text/html"); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java index db11e3ade0ae..ed59ab70d6ba 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryTool.java @@ -131,28 +131,28 @@ public class CanaryTool implements Tool, Canary { 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 { - Configuration conf = new Configuration(); - int port = conf.getInt(HBASE_CANARY_INFO_PORT, DEFAULT_CANARY_INFOPORT); - // -1 is for disabling info server - if (port < 0) { - return; - } String addr = conf.get(HBASE_CANARY_INFO_BINDADDRESS, "0.0.0.0"); try { - InfoServer infoServer = new InfoServer("canary", addr, port, false, conf); + 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 port: " + port); + LOG.info("Bind Canary http info server to {}:{} ", addr, port); } catch (BindException e) { - LOG.warn("Failed binding Canary http info server to port: " + port, e); + LOG.warn("Failed binding Canary http info server to {}:{}", addr, port, e); } } } From d5403ea1e80986e77ca5b643c99fc5820930f6bd Mon Sep 17 00:00:00 2001 From: Zhuoyue Huang <215175212@qq.com> Date: Mon, 13 Apr 2020 22:03:55 +0800 Subject: [PATCH 6/6] HBASE-23994:Add WebUI to Canary(Purge tabs and add assertions to TestCanaryStatusServlet) --- .../hbase/tmpl/tool/CanaryStatusTmpl.jamon | 50 +++++++++---------- .../hbase/tool/CanaryStatusServlet.java | 1 - .../hbase/tool/TestCanaryStatusServlet.java | 29 +++++++++-- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon index 03a33f389e8b..e2d29eef2803 100644 --- a/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon +++ b/hbase-server/src/main/jamon/org/apache/hadoop/hbase/tmpl/tool/CanaryStatusTmpl.jamon @@ -57,9 +57,9 @@ org.apache.hadoop.hbase.tool.CanaryTool.RegionStdOutSink; -

-
-

Failed Servers

+
+
+

Failed Servers

<%java> Map perServerFailuresCount = sink.getPerServerFailuresCount(); @@ -78,28 +78,28 @@ org.apache.hadoop.hbase.tool.CanaryTool.RegionStdOutSink; Total Failed Servers: <% (perServerFailuresCount != null) ? perServerFailuresCount.size() : 0 %> -
-
-

Failed Tables

- <%java> - Map perTableFailuresCount = sink.getPerTableFailuresCount(); - - - - - - - <%if (perTableFailuresCount != null && perTableFailuresCount.size() > 0)%> - <%for Map.Entry entry : perTableFailuresCount.entrySet()%> - - - - - - - -
TableFailures Count
<% entry.getKey() %><% entry.getValue() %>
Total Failed Tables: <% (perTableFailuresCount != null) ? perTableFailuresCount.size() : 0 %>
-
+
+
+

Failed Tables

+ <%java> + Map perTableFailuresCount = sink.getPerTableFailuresCount(); + + + + + + + <%if (perTableFailuresCount != null && perTableFailuresCount.size() > 0)%> + <%for Map.Entry entry : perTableFailuresCount.entrySet()%> + + + + + + + +
TableFailures Count
<% entry.getKey() %><% entry.getValue() %>
Total Failed Tables: <% (perTableFailuresCount != null) ? perTableFailuresCount.size() : 0 %>
+

Software Attributes

diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java index 1ea6abbddd78..ce214a7a2973 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/tool/CanaryStatusServlet.java @@ -35,7 +35,6 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) 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"); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java index 92176861b7f0..56c02a52fad0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/tool/TestCanaryStatusServlet.java @@ -26,6 +26,7 @@ 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; @@ -54,7 +55,14 @@ public void testFailures() throws IOException { regionStdOutSink.publishReadFailure(serverName1, regionInfo1, new IOException()); regionStdOutSink.publishWriteFailure(serverName2, regionInfo2, new IOException()); CanaryStatusTmpl tmpl = new CanaryStatusTmpl(); - tmpl.render(new StringWriter(), regionStdOutSink); + 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 @@ -68,7 +76,11 @@ public void testReadFailuresOnly() throws IOException { regionStdOutSink.publishReadFailure(serverName1, regionInfo1, new IOException()); CanaryStatusTmpl tmpl = new CanaryStatusTmpl(); - tmpl.render(new StringWriter(), regionStdOutSink); + 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 @@ -82,14 +94,23 @@ public void testWriteFailuresOnly() throws IOException { regionStdOutSink.publishReadFailure(serverName2, regionInfo2, new IOException()); CanaryStatusTmpl tmpl = new CanaryStatusTmpl(); - tmpl.render(new StringWriter(), regionStdOutSink); + 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(); - tmpl.render(new StringWriter(), regionStdOutSink); + 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")); } }