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.junit.Assert.assertNotEquals; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertNull; 024import static org.junit.Assert.assertTrue; 025 026import java.io.IOException; 027import java.util.ArrayList; 028import java.util.List; 029import java.util.Optional; 030import org.apache.hadoop.conf.Configuration; 031import org.apache.hadoop.hbase.CompatibilityFactory; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HBaseTestingUtil; 034import org.apache.hadoop.hbase.HConstants; 035import org.apache.hadoop.hbase.HRegionLocation; 036import org.apache.hadoop.hbase.NamespaceDescriptor; 037import org.apache.hadoop.hbase.SingleProcessHBaseCluster; 038import org.apache.hadoop.hbase.TableName; 039import org.apache.hadoop.hbase.client.Admin; 040import org.apache.hadoop.hbase.client.Append; 041import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 042import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 043import org.apache.hadoop.hbase.client.Connection; 044import org.apache.hadoop.hbase.client.Durability; 045import org.apache.hadoop.hbase.client.Get; 046import org.apache.hadoop.hbase.client.Increment; 047import org.apache.hadoop.hbase.client.Put; 048import org.apache.hadoop.hbase.client.RegionInfo; 049import org.apache.hadoop.hbase.client.RegionLocator; 050import org.apache.hadoop.hbase.client.Result; 051import org.apache.hadoop.hbase.client.ResultScanner; 052import org.apache.hadoop.hbase.client.Scan; 053import org.apache.hadoop.hbase.client.Scan.ReadType; 054import org.apache.hadoop.hbase.client.Table; 055import org.apache.hadoop.hbase.client.TableDescriptor; 056import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 057import org.apache.hadoop.hbase.regionserver.compactions.CompactionContext; 058import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker; 059import org.apache.hadoop.hbase.regionserver.throttle.NoLimitThroughputController; 060import org.apache.hadoop.hbase.security.User; 061import org.apache.hadoop.hbase.test.MetricsAssertHelper; 062import org.apache.hadoop.hbase.testclassification.LargeTests; 063import org.apache.hadoop.hbase.testclassification.RegionServerTests; 064import org.apache.hadoop.hbase.util.Bytes; 065import org.apache.hadoop.hbase.util.Threads; 066import org.junit.After; 067import org.junit.AfterClass; 068import org.junit.Before; 069import org.junit.BeforeClass; 070import org.junit.ClassRule; 071import org.junit.Ignore; 072import org.junit.Rule; 073import org.junit.Test; 074import org.junit.experimental.categories.Category; 075import org.junit.rules.TestName; 076import org.slf4j.Logger; 077import org.slf4j.LoggerFactory; 078 079@Category({ RegionServerTests.class, LargeTests.class }) 080public class TestRegionServerMetrics { 081 082 @ClassRule 083 public static final HBaseClassTestRule CLASS_RULE = 084 HBaseClassTestRule.forClass(TestRegionServerMetrics.class); 085 086 private static final Logger LOG = LoggerFactory.getLogger(TestRegionServerMetrics.class); 087 088 @Rule 089 public TestName testName = new TestName(); 090 091 private static MetricsAssertHelper metricsHelper; 092 private static SingleProcessHBaseCluster cluster; 093 private static HRegionServer rs; 094 private static Configuration conf; 095 private static HBaseTestingUtil TEST_UTIL; 096 private static Connection connection; 097 private static MetricsRegionServer metricsRegionServer; 098 private static MetricsRegionServerSource serverSource; 099 private static final int NUM_SCAN_NEXT = 30; 100 private static int numScanNext = 0; 101 private static byte[] cf = Bytes.toBytes("cf"); 102 private static byte[] row = Bytes.toBytes("row"); 103 private static byte[] qualifier = Bytes.toBytes("qual"); 104 private static byte[] val = Bytes.toBytes("val"); 105 private static Admin admin; 106 107 @BeforeClass 108 public static void startCluster() throws Exception { 109 metricsHelper = CompatibilityFactory.getInstance(MetricsAssertHelper.class); 110 TEST_UTIL = new HBaseTestingUtil(); 111 conf = TEST_UTIL.getConfiguration(); 112 conf.getLong("hbase.splitlog.max.resubmit", 0); 113 // Make the failure test faster 114 conf.setInt("zookeeper.recovery.retry", 0); 115 // testMobMetrics creates few hfiles and manages compaction manually. 116 conf.setInt("hbase.hstore.compactionThreshold", 100); 117 conf.setInt("hbase.hstore.compaction.max", 100); 118 conf.setInt("hbase.regionserver.periodicmemstoreflusher.rangeofdelayseconds", 4 * 60); 119 conf.setInt(HConstants.REGIONSERVER_INFO_PORT, -1); 120 121 TEST_UTIL.startMiniCluster(); 122 cluster = TEST_UTIL.getHBaseCluster(); 123 cluster.waitForActiveAndReadyMaster(); 124 admin = TEST_UTIL.getAdmin(); 125 connection = TEST_UTIL.getConnection(); 126 127 while ( 128 cluster.getLiveRegionServerThreads().isEmpty() && cluster.getRegionServer(0) == null 129 && rs.getMetrics() == null 130 ) { 131 Threads.sleep(100); 132 } 133 rs = cluster.getRegionServer(0); 134 metricsRegionServer = rs.getMetrics(); 135 serverSource = metricsRegionServer.getMetricsSource(); 136 } 137 138 @AfterClass 139 public static void after() throws Exception { 140 if (TEST_UTIL != null) { 141 TEST_UTIL.shutdownMiniCluster(); 142 } 143 } 144 145 TableName tableName; 146 Table table; 147 148 @Before 149 public void beforeTestMethod() throws Exception { 150 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 151 tableName = TableName.valueOf(testName.getMethodName()); 152 table = TEST_UTIL.createTable(tableName, cf); 153 } 154 155 @After 156 public void afterTestMethod() throws Exception { 157 admin.disableTable(tableName); 158 admin.deleteTable(tableName); 159 } 160 161 private void assertCounter(String metric, long expectedValue) { 162 metricsHelper.assertCounter(metric, expectedValue, serverSource); 163 } 164 165 private void assertGauge(String metric, long expectedValue) { 166 metricsHelper.assertGauge(metric, expectedValue, serverSource); 167 } 168 169 // Aggregates metrics from regions and assert given list of metrics and expected values. 170 private void assertRegionMetrics(String metric, long expectedValue) throws Exception { 171 try (RegionLocator locator = connection.getRegionLocator(tableName)) { 172 for (HRegionLocation location : locator.getAllRegionLocations()) { 173 RegionInfo hri = location.getRegion(); 174 MetricsRegionAggregateSource agg = 175 rs.getRegion(hri.getRegionName()).getMetrics().getSource().getAggregateSource(); 176 String prefix = "namespace_" + NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR + "_table_" 177 + tableName.getNameAsString() + "_region_" + hri.getEncodedName() + "_metric_"; 178 metricsHelper.assertCounter(prefix + metric, expectedValue, agg); 179 } 180 } 181 } 182 183 private void doNPuts(int n, boolean batch) throws Exception { 184 if (batch) { 185 List<Put> puts = new ArrayList<>(); 186 for (int i = 0; i < n; i++) { 187 Put p = new Put(Bytes.toBytes("" + i + "row")).addColumn(cf, qualifier, val); 188 puts.add(p); 189 } 190 table.put(puts); 191 } else { 192 for (int i = 0; i < n; i++) { 193 Put p = new Put(row).addColumn(cf, qualifier, val); 194 table.put(p); 195 } 196 } 197 } 198 199 private void doNGets(int n, boolean batch) throws Exception { 200 if (batch) { 201 List<Get> gets = new ArrayList<>(); 202 for (int i = 0; i < n; i++) { 203 gets.add(new Get(row)); 204 } 205 table.get(gets); 206 } else { 207 for (int i = 0; i < n; i++) { 208 table.get(new Get(row)); 209 } 210 } 211 } 212 213 private void doScan(int n, boolean caching) throws IOException { 214 Scan scan = new Scan(); 215 if (caching) { 216 scan.setCaching(n); 217 } else { 218 scan.setCaching(1); 219 } 220 ResultScanner scanner = table.getScanner(scan); 221 for (int i = 0; i < n; i++) { 222 Result res = scanner.next(); 223 LOG.debug("Result row: " + Bytes.toString(res.getRow()) + ", value: " 224 + Bytes.toString(res.getValue(cf, qualifier))); 225 } 226 } 227 228 @Test 229 public void testRegionCount() throws Exception { 230 metricsHelper.assertGauge("regionCount", 2, serverSource); 231 } 232 233 @Test 234 public void testLocalFiles() throws Exception { 235 assertGauge("percentFilesLocal", 0); 236 assertGauge("percentFilesLocalSecondaryRegions", 0); 237 } 238 239 @Test 240 public void testRequestCount() throws Exception { 241 // Do a first put to be sure that the connection is established, meta is there and so on. 242 doNPuts(1, false); 243 244 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 245 long requests = metricsHelper.getCounter("totalRequestCount", serverSource); 246 long rowActionRequests = metricsHelper.getCounter("totalRowActionRequestCount", serverSource); 247 long readRequests = metricsHelper.getCounter("readRequestCount", serverSource); 248 long writeRequests = metricsHelper.getCounter("writeRequestCount", serverSource); 249 250 doNPuts(30, false); 251 252 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 253 assertCounter("totalRequestCount", requests + 30); 254 assertCounter("totalRowActionRequestCount", rowActionRequests + 30); 255 assertCounter("readRequestCount", readRequests); 256 assertCounter("writeRequestCount", writeRequests + 30); 257 258 doNGets(10, false); 259 260 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 261 assertCounter("totalRequestCount", requests + 40); 262 assertCounter("totalRowActionRequestCount", rowActionRequests + 40); 263 assertCounter("readRequestCount", readRequests + 10); 264 assertCounter("writeRequestCount", writeRequests + 30); 265 266 assertRegionMetrics("getCount", 10); 267 assertRegionMetrics("putCount", 31); 268 269 doNGets(10, true); // true = batch 270 271 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 272 273 assertCounter("writeRequestCount", writeRequests + 30); 274 275 doNPuts(30, true); 276 277 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 278 assertCounter("writeRequestCount", writeRequests + 60); 279 280 doScan(10, false); // test after batch put so we have enough lines 281 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 282 assertCounter("writeRequestCount", writeRequests + 60); 283 numScanNext += 10; 284 285 doScan(10, true); // true = caching 286 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 287 assertCounter("writeRequestCount", writeRequests + 60); 288 numScanNext += 1; 289 } 290 291 @Test 292 public void testGet() throws Exception { 293 // Do a first put to be sure that the connection is established, meta is there and so on. 294 doNPuts(1, false); 295 doNGets(10, false); 296 assertRegionMetrics("getCount", 10); 297 metricsHelper.assertCounterGt("Get_num_ops", 10, serverSource); 298 } 299 300 @Test 301 public void testMutationsWithoutWal() throws Exception { 302 Put p = new Put(row).addColumn(cf, qualifier, val).setDurability(Durability.SKIP_WAL); 303 table.put(p); 304 305 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 306 assertGauge("mutationsWithoutWALCount", 1); 307 long minLength = row.length + cf.length + qualifier.length + val.length; 308 metricsHelper.assertGaugeGt("mutationsWithoutWALSize", minLength, serverSource); 309 } 310 311 @Test 312 public void testStoreCount() throws Exception { 313 // Force a hfile. 314 doNPuts(1, false); 315 TEST_UTIL.getAdmin().flush(tableName); 316 317 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 318 assertGauge("storeCount", 5); 319 assertGauge("storeFileCount", 1); 320 } 321 322 @Test 323 public void testStoreFileAge() throws Exception { 324 // Force a hfile. 325 doNPuts(1, false); 326 TEST_UTIL.getAdmin().flush(tableName); 327 328 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 329 assertTrue(metricsHelper.getGaugeLong("maxStoreFileAge", serverSource) > 0); 330 assertTrue(metricsHelper.getGaugeLong("minStoreFileAge", serverSource) > 0); 331 assertTrue(metricsHelper.getGaugeLong("avgStoreFileAge", serverSource) > 0); 332 } 333 334 @Test 335 public void testCheckAndPutCount() throws Exception { 336 byte[] valOne = Bytes.toBytes("Value"); 337 byte[] valTwo = Bytes.toBytes("ValueTwo"); 338 byte[] valThree = Bytes.toBytes("ValueThree"); 339 340 Put p = new Put(row); 341 p.addColumn(cf, qualifier, valOne); 342 table.put(p); 343 344 Put pTwo = new Put(row); 345 pTwo.addColumn(cf, qualifier, valTwo); 346 table.checkAndMutate(row, cf).qualifier(qualifier).ifEquals(valOne).thenPut(pTwo); 347 348 Put pThree = new Put(row); 349 pThree.addColumn(cf, qualifier, valThree); 350 table.checkAndMutate(row, cf).qualifier(qualifier).ifEquals(valOne).thenPut(pThree); 351 352 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 353 assertCounter("checkMutateFailedCount", 1); 354 assertCounter("checkMutatePassedCount", 1); 355 } 356 357 @Test 358 public void testIncrement() throws Exception { 359 Put p = new Put(row).addColumn(cf, qualifier, Bytes.toBytes(0L)); 360 table.put(p); 361 362 for (int count = 0; count < 13; count++) { 363 Increment inc = new Increment(row); 364 inc.addColumn(cf, qualifier, 100); 365 table.increment(inc); 366 } 367 368 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 369 assertCounter("incrementNumOps", 13); 370 } 371 372 @Test 373 public void testAppend() throws Exception { 374 doNPuts(1, false); 375 376 for (int count = 0; count < 73; count++) { 377 Append append = new Append(row); 378 append.addColumn(cf, qualifier, Bytes.toBytes(",Test")); 379 table.append(append); 380 } 381 382 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 383 assertCounter("appendNumOps", 73); 384 } 385 386 @Test 387 public void testScanSize() throws Exception { 388 doNPuts(100, true); // batch put 389 Scan s = new Scan(); 390 s.setBatch(1).setCaching(1).setLimit(NUM_SCAN_NEXT).setReadType(ReadType.STREAM); 391 try (ResultScanner resultScanners = table.getScanner(s)) { 392 for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) { 393 Result result = resultScanners.next(); 394 assertNotNull(result); 395 assertEquals(1, result.size()); 396 } 397 numScanNext += NUM_SCAN_NEXT; 398 assertRegionMetrics("scanCount", NUM_SCAN_NEXT); 399 } 400 } 401 402 @Test 403 public void testScanTime() throws Exception { 404 doNPuts(100, true); 405 Scan s = new Scan(); 406 s.setBatch(1).setCaching(1).setLimit(NUM_SCAN_NEXT); 407 try (ResultScanner resultScanners = table.getScanner(s)) { 408 for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) { 409 Result result = resultScanners.next(); 410 assertNotNull(result); 411 assertEquals(1, result.size()); 412 } 413 } 414 numScanNext += NUM_SCAN_NEXT; 415 assertRegionMetrics("scanCount", NUM_SCAN_NEXT); 416 } 417 418 @Test 419 public void testScanSizeForSmallScan() throws Exception { 420 doNPuts(100, true); 421 Scan s = new Scan(); 422 s.setCaching(1).setLimit(NUM_SCAN_NEXT).setReadType(ReadType.PREAD); 423 try (ResultScanner resultScanners = table.getScanner(s)) { 424 for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) { 425 Result result = resultScanners.next(); 426 assertNotNull(result); 427 } 428 assertNull(resultScanners.next()); 429 } 430 numScanNext += NUM_SCAN_NEXT; 431 assertRegionMetrics("scanCount", NUM_SCAN_NEXT); 432 } 433 434 @Test 435 public void testMobMetrics() throws IOException, InterruptedException { 436 TableName tableName = TableName.valueOf("testMobMetricsLocal"); 437 int numHfiles = 5; 438 TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName) 439 .setColumnFamily( 440 ColumnFamilyDescriptorBuilder.newBuilder(cf).setMobEnabled(true).setMobThreshold(0).build()) 441 .build(); 442 byte[] val = Bytes.toBytes("mobdata"); 443 try { 444 Table table = TEST_UTIL.createTable(htd, new byte[0][0], conf); 445 HRegion region = rs.getRegions(tableName).get(0); 446 for (int insertCount = 0; insertCount < numHfiles; insertCount++) { 447 Put p = new Put(Bytes.toBytes(insertCount)); 448 p.addColumn(cf, qualifier, val); 449 table.put(p); 450 admin.flush(tableName); 451 } 452 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 453 assertCounter("mobFlushCount", numHfiles); 454 Scan scan = new Scan().withStartRow(Bytes.toBytes(0)).withStopRow(Bytes.toBytes(numHfiles)); 455 ResultScanner scanner = table.getScanner(scan); 456 scanner.next(100); 457 numScanNext++; // this is an ugly construct 458 scanner.close(); 459 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 460 assertCounter("mobScanCellsCount", numHfiles); 461 462 setMobThreshold(region, cf, 100); 463 // metrics are reset by the region initialization 464 region.initialize(); 465 // This is how we MOB compact region 466 List<HStore> stores = region.getStores(); 467 for (HStore store : stores) { 468 // Force major compaction 469 store.triggerMajorCompaction(); 470 Optional<CompactionContext> context = store.requestCompaction(HStore.PRIORITY_USER, 471 CompactionLifeCycleTracker.DUMMY, User.getCurrent()); 472 if (!context.isPresent()) { 473 continue; 474 } 475 region.compact(context.get(), store, NoLimitThroughputController.INSTANCE, 476 User.getCurrent()); 477 } 478 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 479 assertCounter("cellsCountCompactedFromMob", numHfiles); 480 assertCounter("cellsCountCompactedToMob", 0); 481 482 scanner = table.getScanner(scan); 483 scanner.next(100); 484 numScanNext++; // this is an ugly construct 485 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 486 assertCounter("mobScanCellsCount", 0); 487 488 for (int insertCount = numHfiles; insertCount < 2 * numHfiles; insertCount++) { 489 Put p = new Put(Bytes.toBytes(insertCount)); 490 p.addColumn(cf, qualifier, val); 491 table.put(p); 492 admin.flush(tableName); 493 } 494 setMobThreshold(region, cf, 0); 495 496 // closing the region forces the compaction.discharger to archive the compacted hfiles 497 region.close(); 498 499 // metrics are reset by the region initialization 500 region.initialize(); 501 region.compact(true); 502 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 503 // metrics are reset by the region initialization 504 assertCounter("cellsCountCompactedFromMob", 0); 505 assertCounter("cellsCountCompactedToMob", 2 * numHfiles); 506 } finally { 507 admin.disableTable(tableName); 508 admin.deleteTable(tableName); 509 } 510 } 511 512 private static Region setMobThreshold(Region region, byte[] cfName, long modThreshold) { 513 ColumnFamilyDescriptor cfd = 514 ColumnFamilyDescriptorBuilder.newBuilder(region.getTableDescriptor().getColumnFamily(cfName)) 515 .setMobThreshold(modThreshold).build(); 516 TableDescriptor td = TableDescriptorBuilder.newBuilder(region.getTableDescriptor()) 517 .removeColumnFamily(cfName).setColumnFamily(cfd).build(); 518 ((HRegion) region).setTableDescriptor(td); 519 return region; 520 } 521 522 @Test 523 @Ignore 524 public void testRangeCountMetrics() throws Exception { 525 final long[] timeranges = 526 { 1, 3, 10, 30, 100, 300, 1000, 3000, 10000, 30000, 60000, 120000, 300000, 600000 }; 527 final String timeRangeType = "TimeRangeCount"; 528 final String timeRangeMetricName = "Mutate"; 529 boolean timeRangeCountUpdated = false; 530 531 // Do a first put to be sure that the connection is established, meta is there and so on. 532 Put p = new Put(row); 533 p.addColumn(cf, qualifier, val); 534 table.put(p); 535 536 // do some puts and gets 537 for (int i = 0; i < 10; i++) { 538 table.put(p); 539 } 540 541 Get g = new Get(row); 542 for (int i = 0; i < 10; i++) { 543 table.get(g); 544 } 545 546 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 547 548 // Check some time range counters were updated 549 long prior = 0; 550 551 String dynamicMetricName; 552 for (int i = 0; i < timeranges.length; i++) { 553 dynamicMetricName = 554 timeRangeMetricName + "_" + timeRangeType + "_" + prior + "-" + timeranges[i]; 555 if (metricsHelper.checkCounterExists(dynamicMetricName, serverSource)) { 556 long count = metricsHelper.getGaugeLong(dynamicMetricName, serverSource); 557 if (count > 0) { 558 timeRangeCountUpdated = true; 559 break; 560 } 561 } 562 prior = timeranges[i]; 563 } 564 dynamicMetricName = 565 timeRangeMetricName + "_" + timeRangeType + "_" + timeranges[timeranges.length - 1] + "-inf"; 566 if (metricsHelper.checkCounterExists(dynamicMetricName, serverSource)) { 567 long count = metricsHelper.getCounter(dynamicMetricName, serverSource); 568 if (count > 0) { 569 timeRangeCountUpdated = true; 570 } 571 } 572 assertEquals(true, timeRangeCountUpdated); 573 } 574 575 @Test 576 public void testAverageRegionSize() throws Exception { 577 // Force a hfile. 578 doNPuts(1, false); 579 TEST_UTIL.getAdmin().flush(tableName); 580 581 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 582 assertTrue(metricsHelper.getGaugeDouble("averageRegionSize", serverSource) > 0.0); 583 } 584 585 @Test 586 public void testReadBytes() throws Exception { 587 // Do a first put to be sure that the connection is established, meta is there and so on. 588 doNPuts(1, false); 589 doNGets(10, false); 590 TEST_UTIL.getAdmin().flush(tableName); 591 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 592 593 assertTrue("Total read bytes should be larger than 0", 594 metricsRegionServer.getRegionServerWrapper().getTotalBytesRead() > 0); 595 assertTrue("Total local read bytes should be larger than 0", 596 metricsRegionServer.getRegionServerWrapper().getLocalBytesRead() > 0); 597 assertEquals("Total short circuit read bytes should be equal to 0", 0, 598 metricsRegionServer.getRegionServerWrapper().getShortCircuitBytesRead()); 599 assertEquals("Total zero-byte read bytes should be equal to 0", 0, 600 metricsRegionServer.getRegionServerWrapper().getZeroCopyBytesRead()); 601 } 602 603 @Test 604 public void testTableDescriptorHashMetric() throws Exception { 605 doNPuts(1, false); 606 metricsRegionServer.getRegionServerWrapper().forceRecompute(); 607 608 HRegion region = rs.getRegions(tableName).get(0); 609 assertNotNull("Region should exist", region); 610 611 try (MetricsRegionWrapperImpl wrapper = new MetricsRegionWrapperImpl(region)) { 612 String hash = wrapper.getTableDescriptorHash(); 613 614 assertNotNull("TableDescriptorHash should not be null", hash); 615 assertNotEquals("TableDescriptorHash should not be 'UNKNOWN'", "UNKNOWN", hash); 616 assertEquals("Hash should be 8 characters (CRC32 hex)", 8, hash.length()); 617 } 618 } 619}