diff --git src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 7858846..7ad6e49 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -966,6 +966,7 @@ public class HRegion implements HeapSize { // , Writable{ status.setStatus("Running coprocessor post-close hooks"); this.coprocessorHost.postClose(abort); } + this.opMetrics.closeMetrics(); status.markComplete("Closed"); LOG.info("Closed " + this); return result; diff --git src/main/java/org/apache/hadoop/hbase/regionserver/metrics/OperationMetrics.java src/main/java/org/apache/hadoop/hbase/regionserver/metrics/OperationMetrics.java index ac4e57f..c3cb8f0 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/metrics/OperationMetrics.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/metrics/OperationMetrics.java @@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.regionserver.metrics; import java.util.Set; +import java.util.TreeSet; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; @@ -49,6 +50,7 @@ public class OperationMetrics { private static final String MULTIPUT_KEY = "multiput_"; private static final String APPEND_KEY = "append_"; + /** Conf key controlling whether we should expose metrics.*/ private static final String CONF_KEY = "hbase.metrics.exposeOperationTimes"; @@ -57,6 +59,7 @@ public class OperationMetrics { private String regionName = null; private String regionMetrixPrefix = null; private Configuration conf = null; + private Set metricsPut = null; /** @@ -69,6 +72,7 @@ public class OperationMetrics { // RegionOperationMetrics relies on SchemaMetrics to do naming. if (conf != null) { SchemaMetrics.configureGlobally(conf); + metricsPut = new TreeSet(); this.conf = conf; if (regionInfo != null) { @@ -172,6 +176,16 @@ public class OperationMetrics { public void updateDeleteMetrics(Set columnFamilies, long value) { doUpdateTimeVarying(columnFamilies, DELETE_KEY, value); } + + /** + * This deletes all old metrics this instance has ever created or updated. + */ + public void closeMetrics() { + for (String m:metricsPut) { + RegionMetricsStorage.deleteTimeVaryingMetric(m); + } + this.metricsPut = new TreeSet(); + } /** * Method to send updates for cf and region metrics. This is the normal method @@ -199,7 +213,9 @@ public class OperationMetrics { private void doSafeIncTimeVarying(String prefix, String key, long value) { if (conf.getBoolean(CONF_KEY, true)) { if (prefix != null && !prefix.isEmpty() && key != null && !key.isEmpty()) { - RegionMetricsStorage.incrTimeVaryingMetric(prefix + key, value); + String m = prefix + key; + metricsPut.add(m); + RegionMetricsStorage.incrTimeVaryingMetric(m, value); } } } diff --git src/main/java/org/apache/hadoop/hbase/regionserver/metrics/RegionMetricsStorage.java src/main/java/org/apache/hadoop/hbase/regionserver/metrics/RegionMetricsStorage.java index 416e495..7a782f5 100644 --- src/main/java/org/apache/hadoop/hbase/regionserver/metrics/RegionMetricsStorage.java +++ src/main/java/org/apache/hadoop/hbase/regionserver/metrics/RegionMetricsStorage.java @@ -99,6 +99,10 @@ public class RegionMetricsStorage { } oldVal.addAndGet(amount); } + + static void deleteTimeVaryingMetric(String key) { + timeVaryingMetrics.remove(key); + } public static void setNumericMetric(String key, long amount) { numericMetrics.put(key, new AtomicLong(amount)); @@ -127,4 +131,6 @@ public class RegionMetricsStorage { return m.get(); } + + } diff --git src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerMetrics.java src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerMetrics.java index 6defa73..297bb58 100644 --- src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerMetrics.java +++ src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerMetrics.java @@ -49,6 +49,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; +import com.google.common.collect.Multiset.Entry; + /** * Test metrics incremented on region server operations. */ @@ -197,6 +199,32 @@ public class TestRegionServerMetrics { } @Test + public void testRemoveRegionMetrics() throws IOException, InterruptedException { + String cf = "REMOVECF"; + HTable hTable = TEST_UTIL.createTable(TABLE_NAME.getBytes(), cf.getBytes()); + HRegionInfo[] regionInfos = + hTable.getRegionLocations().keySet() + .toArray(new HRegionInfo[hTable.getRegionLocations().keySet().size()]); + + String regionName = regionInfos[0].getEncodedName(); + + // Do some operations so there are metrics. + Put pOne = new Put("TEST".getBytes()); + pOne.add(cf.getBytes(), "test".getBytes(), "test".getBytes()); + hTable.put(pOne); + + Get g = new Get("TEST".getBytes()); + g.addFamily(cf.getBytes()); + hTable.get(g); + assertTimeVaryingMetricCount(1, TABLE_NAME, cf, regionName, "get_"); + HBaseAdmin admin = TEST_UTIL.getHBaseAdmin(); + admin.disableTable(TABLE_NAME.getBytes()); + + assertTimeVaryingMetricCount(0, TABLE_NAME, cf, regionName, "get_"); + + } + + @Test public void testMultipleRegions() throws IOException, InterruptedException { TEST_UTIL.createRandomTable(