001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertTrue; 022 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.EnumSet; 026import java.util.List; 027import java.util.Map; 028import java.util.concurrent.TimeUnit; 029import java.util.stream.Collectors; 030import org.apache.hadoop.hbase.ClusterMetrics.Option; 031import org.apache.hadoop.hbase.client.Admin; 032import org.apache.hadoop.hbase.client.RegionInfo; 033import org.apache.hadoop.hbase.client.Table; 034import org.apache.hadoop.hbase.testclassification.MediumTests; 035import org.apache.hadoop.hbase.testclassification.MiscTests; 036import org.apache.hadoop.hbase.util.Bytes; 037import org.junit.AfterClass; 038import org.junit.BeforeClass; 039import org.junit.ClassRule; 040import org.junit.Test; 041import org.junit.experimental.categories.Category; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045import org.apache.hbase.thirdparty.com.google.common.collect.Maps; 046 047@Category({ MiscTests.class, MediumTests.class }) 048public class TestRegionMetrics { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestRegionMetrics.class); 053 054 private static final Logger LOG = LoggerFactory.getLogger(TestRegionMetrics.class); 055 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); 056 private static Admin admin; 057 058 private static final TableName TABLE_1 = TableName.valueOf("table_1"); 059 private static final TableName TABLE_2 = TableName.valueOf("table_2"); 060 private static final TableName TABLE_3 = TableName.valueOf("table_3"); 061 private static final TableName[] tables = new TableName[] { TABLE_1, TABLE_2, TABLE_3 }; 062 private static final int MSG_INTERVAL = 500; // ms 063 064 @BeforeClass 065 public static void beforeClass() throws Exception { 066 // Make servers report eagerly. This test is about looking at the cluster status reported. 067 // Make it so we don't have to wait around too long to see change. 068 UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", MSG_INTERVAL); 069 UTIL.startMiniCluster(4); 070 admin = UTIL.getAdmin(); 071 admin.balancerSwitch(false, true); 072 byte[] FAMILY = Bytes.toBytes("f"); 073 for (TableName tableName : tables) { 074 Table table = UTIL.createMultiRegionTable(tableName, FAMILY, 16); 075 UTIL.waitTableAvailable(tableName); 076 UTIL.loadTable(table, FAMILY); 077 } 078 } 079 080 @AfterClass 081 public static void afterClass() throws Exception { 082 for (TableName table : tables) { 083 UTIL.deleteTableIfAny(table); 084 } 085 UTIL.shutdownMiniCluster(); 086 } 087 088 089 @Test 090 public void testRegionMetrics() throws Exception { 091 092 // Check if regions match with the RegionMetrics from the server 093 for (ServerName serverName : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 094 .getLiveServerMetrics().keySet()) { 095 List<RegionInfo> regions = admin.getRegions(serverName); 096 Collection<RegionMetrics> regionMetricsList = 097 admin.getRegionMetrics(serverName); 098 checkRegionsAndRegionMetrics(regions, regionMetricsList); 099 } 100 101 // Check if regionMetrics matches the table's regions and nothing is missed 102 for (TableName table : new TableName[] { TABLE_1, TABLE_2, TABLE_3 }) { 103 List<RegionInfo> tableRegions = admin.getRegions(table); 104 105 List<RegionMetrics> regionMetrics = new ArrayList<>(); 106 for (ServerName serverName : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 107 .getLiveServerMetrics().keySet()) { 108 regionMetrics.addAll(admin.getRegionMetrics(serverName, table)); 109 } 110 checkRegionsAndRegionMetrics(tableRegions, regionMetrics); 111 } 112 113 // Just wait here. If this fixes the test, come back and do a better job. 114 // Would have to redo the below so can wait on cluster status changing. 115 // Admin#getClusterMetrics retrieves data from HMaster. Admin#getRegionMetrics, by contrast, 116 // get the data from RS. Hence, it will fail if we do the assert check before RS has done 117 // the report. 118 TimeUnit.MILLISECONDS.sleep(3 * MSG_INTERVAL); 119 120 // Check RegionMetrics matches the RegionMetrics from ClusterMetrics 121 for (Map.Entry<ServerName, ServerMetrics> entry : admin 122 .getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics().entrySet()) { 123 ServerName serverName = entry.getKey(); 124 ServerMetrics serverMetrics = entry.getValue(); 125 List<RegionMetrics> regionMetrics = admin.getRegionMetrics(serverName); 126 LOG.debug("serverName=" + serverName + ", getRegionLoads=" + 127 serverMetrics.getRegionMetrics().keySet().stream().map(r -> Bytes.toString(r)). 128 collect(Collectors.toList())); 129 LOG.debug("serverName=" + serverName + ", regionLoads=" + 130 regionMetrics.stream().map(r -> Bytes.toString(r.getRegionName())). 131 collect(Collectors.toList())); 132 assertEquals(serverMetrics.getRegionMetrics().size(), regionMetrics.size()); 133 } 134 } 135 136 private void checkRegionsAndRegionMetrics(Collection<RegionInfo> regions, 137 Collection<RegionMetrics> regionMetrics) { 138 139 assertEquals("No of regions and regionMetrics doesn't match", regions.size(), 140 regionMetrics.size()); 141 142 Map<byte[], RegionMetrics> regionMetricsMap = Maps.newTreeMap(Bytes.BYTES_COMPARATOR); 143 for (RegionMetrics r : regionMetrics) { 144 regionMetricsMap.put(r.getRegionName(), r); 145 } 146 for (RegionInfo info : regions) { 147 assertTrue("Region not in RegionMetricsMap region:" 148 + info.getRegionNameAsString() + " regionMap: " 149 + regionMetricsMap, regionMetricsMap.containsKey(info.getRegionName())); 150 } 151 } 152}