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.regionserver; 019 020import static org.junit.Assert.assertEquals; 021import static org.mockito.Mockito.mock; 022import static org.mockito.Mockito.when; 023 024import java.util.ArrayList; 025import java.util.List; 026import java.util.OptionalDouble; 027import java.util.OptionalLong; 028import java.util.concurrent.atomic.AtomicInteger; 029import org.apache.hadoop.conf.Configuration; 030import org.apache.hadoop.hbase.HBaseClassTestRule; 031import org.apache.hadoop.hbase.HBaseConfiguration; 032import org.apache.hadoop.hbase.HConstants; 033import org.apache.hadoop.hbase.HDFSBlocksDistribution; 034import org.apache.hadoop.hbase.ServerName; 035import org.apache.hadoop.hbase.client.RegionInfo; 036import org.apache.hadoop.hbase.ipc.RpcServerInterface; 037import org.apache.hadoop.hbase.testclassification.RegionServerTests; 038import org.apache.hadoop.hbase.testclassification.SmallTests; 039import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 040import org.apache.hadoop.hbase.util.ManualEnvironmentEdge; 041import org.apache.hadoop.hbase.wal.WALFactory; 042import org.apache.hadoop.hbase.wal.WALProvider; 043import org.junit.ClassRule; 044import org.junit.Test; 045import org.junit.experimental.categories.Category; 046import org.mockito.Mockito; 047import org.mockito.stubbing.Answer; 048 049import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 050 051@Category({ SmallTests.class, RegionServerTests.class }) 052public class TestMetricsRegionServerAggregate { 053 054 @ClassRule 055 public static final HBaseClassTestRule CLASS_RULE = 056 HBaseClassTestRule.forClass(TestMetricsRegionServerAggregate.class); 057 058 @Test 059 public void test() { 060 AtomicInteger retVal = new AtomicInteger(0); 061 Answer defaultAnswer = invocation -> { 062 Class<?> returnType = invocation.getMethod().getReturnType(); 063 064 if (returnType.equals(Integer.TYPE) || returnType.equals(Integer.class)) { 065 return retVal.get(); 066 } else if (returnType.equals(Long.TYPE) || returnType.equals(Long.class)) { 067 return (long) retVal.get(); 068 } 069 return Mockito.RETURNS_DEFAULTS.answer(invocation); 070 }; 071 072 ServerName serverName = mock(ServerName.class); 073 when(serverName.getHostname()).thenReturn("foo"); 074 WALFactory walFactory = mock(WALFactory.class); 075 RpcServerInterface rpcServer = mock(RpcServerInterface.class); 076 AtomicInteger storeFileCount = new AtomicInteger(1); 077 HRegion regionOne = getMockedRegion(defaultAnswer, "a", "foo", true, storeFileCount); 078 HRegion regionTwo = getMockedRegion(defaultAnswer, "b", "bar", true, storeFileCount); 079 HRegion regionThree = getMockedRegion(defaultAnswer, "c", "foo", false, storeFileCount); 080 HRegion regionFour = getMockedRegion(defaultAnswer, "d", "bar", false, storeFileCount); 081 List<HRegion> regions = Lists.newArrayList(regionOne, regionTwo, regionThree, regionFour); 082 083 int numStoresPerRegion = 2; 084 for (HRegion region : regions) { 085 // if adding more stores, update numStoresPerRegion so that tests below continue working 086 assertEquals(numStoresPerRegion, region.getStores().size()); 087 } 088 089 HRegionServer regionServer = mock(HRegionServer.class, defaultAnswer); 090 when(regionServer.getWalFactory()).thenReturn(walFactory); 091 when(regionServer.getOnlineRegionsLocalContext()).thenReturn(regions); 092 when(regionServer.getServerName()).thenReturn(serverName); 093 Configuration conf = HBaseConfiguration.create(); 094 int metricsPeriodSec = 600; 095 // set a very long period so that it doesn't actually run during our very quick test 096 conf.setLong(HConstants.REGIONSERVER_METRICS_PERIOD, metricsPeriodSec * 1000); 097 when(regionServer.getConfiguration()).thenReturn(conf); 098 when(regionServer.getRpcServer()).thenReturn(rpcServer); 099 100 MetricsRegionServerWrapperImpl wrapper = new MetricsRegionServerWrapperImpl(regionServer); 101 102 // we need to control the edge because rate calculations expect a 103 // stable interval relative to the configured period 104 ManualEnvironmentEdge edge = new ManualEnvironmentEdge(); 105 EnvironmentEdgeManager.injectEdge(edge); 106 107 try { 108 for (int i = 1; i <= 10; i++) { 109 edge.incValue(wrapper.getPeriod()); 110 retVal.incrementAndGet(); 111 wrapper.forceRecompute(); 112 113 int numRegions = regions.size(); 114 int totalStores = numRegions * numStoresPerRegion; 115 116 // there are N regions, and each has M stores. everything gets aggregated, so 117 // multiply expected values accordingly 118 int expectedForRegions = retVal.get() * numRegions; 119 int expectedForStores = retVal.get() * totalStores; 120 121 assertEquals(totalStores, wrapper.getNumStores()); 122 assertEquals(expectedForStores, wrapper.getFlushedCellsCount()); 123 assertEquals(expectedForStores, wrapper.getCompactedCellsCount()); 124 assertEquals(expectedForStores, wrapper.getMajorCompactedCellsCount()); 125 assertEquals(expectedForStores, wrapper.getFlushedCellsSize()); 126 assertEquals(expectedForStores, wrapper.getCompactedCellsSize()); 127 assertEquals(expectedForStores, wrapper.getMajorCompactedCellsSize()); 128 assertEquals(expectedForRegions, wrapper.getCellsCountCompactedFromMob()); 129 assertEquals(expectedForRegions, wrapper.getCellsCountCompactedToMob()); 130 assertEquals(expectedForRegions, wrapper.getCellsSizeCompactedFromMob()); 131 assertEquals(expectedForRegions, wrapper.getCellsSizeCompactedToMob()); 132 assertEquals(expectedForRegions, wrapper.getMobFlushCount()); 133 assertEquals(expectedForRegions, wrapper.getMobFlushedCellsCount()); 134 assertEquals(expectedForRegions, wrapper.getMobFlushedCellsSize()); 135 assertEquals(expectedForRegions, wrapper.getMobScanCellsCount()); 136 assertEquals(expectedForRegions, wrapper.getMobScanCellsSize()); 137 assertEquals(expectedForRegions, wrapper.getCheckAndMutateChecksFailed()); 138 assertEquals(expectedForRegions, wrapper.getCheckAndMutateChecksPassed()); 139 assertEquals(expectedForStores, wrapper.getStoreFileIndexSize()); 140 assertEquals(expectedForStores, wrapper.getTotalStaticIndexSize()); 141 assertEquals(expectedForStores, wrapper.getTotalStaticBloomSize()); 142 assertEquals(expectedForStores, wrapper.getBloomFilterRequestsCount()); 143 assertEquals(expectedForStores, wrapper.getBloomFilterNegativeResultsCount()); 144 assertEquals(expectedForStores, wrapper.getBloomFilterEligibleRequestsCount()); 145 assertEquals(expectedForRegions, wrapper.getNumMutationsWithoutWAL()); 146 assertEquals(expectedForRegions, wrapper.getDataInMemoryWithoutWAL()); 147 assertEquals(expectedForRegions, wrapper.getAverageRegionSize()); 148 assertEquals(expectedForRegions, wrapper.getBlockedRequestsCount()); 149 assertEquals(expectedForStores, wrapper.getNumReferenceFiles()); 150 assertEquals(expectedForStores, wrapper.getMemStoreSize()); 151 assertEquals(expectedForStores, wrapper.getOnHeapMemStoreSize()); 152 assertEquals(expectedForStores, wrapper.getOffHeapMemStoreSize()); 153 assertEquals(expectedForStores, wrapper.getStoreFileSize()); 154 assertEquals(expectedForRegions, wrapper.getReadRequestsCount()); 155 assertEquals(expectedForRegions, wrapper.getCpRequestsCount()); 156 assertEquals(expectedForRegions, wrapper.getFilteredReadRequestsCount()); 157 assertEquals(expectedForRegions, wrapper.getWriteRequestsCount()); 158 assertEquals(expectedForRegions * 2, wrapper.getTotalRowActionRequestCount()); 159 160 // If we have N regions, each with M stores. That's N*M stores in total. In creating those 161 // stores, we increment the number and age of storefiles for each one. So the first 162 // store has 1 file of 1 age, then 2 files of 2 age, etc. 163 // formula for 1+2+3..+n 164 assertEquals((totalStores * (totalStores + 1)) / 2, wrapper.getNumStoreFiles()); 165 assertEquals(totalStores, wrapper.getMaxStoreFiles()); 166 assertEquals(totalStores, wrapper.getMaxStoreFileAge()); 167 assertEquals(1, wrapper.getMinStoreFileAge()); 168 assertEquals(totalStores / 2, wrapper.getAvgStoreFileAge()); 169 170 // there are four regions, two are primary and the other two secondary 171 // for each type, one region has 100% locality, the other has 0%. 172 // this just proves we correctly aggregate for each 173 assertEquals(50.0, wrapper.getPercentFileLocal(), 0.0001); 174 assertEquals(50.0, wrapper.getPercentFileLocalSecondaryRegions(), 0.0001); 175 176 // readRequestCount and writeRequestCount are tracking the value of i, which increases by 1 177 // each interval. There are N regions, so the delta each interval is N*i=N. So the rate is 178 // simply N / period. 179 assertEquals((double) numRegions / metricsPeriodSec, wrapper.getReadRequestsRatePerSecond(), 180 0.0001); 181 assertEquals((double) numRegions / metricsPeriodSec, 182 wrapper.getWriteRequestsRatePerSecond(), 0.0001); 183 // total of above, so multiply by 2 184 assertEquals((double) numRegions / metricsPeriodSec * 2, wrapper.getRequestsPerSecond(), 185 0.0001); 186 // Similar logic to above, except there are M totalStores and each one is of 187 // size tracking i. So the rate is just M / period. 188 assertEquals((double) totalStores / metricsPeriodSec, wrapper.getStoreFileSizeGrowthRate(), 189 0.0001); 190 } 191 } finally { 192 EnvironmentEdgeManager.reset(); 193 } 194 } 195 196 @Test 197 public void testWalMetricsForRegionServer() throws InterruptedException { 198 long numLogFiles = 10; 199 long logFileSize = 10240; 200 String hostname = "foo"; 201 Configuration conf = HBaseConfiguration.create(); 202 conf.setLong(HConstants.REGIONSERVER_METRICS_PERIOD, 1000); 203 204 HRegionServer regionServer = mock(HRegionServer.class); 205 when(regionServer.getConfiguration()).thenReturn(conf); 206 RpcServerInterface rpcServer = mock(RpcServerInterface.class); 207 when(regionServer.getRpcServer()).thenReturn(rpcServer); 208 WALFactory walFactory = mock(WALFactory.class); 209 WALProvider walProvider = mock(WALProvider.class); 210 when(walProvider.getNumLogFiles()).thenReturn(numLogFiles); 211 when(walProvider.getLogFileSize()).thenReturn(logFileSize); 212 List<WALProvider> providers = new ArrayList<>(); 213 providers.add(walProvider); 214 when(walFactory.getAllWALProviders()).thenReturn(providers); 215 when(regionServer.getWalFactory()).thenReturn(walFactory); 216 ServerName serverName = mock(ServerName.class); 217 when(serverName.getHostname()).thenReturn(hostname); 218 when(regionServer.getServerName()).thenReturn(serverName); 219 220 MetricsRegionServerWrapperImpl wrapper = new MetricsRegionServerWrapperImpl(regionServer); 221 MetricsRegionServerWrapperImpl.RegionServerMetricsWrapperRunnable runnable = 222 wrapper.new RegionServerMetricsWrapperRunnable(); 223 runnable.run(); 224 assertEquals(numLogFiles, wrapper.getNumWALFiles()); 225 assertEquals(logFileSize, wrapper.getWALFileSize()); 226 227 runnable.run(); 228 assertEquals(numLogFiles, wrapper.getNumWALFiles()); 229 assertEquals(logFileSize, wrapper.getWALFileSize()); 230 } 231 232 private HRegion getMockedRegion(Answer defaultAnswer, String name, String localOnHost, 233 boolean isPrimary, AtomicInteger storeFileCount) { 234 RegionInfo regionInfo = mock(RegionInfo.class); 235 when(regionInfo.getEncodedName()).thenReturn(name); 236 if (!isPrimary) { 237 when(regionInfo.getReplicaId()).thenReturn(RegionInfo.DEFAULT_REPLICA_ID + 1); 238 } 239 HDFSBlocksDistribution distribution = new HDFSBlocksDistribution(); 240 distribution.addHostsAndBlockWeight(new String[] { localOnHost }, 100); 241 242 HStore store = getMockedStore(HStore.class, defaultAnswer, storeFileCount); 243 HMobStore mobStore = getMockedStore(HMobStore.class, defaultAnswer, storeFileCount); 244 245 HRegion region = mock(HRegion.class, defaultAnswer); 246 when(region.getRegionInfo()).thenReturn(regionInfo); 247 when(region.getHDFSBlocksDistribution()).thenReturn(distribution); 248 when(region.getStores()).thenReturn(Lists.newArrayList(store, mobStore)); 249 return region; 250 } 251 252 private <T extends HStore> T getMockedStore(Class<T> clazz, Answer defaultAnswer, 253 AtomicInteger storeFileCount) { 254 T store = mock(clazz, defaultAnswer); 255 int storeFileCountVal = storeFileCount.getAndIncrement(); 256 when(store.getStorefilesCount()).thenReturn(storeFileCountVal); 257 when(store.getAvgStoreFileAge()).thenReturn(OptionalDouble.of(storeFileCountVal)); 258 when(store.getMaxStoreFileAge()).thenReturn(OptionalLong.of(storeFileCountVal)); 259 when(store.getMinStoreFileAge()).thenReturn(OptionalLong.of(storeFileCountVal)); 260 MemStoreSize memStore = mock(MemStoreSize.class, defaultAnswer); 261 when(store.getMemStoreSize()).thenReturn(memStore); 262 return store; 263 } 264 265}