diff --git a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/impl/GlobalMetricRegistriesAdapter.java b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/impl/GlobalMetricRegistriesAdapter.java index 0d2c44c2e59a..62e631efa414 100644 --- a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/impl/GlobalMetricRegistriesAdapter.java +++ b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/metrics/impl/GlobalMetricRegistriesAdapter.java @@ -63,15 +63,17 @@ public final class GlobalMetricRegistriesAdapter { private static final Logger LOG = LoggerFactory.getLogger(GlobalMetricRegistriesAdapter.class); private class MetricsSourceAdapter implements MetricsSource { - private final MetricRegistry registry; + private final MetricRegistryInfo info; - MetricsSourceAdapter(MetricRegistry registry) { - this.registry = registry; + MetricsSourceAdapter(MetricRegistryInfo info) { + this.info = info; } @Override public void getMetrics(MetricsCollector collector, boolean all) { - metricsAdapter.snapshotAllMetrics(registry, collector); + Optional registryOpt = MetricRegistries.global().get(info); + registryOpt + .ifPresent(metricRegistry -> metricsAdapter.snapshotAllMetrics(metricRegistry, collector)); } } @@ -115,7 +117,7 @@ private void doRun() { for (MetricRegistry registry : registries) { MetricRegistryInfo info = registry.getMetricRegistryInfo(); - LOG.trace("MetricRegistryInfo : " + info.getMetricsName()); + LOG.trace("MetricRegistryInfo : {}", info.getMetricsName()); if (info.isExistingSource()) { // If there is an already existing BaseSource for this MetricRegistry, skip it here. These // types of registries are there only due to existing BaseSource implementations in the @@ -128,10 +130,10 @@ private void doRun() { if (!registeredSources.containsKey(info)) { if (LOG.isDebugEnabled()) { - LOG.debug("Registering adapter for the MetricRegistry: " + info.getMetricsJmxContext()); + LOG.debug("Registering adapter for the MetricRegistry: {}", info.getMetricsJmxContext()); } // register this as a MetricSource under different JMX Context'es. - MetricsSourceAdapter adapter = new MetricsSourceAdapter(registry); + MetricsSourceAdapter adapter = new MetricsSourceAdapter(info); LOG.info("Registering " + info.getMetricsJmxContext() + " " + info.getMetricsDescription()); DefaultMetricsSystem.instance().register(info.getMetricsJmxContext(), info.getMetricsDescription(), adapter); @@ -148,9 +150,9 @@ private void doRun() { Entry entry = it.next(); MetricRegistryInfo info = entry.getKey(); Optional found = MetricRegistries.global().get(info); - if (!found.isPresent()) { + if (found.isEmpty()) { if (LOG.isDebugEnabled()) { - LOG.debug("Removing adapter for the MetricRegistry: " + info.getMetricsJmxContext()); + LOG.debug("Removing adapter for the MetricRegistry: {}", info.getMetricsJmxContext()); } synchronized (DefaultMetricsSystem.instance()) { DefaultMetricsSystem.instance().unregisterSource(info.getMetricsJmxContext()); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServer.java index 4f5108769d6a..13b0bcc34bc9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServer.java @@ -287,15 +287,6 @@ public void updateWriteQueryMeter(HRegion region, long count) { } } - public void updateWriteQueryMeter(HRegion region) { - if (region.getMetricsTableRequests() != null) { - region.getMetricsTableRequests().updateTableWriteQueryMeter(); - } - if (serverWriteQueryMeter != null) { - serverWriteQueryMeter.mark(); - } - } - public void incrScannerLeaseExpired() { serverSource.incrScannerLeaseExpired(); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/MetricsTableRequests.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/MetricsTableRequests.java index 357a379357fd..03343334c435 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/MetricsTableRequests.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/MetricsTableRequests.java @@ -17,6 +17,7 @@ */ package org.apache.hadoop.hbase.regionserver.metrics; +import com.google.errorprone.annotations.RestrictedApi; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.metrics.Counter; @@ -110,14 +111,14 @@ public class MetricsTableRequests { private MetricRegistryInfo registryInfo; private boolean enableTableLatenciesMetrics; - private boolean enabTableQueryMeterMetrics; + private boolean enableTableQueryMeterMetrics; public boolean isEnableTableLatenciesMetrics() { return enableTableLatenciesMetrics; } - public boolean isEnabTableQueryMeterMetrics() { - return enabTableQueryMeterMetrics; + public boolean isEnableTableQueryMeterMetrics() { + return enableTableQueryMeterMetrics; } public MetricsTableRequests(TableName tableName, Configuration conf) { @@ -129,9 +130,9 @@ private void init(TableName tableName, Configuration conf) { this.conf = conf; enableTableLatenciesMetrics = this.conf.getBoolean(ENABLE_TABLE_LATENCIES_METRICS_KEY, ENABLE_TABLE_LATENCIES_METRICS_DEFAULT); - enabTableQueryMeterMetrics = this.conf.getBoolean(ENABLE_TABLE_QUERY_METER_METRICS_KEY, + enableTableQueryMeterMetrics = this.conf.getBoolean(ENABLE_TABLE_QUERY_METER_METRICS_KEY, ENABLE_TABLE_QUERY_METER_METRICS_KEY_DEFAULT); - if (enableTableLatenciesMetrics || enabTableQueryMeterMetrics) { + if (enableTableLatenciesMetrics || enableTableQueryMeterMetrics) { registry = createRegistryForTableRequests(); if (enableTableLatenciesMetrics) { getTimeHistogram = registry.histogram(GET_TIME); @@ -155,7 +156,7 @@ private void init(TableName tableName, Configuration conf) { scanBlockBytesScanned = registry.histogram(SCAN_BLOCK_BYTES_SCANNED_KEY); } - if (enabTableQueryMeterMetrics) { + if (enableTableQueryMeterMetrics) { readMeter = registry.meter(TABLE_READ_QUERY_PER_SECOND); writeMeter = registry.meter(TABLE_WRITE_QUERY_PER_SECOND); } @@ -173,7 +174,7 @@ private MetricRegistryInfo createRegistryInfoForTableRequests() { } public void removeRegistry() { - if (enableTableLatenciesMetrics || enabTableQueryMeterMetrics) { + if (enableTableLatenciesMetrics || enableTableQueryMeterMetrics) { MetricRegistries.global().remove(registry.getMetricRegistryInfo()); } } @@ -327,41 +328,30 @@ public void updateCheckAndMutate(long time, long blockBytesScanned) { * @param count Number of occurrences to record */ public void updateTableReadQueryMeter(long count) { - if (isEnabTableQueryMeterMetrics()) { + if (isEnableTableQueryMeterMetrics()) { readMeter.mark(count); } } - /** - * Update table read QPS - */ - public void updateTableReadQueryMeter() { - if (isEnabTableQueryMeterMetrics()) { - readMeter.mark(); - } - } - /** * Update table write QPS * @param count Number of occurrences to record */ public void updateTableWriteQueryMeter(long count) { - if (isEnabTableQueryMeterMetrics()) { + if (isEnableTableQueryMeterMetrics()) { writeMeter.mark(count); } } - /** - * Update table write QPS - */ - public void updateTableWriteQueryMeter() { - if (isEnabTableQueryMeterMetrics()) { - writeMeter.mark(); - } - } - - // Visible for testing + @RestrictedApi(explanation = "Should only be called in TestMetricsTableRequests", link = "", + allowedOnPath = ".*/TestMetricsTableRequests.java") public MetricRegistryInfo getMetricRegistryInfo() { return registryInfo; } + + @RestrictedApi(explanation = "Should only be called in TestMetricsTableRequests", link = "", + allowedOnPath = ".*/TestMetricsTableRequests.java") + public MetricRegistry getMetricRegistry() { + return registry; + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsRegionServer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsRegionServer.java index 8c6b3f04eb6b..731612561992 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsRegionServer.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsRegionServer.java @@ -171,7 +171,7 @@ public void testSlowCount() { MetricsTableRequests metricsTableRequests = mock(MetricsTableRequests.class); when(region.getMetricsTableRequests()).thenReturn(metricsTableRequests); when(metricsTableRequests.isEnableTableLatenciesMetrics()).thenReturn(false); - when(metricsTableRequests.isEnabTableQueryMeterMetrics()).thenReturn(false); + when(metricsTableRequests.isEnableTableQueryMeterMetrics()).thenReturn(false); for (int i = 0; i < 12; i++) { rsm.updateAppend(region, 12, 120); rsm.updateAppend(region, 1002, 10020); @@ -311,7 +311,7 @@ public void testTableQueryMeterSwitch() { MetricsTableRequests metricsTableRequests = mock(MetricsTableRequests.class); when(region.getMetricsTableRequests()).thenReturn(metricsTableRequests); when(metricsTableRequests.isEnableTableLatenciesMetrics()).thenReturn(false); - when(metricsTableRequests.isEnabTableQueryMeterMetrics()).thenReturn(false); + when(metricsTableRequests.isEnableTableQueryMeterMetrics()).thenReturn(false); Configuration conf = new Configuration(false); // disable rsm.updateReadQueryMeter(region, 500L); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsUserAggregate.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsUserAggregate.java index 8e1d126bd5cc..1cc91b860d4f 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsUserAggregate.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsUserAggregate.java @@ -73,7 +73,7 @@ private void doOperations() { MetricsTableRequests metricsTableRequests = mock(MetricsTableRequests.class); when(region.getMetricsTableRequests()).thenReturn(metricsTableRequests); when(metricsTableRequests.isEnableTableLatenciesMetrics()).thenReturn(false); - when(metricsTableRequests.isEnabTableQueryMeterMetrics()).thenReturn(false); + when(metricsTableRequests.isEnableTableQueryMeterMetrics()).thenReturn(false); for (int i = 0; i < 10; i++) { rsm.updateGet(region, 10, 10); } @@ -151,7 +151,7 @@ public Void run() { MetricsTableRequests metricsTableRequests = mock(MetricsTableRequests.class); when(region.getMetricsTableRequests()).thenReturn(metricsTableRequests); when(metricsTableRequests.isEnableTableLatenciesMetrics()).thenReturn(false); - when(metricsTableRequests.isEnabTableQueryMeterMetrics()).thenReturn(false); + when(metricsTableRequests.isEnableTableQueryMeterMetrics()).thenReturn(false); rsm.updateGet(region, 10, 100); return null; } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableRequests.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestMetricsTableRequests.java similarity index 77% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableRequests.java rename to hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestMetricsTableRequests.java index 8c47c96f1009..fb0f5133c99b 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableRequests.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestMetricsTableRequests.java @@ -15,15 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.hadoop.hbase.regionserver; +package org.apache.hadoop.hbase.regionserver.metrics; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Optional; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.metrics.Metric; import org.apache.hadoop.hbase.metrics.MetricRegistries; @@ -32,30 +31,22 @@ import org.apache.hadoop.hbase.metrics.Snapshot; import org.apache.hadoop.hbase.metrics.impl.DropwizardMeter; import org.apache.hadoop.hbase.metrics.impl.HistogramImpl; -import org.apache.hadoop.hbase.regionserver.metrics.MetricsTableRequests; import org.apache.hadoop.hbase.testclassification.RegionServerTests; import org.apache.hadoop.hbase.testclassification.SmallTests; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; -@Category({ RegionServerTests.class, SmallTests.class }) +@Tag(RegionServerTests.TAG) +@Tag(SmallTests.TAG) public class TestMetricsTableRequests { - @ClassRule - public static final HBaseClassTestRule CLASS_RULE = - HBaseClassTestRule.forClass(TestMetricsTableRequests.class); - @Test public void testMetricsTableLatencies() { TableName tn1 = TableName.valueOf("table1"); TableName tn2 = TableName.valueOf("table2"); MetricsTableRequests requests1 = new MetricsTableRequests(tn1, new Configuration()); MetricsTableRequests requests2 = new MetricsTableRequests(tn2, new Configuration()); - assertTrue("'requests' is actually " + requests1.getClass(), - requests1 instanceof MetricsTableRequests); - assertTrue("'requests' is actually " + requests2.getClass(), - requests2 instanceof MetricsTableRequests); MetricRegistryInfo info1 = requests1.getMetricRegistryInfo(); MetricRegistryInfo info2 = requests2.getMetricRegistryInfo(); @@ -101,8 +92,6 @@ public void testTableQueryMeterSwitch() { // disable assertFalse(enableTableQueryMeter); MetricsTableRequests requests = new MetricsTableRequests(tn1, conf); - assertTrue("'requests' is actually " + requests.getClass(), - requests instanceof MetricsTableRequests); MetricRegistryInfo info = requests.getMetricRegistryInfo(); Optional registry = MetricRegistries.global().get(info); @@ -118,8 +107,6 @@ public void testTableQueryMeterSwitch() { MetricsTableRequests.ENABLE_TABLE_QUERY_METER_METRICS_KEY_DEFAULT); assertTrue(enableTableQueryMeter); requests = new MetricsTableRequests(tn1, conf); - assertTrue("'requests' is actually " + requests.getClass(), - requests instanceof MetricsTableRequests); info = requests.getMetricRegistryInfo(); registry = MetricRegistries.global().get(info); @@ -127,6 +114,26 @@ public void testTableQueryMeterSwitch() { requests.updateTableReadQueryMeter(500L); read = registry.get().get("tableReadQueryPerSecond"); assertTrue(read.isPresent()); - assertEquals(((DropwizardMeter) read.get()).getCount(), 500); + assertEquals(500, ((DropwizardMeter) read.get()).getCount()); + } + + @Test + public void testSameRegistryInstanceRefCounting(TestInfo testInfo) { + TableName tn1 = TableName.valueOf(testInfo.getTestMethod().get().getName()); + + // create registry twice, should return same instance due to ref-counting + MetricsTableRequests requests1 = new MetricsTableRequests(tn1, new Configuration()); + MetricsTableRequests requests2 = new MetricsTableRequests(tn1, new Configuration()); + + MetricRegistry metricRegistry1 = requests1.getMetricRegistry(); + MetricRegistry metricRegistry2 = requests2.getMetricRegistry(); + // verify ref-counting returns same instance + assertEquals(metricRegistry1, metricRegistry2); + + MetricRegistryInfo registryInfo = metricRegistry1.getMetricRegistryInfo(); + MetricRegistries.global().remove(registryInfo); + assertTrue(MetricRegistries.global().get(registryInfo).isPresent()); + MetricRegistries.global().remove(registryInfo); + assertFalse(MetricRegistries.global().get(registryInfo).isPresent()); } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestMetricsTableRequestsRegister.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestMetricsTableRequestsRegister.java new file mode 100644 index 000000000000..cd576f3a8966 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestMetricsTableRequestsRegister.java @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.regionserver.metrics; + +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collection; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import org.apache.hadoop.hbase.HBaseTestingUtil; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; +import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; +import org.apache.hadoop.hbase.client.Table; +import org.apache.hadoop.hbase.client.TableDescriptorBuilder; +import org.apache.hadoop.hbase.metrics.MetricRegistries; +import org.apache.hadoop.hbase.metrics.MetricRegistry; +import org.apache.hadoop.hbase.metrics.MetricRegistryInfo; +import org.apache.hadoop.hbase.metrics.Snapshot; +import org.apache.hadoop.hbase.metrics.impl.HistogramImpl; +import org.apache.hadoop.hbase.testclassification.MediumTests; +import org.apache.hadoop.hbase.testclassification.RegionServerTests; +import org.apache.hadoop.metrics2.AbstractMetric; +import org.apache.hadoop.metrics2.MetricsRecord; +import org.apache.hadoop.metrics2.MetricsSource; +import org.apache.hadoop.metrics2.impl.MetricsExportHelper; +import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; + +@Tag(MediumTests.TAG) +@Tag(RegionServerTests.TAG) +public class TestMetricsTableRequestsRegister { + + private static HBaseTestingUtil UTIL; + private static Admin admin; + private static final String CF = "cf"; + private static final int PUT_COUNT = 10; + private TableName tableName; + private MetricRegistryInfo info; + + @BeforeAll + public static void beforeAll() throws Exception { + UTIL = new HBaseTestingUtil(); + UTIL.startMiniCluster(1); + admin = UTIL.getAdmin(); + } + + @BeforeEach + public void setUp(TestInfo testInfo) throws Exception { + tableName = TableName.valueOf(testInfo.getTestMethod().get().getName()); + info = buildRegistryInfo(tableName); + + TableDescriptorBuilder tdb = TableDescriptorBuilder.newBuilder(tableName) + .setColumnFamily(ColumnFamilyDescriptorBuilder.of(CF)); + admin.createTable(tdb.build()); + UTIL.waitTableAvailable(tableName); + } + + @AfterAll + public static void afterAll() throws Exception { + if (UTIL != null) { + UTIL.shutdownMiniCluster(); + } + } + + @Test + public void testMetricsTableRequestsReRegisterAfterAlter() throws Exception { + // Wait for the metrics to be registered + await().atMost(15, TimeUnit.SECONDS).until(() -> getRegisteredMetrics(info) != null); + assertTrue(isMetricsExported(info)); + + generatePutMetrics(PUT_COUNT); + + Optional metricRegistryBefore = MetricRegistries.global().get(info); + assertTrue(metricRegistryBefore.isPresent()); + assertEquals(PUT_COUNT, getMetricsSnapshot(metricRegistryBefore.get(), "putTime").getCount()); + assertEquals(PUT_COUNT, getMetricsExportedCount(info, "PutTime_num_ops")); + + // Alter table to force region reopen + ColumnFamilyDescriptorBuilder cfd = + ColumnFamilyDescriptorBuilder.newBuilder(CF.getBytes()).setMaxVersions(2); + admin.modifyColumnFamily(tableName, cfd.build()); + UTIL.waitTableAvailable(tableName); + + generatePutMetrics(PUT_COUNT * 2); + + await().atMost(15, TimeUnit.SECONDS) + .until(() -> !metricRegistryBefore.get().equals(MetricRegistries.global().get(info).get())); + + Optional metricRegistryAfter = MetricRegistries.global().get(info); + assertTrue(metricRegistryAfter.isPresent()); + // Check that the registry has been updated + assertNotEquals(metricRegistryBefore, metricRegistryAfter); + assertEquals(PUT_COUNT * 2, + getMetricsSnapshot(metricRegistryAfter.get(), "putTime").getCount()); + + // Check that the exported metrics have been updated + await().atMost(15, TimeUnit.SECONDS) + .until(() -> getMetricsExportedCount(info, "PutTime_num_ops") == PUT_COUNT * 2); + } + + @Test + public void testMetricsTableRequestsUnRegisterAfterDrop() throws Exception { + // Wait for the metrics to be registered + await().atMost(15, TimeUnit.SECONDS).until(() -> getRegisteredMetrics(info) != null); + assertTrue(isMetricsExported(info)); + + generatePutMetrics(PUT_COUNT); + + Optional metricRegistryBefore = MetricRegistries.global().get(info); + assertTrue(metricRegistryBefore.isPresent()); + assertEquals(PUT_COUNT, getMetricsSnapshot(metricRegistryBefore.get(), "putTime").getCount()); + assertEquals(PUT_COUNT, getMetricsExportedCount(info, "PutTime_num_ops")); + + // Disable and delete the table to trigger the metrics un-registration + admin.disableTable(tableName); + admin.deleteTable(tableName); + + Optional metricRegistryAfter = MetricRegistries.global().get(info); + assertFalse(metricRegistryAfter.isPresent()); + + // Check that the exported metrics have been removed + await().atMost(15, TimeUnit.SECONDS) + .until(() -> getRegisteredMetrics(info) == null && !isMetricsExported(info)); + } + + private void generatePutMetrics(int count) throws Exception { + try (Table table = UTIL.getConnection().getTable(tableName)) { + UTIL.loadNumericRows(table, CF.getBytes(), 0, count); + } + } + + private MetricsSource getRegisteredMetrics(MetricRegistryInfo metricRegistryInfo) { + return DefaultMetricsSystem.instance().getSource(metricRegistryInfo.getMetricsJmxContext()); + } + + private boolean isMetricsExported(MetricRegistryInfo metricRegistryInfo) { + return MetricsExportHelper.export().stream() + .anyMatch(exported -> exported.name().equals(metricRegistryInfo.getMetricsName())); + } + + private Snapshot getMetricsSnapshot(MetricRegistry metricRegistry, String metricName) { + return ((HistogramImpl) metricRegistry.get(metricName).get()).snapshot(); + } + + private int getMetricsExportedCount(MetricRegistryInfo metricRegistryInfo, String metricsName) { + Collection exportedMetrics = MetricsExportHelper.export(); + for (MetricsRecord exported : exportedMetrics) { + if (exported.name().equals(metricRegistryInfo.getMetricsName())) { + for (AbstractMetric metric : exported.metrics()) { + if (metric.name().equals(metricsName)) { + return metric.value().intValue(); + } + } + } + } + return -1; + } + + private MetricRegistryInfo buildRegistryInfo(TableName tableName) { + String metricsName = "TableRequests_Namespace_" + tableName.getNamespaceAsString() + "_table_" + + tableName.getQualifierAsString(); + String metricsJmx = "RegionServer,sub=" + metricsName; + return new MetricRegistryInfo(metricsName, + "Metrics about Tables on a single HBase RegionServer", metricsJmx, "regionserver", false); + } +}