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