2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.assertTrue
;
23 import java
.lang
.reflect
.InvocationTargetException
;
24 import java
.lang
.reflect
.Method
;
25 import java
.util
.ArrayList
;
26 import java
.util
.Collection
;
27 import java
.util
.EnumSet
;
28 import java
.util
.List
;
30 import java
.util
.concurrent
.TimeUnit
;
31 import java
.util
.stream
.Collectors
;
32 import org
.apache
.hadoop
.hbase
.ClusterMetrics
.Option
;
33 import org
.apache
.hadoop
.hbase
.client
.Admin
;
34 import org
.apache
.hadoop
.hbase
.client
.RegionInfo
;
35 import org
.apache
.hadoop
.hbase
.client
.Table
;
36 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
37 import org
.apache
.hadoop
.hbase
.testclassification
.MiscTests
;
38 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
39 import org
.junit
.AfterClass
;
40 import org
.junit
.BeforeClass
;
41 import org
.junit
.ClassRule
;
42 import org
.junit
.Test
;
43 import org
.junit
.experimental
.categories
.Category
;
44 import org
.slf4j
.Logger
;
45 import org
.slf4j
.LoggerFactory
;
47 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.collect
.Maps
;
49 @Category({ MiscTests
.class, MediumTests
.class })
50 public class TestRegionMetrics
{
53 public static final HBaseClassTestRule CLASS_RULE
=
54 HBaseClassTestRule
.forClass(TestRegionMetrics
.class);
56 private static final Logger LOG
= LoggerFactory
.getLogger(TestRegionMetrics
.class);
57 private static final HBaseTestingUtility UTIL
= new HBaseTestingUtility();
58 private static Admin admin
;
60 private static final TableName TABLE_1
= TableName
.valueOf("table_1");
61 private static final TableName TABLE_2
= TableName
.valueOf("table_2");
62 private static final TableName TABLE_3
= TableName
.valueOf("table_3");
63 private static final TableName
[] tables
= new TableName
[] { TABLE_1
, TABLE_2
, TABLE_3
};
64 private static final int MSG_INTERVAL
= 500; // ms
67 public static void beforeClass() throws Exception
{
68 // Make servers report eagerly. This test is about looking at the cluster status reported.
69 // Make it so we don't have to wait around too long to see change.
70 UTIL
.getConfiguration().setInt("hbase.regionserver.msginterval", MSG_INTERVAL
);
71 UTIL
.startMiniCluster(4);
72 admin
= UTIL
.getAdmin();
73 admin
.balancerSwitch(false, true);
74 byte[] FAMILY
= Bytes
.toBytes("f");
75 for (TableName tableName
: tables
) {
76 Table table
= UTIL
.createMultiRegionTable(tableName
, FAMILY
, 16);
77 UTIL
.waitTableAvailable(tableName
);
78 UTIL
.loadTable(table
, FAMILY
);
83 public static void afterClass() throws Exception
{
84 for (TableName table
: tables
) {
85 UTIL
.deleteTableIfAny(table
);
87 UTIL
.shutdownMiniCluster();
92 public void testRegionMetrics() throws Exception
{
94 // Check if regions match with the RegionMetrics from the server
95 for (ServerName serverName
: admin
.getClusterMetrics(EnumSet
.of(Option
.LIVE_SERVERS
))
96 .getLiveServerMetrics().keySet()) {
97 List
<RegionInfo
> regions
= admin
.getRegions(serverName
);
98 Collection
<RegionMetrics
> regionMetricsList
=
99 admin
.getRegionMetrics(serverName
);
100 checkRegionsAndRegionMetrics(regions
, regionMetricsList
);
103 // Check if regionMetrics matches the table's regions and nothing is missed
104 for (TableName table
: new TableName
[] { TABLE_1
, TABLE_2
, TABLE_3
}) {
105 List
<RegionInfo
> tableRegions
= admin
.getRegions(table
);
107 List
<RegionMetrics
> regionMetrics
= new ArrayList
<>();
108 for (ServerName serverName
: admin
.getClusterMetrics(EnumSet
.of(Option
.LIVE_SERVERS
))
109 .getLiveServerMetrics().keySet()) {
110 regionMetrics
.addAll(admin
.getRegionMetrics(serverName
, table
));
112 checkRegionsAndRegionMetrics(tableRegions
, regionMetrics
);
115 // Just wait here. If this fixes the test, come back and do a better job.
116 // Would have to redo the below so can wait on cluster status changing.
117 // Admin#getClusterMetrics retrieves data from HMaster. Admin#getRegionMetrics, by contrast,
118 // get the data from RS. Hence, it will fail if we do the assert check before RS has done
120 TimeUnit
.MILLISECONDS
.sleep(3 * MSG_INTERVAL
);
122 // Check RegionMetrics matches the RegionMetrics from ClusterMetrics
123 for (Map
.Entry
<ServerName
, ServerMetrics
> entry
: admin
124 .getClusterMetrics(EnumSet
.of(Option
.LIVE_SERVERS
)).getLiveServerMetrics().entrySet()) {
125 ServerName serverName
= entry
.getKey();
126 ServerMetrics serverMetrics
= entry
.getValue();
127 List
<RegionMetrics
> regionMetrics
= admin
.getRegionMetrics(serverName
);
128 LOG
.debug("serverName=" + serverName
+ ", getRegionLoads=" +
129 serverMetrics
.getRegionMetrics().keySet().stream().map(r
-> Bytes
.toString(r
)).
130 collect(Collectors
.toList()));
131 LOG
.debug("serverName=" + serverName
+ ", regionLoads=" +
132 regionMetrics
.stream().map(r
-> Bytes
.toString(r
.getRegionName())).
133 collect(Collectors
.toList()));
134 assertEquals(serverMetrics
.getRegionMetrics().size(), regionMetrics
.size());
135 checkMetricsValue(regionMetrics
, serverMetrics
);
139 private void checkMetricsValue(List
<RegionMetrics
> regionMetrics
, ServerMetrics serverMetrics
)
140 throws InvocationTargetException
, IllegalAccessException
{
141 for (RegionMetrics fromRM
: regionMetrics
) {
142 RegionMetrics fromSM
= serverMetrics
.getRegionMetrics().get(fromRM
.getRegionName());
143 Class clazz
= RegionMetrics
.class;
144 for (Method method
: clazz
.getMethods()) {
145 // check numeric values only
146 if (method
.getReturnType().equals(Size
.class)
147 || method
.getReturnType().equals(int.class)
148 || method
.getReturnType().equals(long.class)
149 || method
.getReturnType().equals(float.class)) {
150 Object valueRm
= method
.invoke(fromRM
);
151 Object valueSM
= method
.invoke(fromSM
);
152 assertEquals("Return values of method " + method
.getName() + " are different",
153 valueRm
.toString(), valueSM
.toString());
159 private void checkRegionsAndRegionMetrics(Collection
<RegionInfo
> regions
,
160 Collection
<RegionMetrics
> regionMetrics
) {
162 assertEquals("No of regions and regionMetrics doesn't match", regions
.size(),
163 regionMetrics
.size());
165 Map
<byte[], RegionMetrics
> regionMetricsMap
= Maps
.newTreeMap(Bytes
.BYTES_COMPARATOR
);
166 for (RegionMetrics r
: regionMetrics
) {
167 regionMetricsMap
.put(r
.getRegionName(), r
);
169 for (RegionInfo info
: regions
) {
170 assertTrue("Region not in RegionMetricsMap region:"
171 + info
.getRegionNameAsString() + " regionMap: "
172 + regionMetricsMap
, regionMetricsMap
.containsKey(info
.getRegionName()));