diff --git a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapper.java b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapper.java index 03ebc4cbd7b1..10eb281fa1ec 100644 --- a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapper.java +++ b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapper.java @@ -523,4 +523,6 @@ public interface MetricsRegionServerWrapper { long getTrailerHitCount(); long getTotalRowActionRequestCount(); + + String getConfVar(String name, String defaultValue); } diff --git a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatencies.java b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatencies.java index 231bad1be879..d99ef25a381f 100644 --- a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatencies.java +++ b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatencies.java @@ -44,15 +44,15 @@ public interface MetricsTableLatencies { */ String METRICS_JMX_CONTEXT = "RegionServer,sub=" + METRICS_NAME; - String GET_TIME = "getTime"; + String GET_TIME = "get"; String SCAN_TIME = "scanTime"; String SCAN_SIZE = "scanSize"; - String PUT_TIME = "putTime"; - String PUT_BATCH_TIME = "putBatchTime"; - String DELETE_TIME = "deleteTime"; - String DELETE_BATCH_TIME = "deleteBatchTime"; - String INCREMENT_TIME = "incrementTime"; - String APPEND_TIME = "appendTime"; + String PUT_TIME = "put"; + String PUT_BATCH_TIME = "putBatch"; + String DELETE_TIME = "delete"; + String DELETE_BATCH_TIME = "deleteBatch"; + String INCREMENT_TIME = "increment"; + String APPEND_TIME = "append"; /** * Update the Put time histogram @@ -125,4 +125,9 @@ public interface MetricsTableLatencies { * @param t time it took */ void updateScanTime(String tableName, long t); + + /** + * @return Whether this metrics writer creates scoped metrics (see DynamicMetricsRegistry). + */ + boolean isScoped(); } diff --git a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregate.java b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregate.java index 48b3a2c8252d..d5659132a4d1 100644 --- a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregate.java +++ b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregate.java @@ -18,6 +18,8 @@ package org.apache.hadoop.hbase.regionserver; +import org.apache.hadoop.conf.Configuration; + import org.apache.yetus.audience.InterfaceAudience; /** @@ -107,6 +109,8 @@ public interface MetricsTableWrapperAggregate { */ long getNumReferenceFiles(String table); - - + /** + * @return Get HBase configuration; allows reflection-based classes to have access to it. + */ + Configuration getConf(); } diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java index 2532a2d836bc..d95d17ba9765 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsAssignmentManagerSourceImpl.java @@ -29,7 +29,7 @@ public class MetricsAssignmentManagerSourceImpl extends BaseSourceImpl implements MetricsAssignmentManagerSource { - + // TODO: it may make sense to add some table-scoped metrics for these. private MutableGaugeLong ritGauge; private MutableGaugeLong ritCountOverThresholdGauge; private MutableGaugeLong ritOldestAgeGauge; diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsMasterFilesystemSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsMasterFilesystemSourceImpl.java index d78efce2add9..11a21715c72b 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsMasterFilesystemSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/master/MetricsMasterFilesystemSourceImpl.java @@ -26,7 +26,7 @@ public class MetricsMasterFilesystemSourceImpl extends BaseSourceImpl implements MetricsMasterFileSystemSource { - + // TODO: it may make sense to add some table-scoped metrics for these. private MetricHistogram splitSizeHisto; private MetricHistogram splitTimeHisto; private MetricHistogram metaSplitTimeHisto; diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/ExceptionTrackingSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/ExceptionTrackingSourceImpl.java index 3af27d89b90c..a459f03478c3 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/ExceptionTrackingSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/metrics/ExceptionTrackingSourceImpl.java @@ -28,6 +28,7 @@ @InterfaceAudience.Private public class ExceptionTrackingSourceImpl extends BaseSourceImpl implements ExceptionTrackingSource { + // TODO: it may make sense to add some table-scoped metrics for these. protected MutableFastCounter exceptions; protected MutableFastCounter exceptionsOOO; protected MutableFastCounter exceptionsBusy; diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsHeapMemoryManagerSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsHeapMemoryManagerSourceImpl.java index 047f8e13b1e1..75ffb0a7bc2f 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsHeapMemoryManagerSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsHeapMemoryManagerSourceImpl.java @@ -31,7 +31,7 @@ @InterfaceAudience.Private public class MetricsHeapMemoryManagerSourceImpl extends BaseSourceImpl implements MetricsHeapMemoryManagerSource { - + // TODO: it may make sense to add some table-scoped metrics for these. private final MetricHistogram blockedFlushHistogram; private final MetricHistogram unblockedFlushHistogram; private final MetricHistogram incMemStoreSizeHistogram; diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.java index 2e6b4586919d..b1b0870d0cce 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.java @@ -77,7 +77,11 @@ public MetricsRegionSource createRegion(MetricsRegionWrapper wrapper) { @Override public MetricsTableSource createTable(String table, MetricsTableWrapperAggregate wrapper) { - return new MetricsTableSourceImpl(table, getTableAggregate(), wrapper); + if (MetricsTableAggregateSourceImpl.areTablesViaTags(wrapper)) { + return new MetricsTableSourceImplWithTags(table, getTableAggregate(), wrapper); + } else { + return new MetricsTableSourceImpl(table, getTableAggregate(), wrapper); + } } public MetricsIOSource createIO(MetricsIOWrapper wrapper) { diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceImpl.java index 58c42a558330..8aafd4873386 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceImpl.java @@ -18,14 +18,26 @@ package org.apache.hadoop.hbase.regionserver; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.nio.channels.ClosedByInterruptException; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.metrics.BaseSourceImpl; import org.apache.hadoop.hbase.metrics.Interns; import org.apache.hadoop.metrics2.MetricHistogram; import org.apache.hadoop.metrics2.MetricsCollector; import org.apache.hadoop.metrics2.MetricsRecordBuilder; +import org.apache.hadoop.metrics2.lib.MetricsFactory; import org.apache.hadoop.metrics2.lib.MutableFastCounter; import org.apache.yetus.audience.InterfaceAudience; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Hadoop2 implementation of MetricsRegionServerSource. * @@ -34,6 +46,8 @@ @InterfaceAudience.Private public class MetricsRegionServerSourceImpl extends BaseSourceImpl implements MetricsRegionServerSource { + private static final Logger LOG = LoggerFactory.getLogger(MetricsRegionServerSourceImpl.class); + final MetricsRegionServerWrapper rsWrap; private final MetricHistogram putHisto; @@ -102,73 +116,80 @@ public MetricsRegionServerSourceImpl(String metricsName, super(metricsName, metricsDescription, metricsContext, metricsJmxContext); this.rsWrap = rsWrap; - putHisto = getMetricsRegistry().newTimeHistogram(PUT_KEY); - putBatchHisto = getMetricsRegistry().newTimeHistogram(PUT_BATCH_KEY); - slowPut = getMetricsRegistry().newCounter(SLOW_PUT_KEY, SLOW_PUT_DESC, 0L); - - deleteHisto = getMetricsRegistry().newTimeHistogram(DELETE_KEY); - slowDelete = getMetricsRegistry().newCounter(SLOW_DELETE_KEY, SLOW_DELETE_DESC, 0L); - - deleteBatchHisto = getMetricsRegistry().newTimeHistogram(DELETE_BATCH_KEY); - checkAndDeleteHisto = getMetricsRegistry().newTimeHistogram(CHECK_AND_DELETE_KEY); - checkAndPutHisto = getMetricsRegistry().newTimeHistogram(CHECK_AND_PUT_KEY); - - getHisto = getMetricsRegistry().newTimeHistogram(GET_KEY); - slowGet = getMetricsRegistry().newCounter(SLOW_GET_KEY, SLOW_GET_DESC, 0L); - - incrementHisto = getMetricsRegistry().newTimeHistogram(INCREMENT_KEY); - slowIncrement = getMetricsRegistry().newCounter(SLOW_INCREMENT_KEY, SLOW_INCREMENT_DESC, 0L); - - appendHisto = getMetricsRegistry().newTimeHistogram(APPEND_KEY); - slowAppend = getMetricsRegistry().newCounter(SLOW_APPEND_KEY, SLOW_APPEND_DESC, 0L); - - replayHisto = getMetricsRegistry().newTimeHistogram(REPLAY_KEY); - scanSizeHisto = getMetricsRegistry().newSizeHistogram(SCAN_SIZE_KEY); - scanTimeHisto = getMetricsRegistry().newTimeHistogram(SCAN_TIME_KEY); - - flushTimeHisto = getMetricsRegistry().newTimeHistogram(FLUSH_TIME, FLUSH_TIME_DESC); - flushMemstoreSizeHisto = getMetricsRegistry() + // See the comment in getMetrics. This is similar but for registry-based metrics; + // if tables are via tags, don't output the same metrics as MetricsTableSourceImpl. + boolean areTablesViaTags = MetricsTableAggregateSourceImpl.areTablesViaTags(rsWrap); + boolean areLatenciesViaTags = areTablesViaTags && Boolean.parseBoolean(rsWrap.getConfVar( + MetricsTableSourceImpl.RS_ENABLE_TABLE_METRICS_KEY, + Boolean.toString(MetricsTableSourceImpl.RS_ENABLE_TABLE_METRICS_DEFAULT))); + MetricsFactory tableFactory = areTablesViaTags? new MetricsFactory() : getMetricsRegistry(); + MetricsFactory tableLatencyFactory = areLatenciesViaTags ? tableFactory : getMetricsRegistry(); + + putHisto = tableLatencyFactory.newTimeHistogram(PUT_KEY, ""); + putBatchHisto = tableLatencyFactory.newTimeHistogram(PUT_BATCH_KEY, ""); + deleteHisto = tableLatencyFactory.newTimeHistogram(DELETE_KEY, ""); + deleteBatchHisto = tableLatencyFactory.newTimeHistogram(DELETE_BATCH_KEY, ""); + scanSizeHisto = tableLatencyFactory.newSizeHistogram(SCAN_SIZE_KEY, ""); + scanTimeHisto = tableLatencyFactory.newTimeHistogram(SCAN_TIME_KEY, ""); + getHisto = tableLatencyFactory.newTimeHistogram(GET_KEY, ""); + incrementHisto = tableLatencyFactory.newTimeHistogram(INCREMENT_KEY, ""); + appendHisto = tableLatencyFactory.newTimeHistogram(APPEND_KEY, ""); + + flushTimeHisto = tableFactory.newTimeHistogram(FLUSH_TIME, FLUSH_TIME_DESC); + flushMemstoreSizeHisto = tableFactory .newSizeHistogram(FLUSH_MEMSTORE_SIZE, FLUSH_MEMSTORE_SIZE_DESC); - flushOutputSizeHisto = getMetricsRegistry().newSizeHistogram(FLUSH_OUTPUT_SIZE, - FLUSH_OUTPUT_SIZE_DESC); - flushedOutputBytes = getMetricsRegistry().newCounter(FLUSHED_OUTPUT_BYTES, - FLUSHED_OUTPUT_BYTES_DESC, 0L); - flushedMemstoreBytes = getMetricsRegistry().newCounter(FLUSHED_MEMSTORE_BYTES, - FLUSHED_MEMSTORE_BYTES_DESC, 0L); - - compactionTimeHisto = getMetricsRegistry() + flushOutputSizeHisto = tableFactory.newSizeHistogram(FLUSH_OUTPUT_SIZE, + FLUSH_OUTPUT_SIZE_DESC); + flushedOutputBytes = tableFactory.newCounter(FLUSHED_OUTPUT_BYTES, + FLUSHED_OUTPUT_BYTES_DESC, 0L); + flushedMemstoreBytes = tableFactory.newCounter(FLUSHED_MEMSTORE_BYTES, + FLUSHED_MEMSTORE_BYTES_DESC, 0L); + + compactionTimeHisto = tableFactory .newTimeHistogram(COMPACTION_TIME, COMPACTION_TIME_DESC); - compactionInputFileCountHisto = getMetricsRegistry() + compactionInputFileCountHisto = tableFactory .newHistogram(COMPACTION_INPUT_FILE_COUNT, COMPACTION_INPUT_FILE_COUNT_DESC); - compactionInputSizeHisto = getMetricsRegistry() + compactionInputSizeHisto = tableFactory .newSizeHistogram(COMPACTION_INPUT_SIZE, COMPACTION_INPUT_SIZE_DESC); - compactionOutputFileCountHisto = getMetricsRegistry() + compactionOutputFileCountHisto = tableFactory .newHistogram(COMPACTION_OUTPUT_FILE_COUNT, COMPACTION_OUTPUT_FILE_COUNT_DESC); - compactionOutputSizeHisto = getMetricsRegistry() + compactionOutputSizeHisto = tableFactory .newSizeHistogram(COMPACTION_OUTPUT_SIZE, COMPACTION_OUTPUT_SIZE_DESC); - compactedInputBytes = getMetricsRegistry() + compactedInputBytes = tableFactory .newCounter(COMPACTED_INPUT_BYTES, COMPACTED_INPUT_BYTES_DESC, 0L); - compactedOutputBytes = getMetricsRegistry() + compactedOutputBytes = tableFactory .newCounter(COMPACTED_OUTPUT_BYTES, COMPACTED_OUTPUT_BYTES_DESC, 0L); - majorCompactionTimeHisto = getMetricsRegistry() + majorCompactionTimeHisto = tableFactory .newTimeHistogram(MAJOR_COMPACTION_TIME, MAJOR_COMPACTION_TIME_DESC); - majorCompactionInputFileCountHisto = getMetricsRegistry() + majorCompactionInputFileCountHisto = tableFactory .newHistogram(MAJOR_COMPACTION_INPUT_FILE_COUNT, MAJOR_COMPACTION_INPUT_FILE_COUNT_DESC); - majorCompactionInputSizeHisto = getMetricsRegistry() + majorCompactionInputSizeHisto = tableFactory .newSizeHistogram(MAJOR_COMPACTION_INPUT_SIZE, MAJOR_COMPACTION_INPUT_SIZE_DESC); - majorCompactionOutputFileCountHisto = getMetricsRegistry() + majorCompactionOutputFileCountHisto = tableFactory .newHistogram(MAJOR_COMPACTION_OUTPUT_FILE_COUNT, MAJOR_COMPACTION_OUTPUT_FILE_COUNT_DESC); - majorCompactionOutputSizeHisto = getMetricsRegistry() + majorCompactionOutputSizeHisto = tableFactory .newSizeHistogram(MAJOR_COMPACTION_OUTPUT_SIZE, MAJOR_COMPACTION_OUTPUT_SIZE_DESC); - majorCompactedInputBytes = getMetricsRegistry() + majorCompactedInputBytes = tableFactory .newCounter(MAJOR_COMPACTED_INPUT_BYTES, MAJOR_COMPACTED_INPUT_BYTES_DESC, 0L); - majorCompactedOutputBytes = getMetricsRegistry() + majorCompactedOutputBytes = tableFactory .newCounter(MAJOR_COMPACTED_OUTPUT_BYTES, MAJOR_COMPACTED_OUTPUT_BYTES_DESC, 0L); - splitTimeHisto = getMetricsRegistry().newTimeHistogram(SPLIT_KEY); - splitRequest = getMetricsRegistry().newCounter(SPLIT_REQUEST_KEY, SPLIT_REQUEST_DESC, 0L); - splitSuccess = getMetricsRegistry().newCounter(SPLIT_SUCCESS_KEY, SPLIT_SUCCESS_DESC, 0L); + splitTimeHisto = tableFactory.newTimeHistogram(SPLIT_KEY, ""); + splitRequest = tableFactory.newCounter(SPLIT_REQUEST_KEY, SPLIT_REQUEST_DESC, 0L); + splitSuccess = tableFactory.newCounter(SPLIT_SUCCESS_KEY, SPLIT_SUCCESS_DESC, 0L); + + // End metrics we currently output per table. The rest are always output by server. + + slowPut = getMetricsRegistry().newCounter(SLOW_PUT_KEY, SLOW_PUT_DESC, 0L); + slowDelete = getMetricsRegistry().newCounter(SLOW_DELETE_KEY, SLOW_DELETE_DESC, 0L); + checkAndDeleteHisto = getMetricsRegistry().newTimeHistogram(CHECK_AND_DELETE_KEY); + checkAndPutHisto = getMetricsRegistry().newTimeHistogram(CHECK_AND_PUT_KEY); + slowGet = getMetricsRegistry().newCounter(SLOW_GET_KEY, SLOW_GET_DESC, 0L); + slowIncrement = getMetricsRegistry().newCounter(SLOW_INCREMENT_KEY, SLOW_INCREMENT_DESC, 0L); + slowAppend = getMetricsRegistry().newCounter(SLOW_APPEND_KEY, SLOW_APPEND_DESC, 0L); + + replayHisto = getMetricsRegistry().newTimeHistogram(REPLAY_KEY); // pause monitor metrics infoPauseThresholdExceeded = getMetricsRegistry().newCounter(INFO_THRESHOLD_COUNT_KEY, @@ -334,19 +355,16 @@ public void getMetrics(MetricsCollector metricsCollector, boolean all) { // rsWrap can be null because this function is called inside of init. if (rsWrap != null) { - addGaugesToMetricsRecordBuilder(mrb) - .addCounter(Interns.info(TOTAL_REQUEST_COUNT, TOTAL_REQUEST_COUNT_DESC), - rsWrap.getTotalRequestCount()) + // TODO: this is rather ugly... there are too many ways to handle metrics in HBase. + // There needs to be refactoring where ALL the metrics are in one place, + // handled the same, and the e.g. same request count is handled in exactly one place. + // For now here we'd make an assumption of how the independent table-metrics thingie + // handles a subset of its metrics (others that go thru registry are handled this way + // via "TableMetrics" and "MetricsTable"). Sigh.. + boolean skipTableMetrics = MetricsTableAggregateSourceImpl.areTablesViaTags(rsWrap); + mrb = addGaugesToMetricsRecordBuilder(mrb, skipTableMetrics) .addCounter(Interns.info(TOTAL_ROW_ACTION_REQUEST_COUNT, TOTAL_ROW_ACTION_REQUEST_COUNT_DESC), rsWrap.getTotalRowActionRequestCount()) - .addCounter(Interns.info(READ_REQUEST_COUNT, READ_REQUEST_COUNT_DESC), - rsWrap.getReadRequestsCount()) - .addCounter(Interns.info(CP_REQUEST_COUNT, CP_REQUEST_COUNT_DESC), - rsWrap.getCpRequestsCount()) - .addCounter(Interns.info(FILTERED_READ_REQUEST_COUNT, - FILTERED_READ_REQUEST_COUNT_DESC), rsWrap.getFilteredReadRequestsCount()) - .addCounter(Interns.info(WRITE_REQUEST_COUNT, WRITE_REQUEST_COUNT_DESC), - rsWrap.getWriteRequestsCount()) .addCounter(Interns.info(RPC_GET_REQUEST_COUNT, RPC_GET_REQUEST_COUNT_DESC), rsWrap.getRpcGetRequestsCount()) .addCounter(Interns.info(RPC_SCAN_REQUEST_COUNT, RPC_SCAN_REQUEST_COUNT_DESC), @@ -462,6 +480,20 @@ public void getMetrics(MetricsCollector metricsCollector, boolean all) { rsWrap.getZookeeperQuorum()) .tag(Interns.info(SERVER_NAME_NAME, SERVER_NAME_DESC), rsWrap.getServerName()) .tag(Interns.info(CLUSTER_ID_NAME, CLUSTER_ID_DESC), rsWrap.getClusterId()); + + if (!skipTableMetrics) { + // See MetricsTableSourceImpl.snapshot for the list, and the TO-DO above + mrb.addCounter(Interns.info(TOTAL_REQUEST_COUNT, TOTAL_REQUEST_COUNT_DESC), + rsWrap.getTotalRequestCount()) + .addCounter(Interns.info(READ_REQUEST_COUNT, READ_REQUEST_COUNT_DESC), + rsWrap.getReadRequestsCount()) + .addCounter(Interns.info(CP_REQUEST_COUNT, CP_REQUEST_COUNT_DESC), + rsWrap.getCpRequestsCount()) + .addCounter(Interns.info(FILTERED_READ_REQUEST_COUNT, + FILTERED_READ_REQUEST_COUNT_DESC), rsWrap.getFilteredReadRequestsCount()) + .addCounter(Interns.info(WRITE_REQUEST_COUNT, WRITE_REQUEST_COUNT_DESC), + rsWrap.getWriteRequestsCount()); + } } metricsRegistry.snapshot(mrb, all); @@ -473,28 +505,13 @@ public void getMetrics(MetricsCollector metricsCollector, boolean all) { } } - private MetricsRecordBuilder addGaugesToMetricsRecordBuilder(MetricsRecordBuilder mrb) { - return mrb.addGauge(Interns.info(REGION_COUNT, REGION_COUNT_DESC), rsWrap.getNumOnlineRegions()) - .addGauge(Interns.info(STORE_COUNT, STORE_COUNT_DESC), rsWrap.getNumStores()) - .addGauge(Interns.info(WALFILE_COUNT, WALFILE_COUNT_DESC), rsWrap.getNumWALFiles()) + private MetricsRecordBuilder addGaugesToMetricsRecordBuilder( + MetricsRecordBuilder mrb, boolean skipTableMetrics) { + mrb = mrb.addGauge(Interns.info(WALFILE_COUNT, WALFILE_COUNT_DESC), rsWrap.getNumWALFiles()) .addGauge(Interns.info(WALFILE_SIZE, WALFILE_SIZE_DESC), rsWrap.getWALFileSize()) - .addGauge(Interns.info(STOREFILE_COUNT, STOREFILE_COUNT_DESC), - rsWrap.getNumStoreFiles()) - .addGauge(Interns.info(MEMSTORE_SIZE, MEMSTORE_SIZE_DESC), rsWrap.getMemStoreSize()) - .addGauge(Interns.info(STOREFILE_SIZE, STOREFILE_SIZE_DESC), rsWrap.getStoreFileSize()) .addGauge(Interns.info(STOREFILE_SIZE_GROWTH_RATE, STOREFILE_SIZE_GROWTH_RATE_DESC), - rsWrap.getStoreFileSizeGrowthRate()) - .addGauge(Interns.info(MAX_STORE_FILE_AGE, MAX_STORE_FILE_AGE_DESC), - rsWrap.getMaxStoreFileAge()) - .addGauge(Interns.info(MIN_STORE_FILE_AGE, MIN_STORE_FILE_AGE_DESC), - rsWrap.getMinStoreFileAge()) - .addGauge(Interns.info(AVG_STORE_FILE_AGE, AVG_STORE_FILE_AGE_DESC), - rsWrap.getAvgStoreFileAge()) - .addGauge(Interns.info(NUM_REFERENCE_FILES, NUM_REFERENCE_FILES_DESC), - rsWrap.getNumReferenceFiles()) + rsWrap.getStoreFileSizeGrowthRate()) .addGauge(Interns.info(RS_START_TIME_NAME, RS_START_TIME_DESC), rsWrap.getStartCode()) - .addGauge(Interns.info(AVERAGE_REGION_SIZE, AVERAGE_REGION_SIZE_DESC), - rsWrap.getAverageRegionSize()) .addGauge(Interns.info(STOREFILE_INDEX_SIZE, STOREFILE_INDEX_SIZE_DESC), rsWrap.getStoreFileIndexSize()) .addGauge(Interns.info(STATIC_INDEX_SIZE, STATIC_INDEX_SIZE_DESC), @@ -554,6 +571,25 @@ private MetricsRecordBuilder addGaugesToMetricsRecordBuilder(MetricsRecordBuilde rsWrap.getReadRequestsRatePerSecond()) .addGauge(Interns.info(WRITE_REQUEST_RATE_PER_SECOND, WRITE_REQUEST_RATE_DESC), rsWrap.getWriteRequestsRatePerSecond()); + // See MetricsTableSourceImpl.snapshot for the list, and the TO-DO in the caller + if (!skipTableMetrics) { + mrb.addGauge(Interns.info(REGION_COUNT, REGION_COUNT_DESC), rsWrap.getNumOnlineRegions()) + .addGauge(Interns.info(STORE_COUNT, STORE_COUNT_DESC), rsWrap.getNumStores()) + .addGauge(Interns.info(STOREFILE_COUNT, STOREFILE_COUNT_DESC), rsWrap.getNumStoreFiles()) + .addGauge(Interns.info(MEMSTORE_SIZE, MEMSTORE_SIZE_DESC), rsWrap.getMemStoreSize()) + .addGauge(Interns.info(STOREFILE_SIZE, STOREFILE_SIZE_DESC), rsWrap.getStoreFileSize()) + .addGauge(Interns.info(MAX_STORE_FILE_AGE, MAX_STORE_FILE_AGE_DESC), + rsWrap.getMaxStoreFileAge()) + .addGauge(Interns.info(MIN_STORE_FILE_AGE, MIN_STORE_FILE_AGE_DESC), + rsWrap.getMinStoreFileAge()) + .addGauge(Interns.info(AVG_STORE_FILE_AGE, AVG_STORE_FILE_AGE_DESC), + rsWrap.getAvgStoreFileAge()) + .addGauge(Interns.info(AVERAGE_REGION_SIZE, AVERAGE_REGION_SIZE_DESC), + rsWrap.getAverageRegionSize()) + .addGauge(Interns.info(NUM_REFERENCE_FILES, NUM_REFERENCE_FILES_DESC), + rsWrap.getNumReferenceFiles()); + } + return mrb; } @Override diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionSourceImpl.java index 1831062c288b..83952121bec9 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionSourceImpl.java @@ -65,6 +65,10 @@ public class MetricsRegionSourceImpl implements MetricsRegionSource { private final int hashCode; + // TODO: add tagged region metrics option, similar to the tables one? + // Note that this would require refactoring them together to avoid metrics duplication. + // See also the ugly way server-level metrics handle duplication now - all of these + // could be merged and handled nicely and consistently. public MetricsRegionSourceImpl(MetricsRegionWrapper regionWrapper, MetricsRegionAggregateSourceImpl aggregate) { this.regionWrapper = regionWrapper; diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableAggregateSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableAggregateSourceImpl.java index 5133a96db10a..b8bccc7630e6 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableAggregateSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableAggregateSourceImpl.java @@ -18,8 +18,11 @@ package org.apache.hadoop.hbase.regionserver; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.CompatibilitySingletonFactory; import org.apache.hadoop.hbase.metrics.BaseSourceImpl; import org.apache.hadoop.hbase.metrics.Interns; @@ -32,6 +35,8 @@ @InterfaceAudience.Private public class MetricsTableAggregateSourceImpl extends BaseSourceImpl implements MetricsTableAggregateSource { + public static final String TABLE_METRICS_TAGS = "hbase.metrics.table.via.tags"; + public static final boolean TABLE_METRICS_TAGS_DEFAULT = false; private static final Logger LOG = LoggerFactory.getLogger(MetricsTableAggregateSourceImpl.class); private ConcurrentHashMap tableSources = new ConcurrentHashMap<>(); @@ -47,8 +52,17 @@ public MetricsTableAggregateSourceImpl(String metricsName, super(metricsName, metricsDescription, metricsContext, metricsJmxContext); } - private void register(MetricsTableSource source) { - source.registerMetrics(); + public static boolean areTablesViaTags(MetricsTableWrapperAggregate wrapper) { + return areTablesViaTags(wrapper.getConf()); + } + + public static boolean areTablesViaTags(MetricsRegionServerWrapper wrapper) { + return Boolean.parseBoolean(wrapper.getConfVar( + TABLE_METRICS_TAGS, Boolean.toString(TABLE_METRICS_TAGS_DEFAULT))); + } + + public static boolean areTablesViaTags(Configuration conf) { + return conf != null && conf.getBoolean(TABLE_METRICS_TAGS, TABLE_METRICS_TAGS_DEFAULT); } @Override @@ -92,14 +106,33 @@ public MetricsTableSource getOrCreateTableSource(String table, @Override public void getMetrics(MetricsCollector collector, boolean all) { MetricsRecordBuilder mrb = collector.addRecord(metricsName); + Map scopedMrbs = new HashMap<>(); + + // Note that there are two metrics models in one being merged here... + // 1) MetricsTableSource.snapshot writes a subset of metrics + // 2) DynamicMetricsRegistry.snapshot writes a DIFFERENT set of metrics via a different model. + // See MetricsTableSourceImpl of registerMetrics and snapshot for the example of two models. if (tableSources != null) { for (MetricsTableSource tableMetricSource : tableSources.values()) { if (tableMetricSource instanceof MetricsTableSourceImpl) { - ((MetricsTableSourceImpl) tableMetricSource).snapshot(mrb, all); + MetricsTableSourceImpl impl = (MetricsTableSourceImpl) tableMetricSource; + MetricsRecordBuilder scopedMrb = mrb; + String scope = impl.getScope(); + if (scope != null) { + scopedMrb = collector.addRecord(metricsName + "." + scope); + if (scopedMrbs.put(scope, scopedMrb) != null) { + LOG.error("Found multiple collectors for " + scope); + } + } + impl.snapshot(scopedMrb, all); } } mrb.addGauge(Interns.info(NUM_TABLES, NUMBER_OF_TABLES_DESC), tableSources.size()); + + for (Map.Entry e : scopedMrbs.entrySet()) { + metricsRegistry.snapshotScoped(e.getKey(), e.getValue(), all); + } metricsRegistry.snapshot(mrb, all); } } diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatenciesImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatenciesImpl.java index 980388f54796..d53cd5a7cd1e 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatenciesImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatenciesImpl.java @@ -16,14 +16,24 @@ */ package org.apache.hadoop.hbase.regionserver; -import java.util.HashMap; +import java.util.concurrent.ConcurrentMap; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.metrics.BaseSourceImpl; import org.apache.hadoop.metrics2.MetricHistogram; +import org.apache.hadoop.metrics2.MetricsCollector; +import org.apache.hadoop.metrics2.MetricsRecordBuilder; +import org.apache.hadoop.metrics2.MetricsTag; import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry; +import org.apache.hadoop.metrics2.lib.MutableSizeHistogram; +import org.apache.hadoop.metrics2.lib.MutableTimeHistogram; import org.apache.yetus.audience.InterfaceAudience; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; +import org.apache.hbase.thirdparty.com.google.common.collect.Maps;import org.slf4j.Logger;import org.slf4j.LoggerFactory; /** * Implementation of {@link MetricsTableLatencies} to track latencies for one table in a @@ -31,8 +41,12 @@ */ @InterfaceAudience.Private public class MetricsTableLatenciesImpl extends BaseSourceImpl implements MetricsTableLatencies { + private static final Logger LOG = LoggerFactory.getLogger(MetricsTableLatenciesImpl.class); - private final HashMap histogramsByTable = new HashMap<>(); + private final ConcurrentMap histogramsByTable = + Maps.newConcurrentMap(); + private Configuration conf; + private boolean useTags; @VisibleForTesting public static class TableHistograms { @@ -46,18 +60,27 @@ public static class TableHistograms { final MetricHistogram scanTimeHisto; final MetricHistogram scanSizeHisto; + // TODO: this doesn't appear to remove metrics like the other impl TableHistograms(DynamicMetricsRegistry registry, TableName tn) { - getTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, GET_TIME)); - incrementTimeHisto = registry.newTimeHistogram( - qualifyMetricsName(tn, INCREMENT_TIME)); - appendTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, APPEND_TIME)); - putTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, PUT_TIME)); - putBatchTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, PUT_BATCH_TIME)); - deleteTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, DELETE_TIME)); - deleteBatchTimeHisto = registry.newTimeHistogram( - qualifyMetricsName(tn, DELETE_BATCH_TIME)); - scanTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, SCAN_TIME)); - scanSizeHisto = registry.newSizeHistogram(qualifyMetricsName(tn, SCAN_SIZE)); + getTimeHisto = newTimeHistogram(registry, tn, GET_TIME); + incrementTimeHisto = newTimeHistogram(registry, tn, INCREMENT_TIME); + appendTimeHisto = newTimeHistogram(registry, tn, APPEND_TIME); + putTimeHisto = newTimeHistogram(registry, tn, PUT_TIME); + putBatchTimeHisto = newTimeHistogram(registry, tn, PUT_BATCH_TIME); + deleteTimeHisto = newTimeHistogram(registry, tn, DELETE_TIME); + deleteBatchTimeHisto = newTimeHistogram(registry, tn, DELETE_BATCH_TIME); + scanTimeHisto = newTimeHistogram(registry, tn, SCAN_TIME); + scanSizeHisto = newSizeHistogram(registry, tn, SCAN_SIZE); + } + + protected MutableTimeHistogram newTimeHistogram( + DynamicMetricsRegistry registry, TableName tn, String name) { + return registry.newTimeHistogram(qualifyMetricsName(tn, name)); + } + + protected MutableSizeHistogram newSizeHistogram( + DynamicMetricsRegistry registry, TableName tn, String name) { + return registry.newSizeHistogram(qualifyMetricsName(tn, name)); } public void updatePut(long time) { @@ -97,6 +120,24 @@ public void updateScanTime(long t) { } } + private static class TableHistogramsWithTags extends TableHistograms { + TableHistogramsWithTags(DynamicMetricsRegistry registry, TableName tn) { + super(registry, tn); + } + + @Override + protected MutableSizeHistogram newSizeHistogram( + DynamicMetricsRegistry registry, TableName tn, String name) { + return registry.newScopedSizeHistogram(tn.getNameAsString(), name, ""); + } + + @Override + protected MutableTimeHistogram newTimeHistogram( + DynamicMetricsRegistry registry, TableName tn, String name) { + return registry.newScopedTimeHistogram(tn.getNameAsString(), name, ""); + } + } + @VisibleForTesting public static String qualifyMetricsName(TableName tableName, String metric) { StringBuilder sb = new StringBuilder(); @@ -112,7 +153,8 @@ public TableHistograms getOrCreateTableHistogram(String tableName) { final TableName tn = TableName.valueOf(tableName); TableHistograms latency = histogramsByTable.get(tn); if (latency == null) { - latency = new TableHistograms(getMetricsRegistry(), tn); + DynamicMetricsRegistry reg = getMetricsRegistry(); + latency = useTags ? new TableHistogramsWithTags(reg, tn) : new TableHistograms(reg, tn); histogramsByTable.put(tn, latency); } return latency; @@ -171,4 +213,34 @@ public void updateScanSize(String tableName, long scanSize) { public void updateScanTime(String tableName, long t) { getOrCreateTableHistogram(tableName).updateScanTime(t); } + + public void setConf(Configuration conf) { + if (this.conf != null) { + LOG.warn("The object was already initialized with {}", this.useTags); + return; + } + this.conf = conf; + this.useTags = MetricsTableAggregateSourceImpl.areTablesViaTags(conf); + } + + @Override + public void getMetrics(MetricsCollector metricsCollector, boolean all) { + if (!useTags) { + super.getMetrics(metricsCollector, all); + } else { + for (TableName tn : histogramsByTable.keySet()) { + String scope = tn.getNameAsString(); + String recName = metricsRegistry.info().name() + "." + scope; + MetricsRecordBuilder mrb = metricsCollector.addRecord(recName); + mrb.add(new MetricsTag(MetricsTableSourceImplWithTags.TABLE_TAG_INFO, scope)); + metricsRegistry.snapshotScoped(scope, mrb, all); + } + // There are no metrics here not scoped to the table, so don't snapshot(). + } + } + + @Override + public boolean isScoped() { + return useTags; + } } diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImpl.java index 5e789d506257..d419039ecd66 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImpl.java @@ -62,21 +62,30 @@ import static org.apache.hadoop.hbase.regionserver.MetricsRegionServerSource.SPLIT_SUCCESS_KEY; import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.metrics.Interns; import org.apache.hadoop.metrics2.MetricHistogram; +import org.apache.hadoop.metrics2.MetricsInfo; import org.apache.hadoop.metrics2.MetricsRecordBuilder; import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry; import org.apache.hadoop.metrics2.lib.MutableFastCounter; +import org.apache.hadoop.metrics2.lib.MutableHistogram; +import org.apache.hadoop.metrics2.lib.MutableSizeHistogram; +import org.apache.hadoop.metrics2.lib.MutableTimeHistogram; import org.apache.yetus.audience.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @InterfaceAudience.Private public class MetricsTableSourceImpl implements MetricsTableSource { - private static final Logger LOG = LoggerFactory.getLogger(MetricsTableSourceImpl.class); + + public static final String RS_ENABLE_TABLE_METRICS_KEY = + "hbase.regionserver.enable.table.latencies"; + public static final boolean RS_ENABLE_TABLE_METRICS_DEFAULT = true; + private AtomicBoolean closed = new AtomicBoolean(false); // Non-final so that we can null out the wrapper @@ -85,7 +94,7 @@ public class MetricsTableSourceImpl implements MetricsTableSource { // tableWrapper around too long. private MetricsTableWrapperAggregate tableWrapperAgg; private final MetricsTableAggregateSourceImpl agg; - private final DynamicMetricsRegistry registry; + protected final DynamicMetricsRegistry registry; private final String tableNamePrefix; private final TableName tableName; private final int hashCode; @@ -132,77 +141,93 @@ public MetricsTableSourceImpl(String tblName, this.hashCode = this.tableName.hashCode(); } + + public static boolean areTableLatenciesEnabled(Configuration conf) { + return conf.getBoolean(RS_ENABLE_TABLE_METRICS_KEY, RS_ENABLE_TABLE_METRICS_DEFAULT); + } + + @Override public synchronized void registerMetrics() { - flushTimeHisto = registry.newTimeHistogram(tableNamePrefix + FLUSH_TIME, FLUSH_TIME_DESC); - flushMemstoreSizeHisto = - registry.newSizeHistogram(tableNamePrefix + FLUSH_MEMSTORE_SIZE, FLUSH_MEMSTORE_SIZE_DESC); - flushOutputSizeHisto = - registry.newSizeHistogram(tableNamePrefix + FLUSH_OUTPUT_SIZE, FLUSH_OUTPUT_SIZE_DESC); - flushedOutputBytes = - registry.newCounter(tableNamePrefix + FLUSHED_OUTPUT_BYTES, FLUSHED_OUTPUT_BYTES_DESC, 0L); - flushedMemstoreBytes = registry.newCounter(tableNamePrefix + FLUSHED_MEMSTORE_BYTES, - FLUSHED_MEMSTORE_BYTES_DESC, 0L); - - compactionTimeHisto = - registry.newTimeHistogram(tableNamePrefix + COMPACTION_TIME, COMPACTION_TIME_DESC); - compactionInputFileCountHisto = registry.newHistogram( - tableNamePrefix + COMPACTION_INPUT_FILE_COUNT, COMPACTION_INPUT_FILE_COUNT_DESC); - compactionInputSizeHisto = registry.newSizeHistogram(tableNamePrefix + COMPACTION_INPUT_SIZE, - COMPACTION_INPUT_SIZE_DESC); - compactionOutputFileCountHisto = registry.newHistogram( - tableNamePrefix + COMPACTION_OUTPUT_FILE_COUNT, COMPACTION_OUTPUT_FILE_COUNT_DESC); - compactionOutputSizeHisto = registry.newSizeHistogram(tableNamePrefix + COMPACTION_OUTPUT_SIZE, - COMPACTION_OUTPUT_SIZE_DESC); - compactedInputBytes = registry.newCounter(tableNamePrefix + COMPACTED_INPUT_BYTES, - COMPACTED_INPUT_BYTES_DESC, 0L); - compactedOutputBytes = registry.newCounter(tableNamePrefix + COMPACTED_OUTPUT_BYTES, - COMPACTED_OUTPUT_BYTES_DESC, 0L); - - majorCompactionTimeHisto = registry.newTimeHistogram(tableNamePrefix + MAJOR_COMPACTION_TIME, - MAJOR_COMPACTION_TIME_DESC); - majorCompactionInputFileCountHisto = registry.newHistogram( - tableNamePrefix + MAJOR_COMPACTION_INPUT_FILE_COUNT, MAJOR_COMPACTION_INPUT_FILE_COUNT_DESC); - majorCompactionInputSizeHisto = registry.newSizeHistogram( - tableNamePrefix + MAJOR_COMPACTION_INPUT_SIZE, MAJOR_COMPACTION_INPUT_SIZE_DESC); + flushTimeHisto = newTimeHisto(FLUSH_TIME, FLUSH_TIME_DESC); + flushMemstoreSizeHisto = newSizeHisto(FLUSH_MEMSTORE_SIZE, FLUSH_MEMSTORE_SIZE_DESC); + flushOutputSizeHisto = newSizeHisto(FLUSH_OUTPUT_SIZE, FLUSH_OUTPUT_SIZE_DESC); + flushedOutputBytes = newCounter(FLUSHED_OUTPUT_BYTES, FLUSHED_OUTPUT_BYTES_DESC); + flushedMemstoreBytes = newCounter(FLUSHED_MEMSTORE_BYTES, FLUSHED_MEMSTORE_BYTES_DESC); + + compactionTimeHisto = newTimeHisto(COMPACTION_TIME, COMPACTION_TIME_DESC); + compactionInputFileCountHisto = newHistogram(COMPACTION_INPUT_FILE_COUNT, COMPACTION_INPUT_FILE_COUNT_DESC); + compactionInputSizeHisto = newSizeHisto(COMPACTION_INPUT_SIZE, COMPACTION_INPUT_SIZE_DESC); + compactionOutputFileCountHisto = newHistogram(COMPACTION_OUTPUT_FILE_COUNT, COMPACTION_OUTPUT_FILE_COUNT_DESC); + compactionOutputSizeHisto = newSizeHisto(COMPACTION_OUTPUT_SIZE, COMPACTION_OUTPUT_SIZE_DESC); + compactedInputBytes = newCounter(COMPACTED_INPUT_BYTES, COMPACTED_INPUT_BYTES_DESC); + compactedOutputBytes = newCounter(COMPACTED_OUTPUT_BYTES, COMPACTED_OUTPUT_BYTES_DESC); + + majorCompactionTimeHisto = newTimeHisto(MAJOR_COMPACTION_TIME, MAJOR_COMPACTION_TIME_DESC); + majorCompactionInputFileCountHisto = newHistogram(MAJOR_COMPACTION_INPUT_FILE_COUNT, MAJOR_COMPACTION_INPUT_FILE_COUNT_DESC); + majorCompactionInputSizeHisto = newSizeHisto(MAJOR_COMPACTION_INPUT_SIZE, MAJOR_COMPACTION_INPUT_SIZE_DESC); majorCompactionOutputFileCountHisto = - registry.newHistogram(tableNamePrefix + MAJOR_COMPACTION_OUTPUT_FILE_COUNT, - MAJOR_COMPACTION_OUTPUT_FILE_COUNT_DESC); - majorCompactionOutputSizeHisto = registry.newSizeHistogram( - tableNamePrefix + MAJOR_COMPACTION_OUTPUT_SIZE, MAJOR_COMPACTION_OUTPUT_SIZE_DESC); - majorCompactedInputBytes = registry.newCounter(tableNamePrefix + MAJOR_COMPACTED_INPUT_BYTES, - MAJOR_COMPACTED_INPUT_BYTES_DESC, 0L); - majorCompactedOutputBytes = registry.newCounter(tableNamePrefix + MAJOR_COMPACTED_OUTPUT_BYTES, - MAJOR_COMPACTED_OUTPUT_BYTES_DESC, 0L); + newHistogram(MAJOR_COMPACTION_OUTPUT_FILE_COUNT, MAJOR_COMPACTION_OUTPUT_FILE_COUNT_DESC); + majorCompactionOutputSizeHisto = newSizeHisto(MAJOR_COMPACTION_OUTPUT_SIZE, MAJOR_COMPACTION_OUTPUT_SIZE_DESC); + majorCompactedInputBytes = newCounter(MAJOR_COMPACTED_INPUT_BYTES, MAJOR_COMPACTED_INPUT_BYTES_DESC); + majorCompactedOutputBytes = newCounter(MAJOR_COMPACTED_OUTPUT_BYTES, MAJOR_COMPACTED_OUTPUT_BYTES_DESC); + + splitTimeHisto = newTimeHisto(tableNamePrefix + SPLIT_KEY, ""); + splitRequest = newCounter(SPLIT_REQUEST_KEY, SPLIT_REQUEST_DESC); + splitSuccess = newCounter(SPLIT_SUCCESS_KEY, SPLIT_SUCCESS_DESC); + } + + protected MutableHistogram newHistogram(String name, String desc) { + return registry.newHistogram(tableNamePrefix + name, desc); + } + + protected MutableFastCounter newCounter(String name, String desc) { + return registry.newCounter(tableNamePrefix + name, desc, 0L); + } + + protected MutableSizeHistogram newSizeHisto(String name, String desc) { + return registry.newSizeHistogram(tableNamePrefix + name, desc); + } - splitTimeHisto = registry.newTimeHistogram(tableNamePrefix + SPLIT_KEY); - splitRequest = registry.newCounter(tableNamePrefix + SPLIT_REQUEST_KEY, SPLIT_REQUEST_DESC, 0L); - splitSuccess = registry.newCounter(tableNamePrefix + SPLIT_SUCCESS_KEY, SPLIT_SUCCESS_DESC, 0L); + protected MutableTimeHistogram newTimeHisto(String name, String desc) { + return registry.newTimeHistogram(tableNamePrefix + name, desc); + } + + protected void removeNonHistogram(String name) { + registry.removeMetric(tableNamePrefix + name); + } + + protected void removeHistogram(String name) { + registry.removeHistogramMetrics(tableNamePrefix + name); + } + + protected MetricsInfo createMetricsInfo(String name, String desc) { + return Interns.info(tableNamePrefix + name, desc); } private void deregisterMetrics() { - registry.removeHistogramMetrics(tableNamePrefix + FLUSH_TIME); - registry.removeHistogramMetrics(tableNamePrefix + FLUSH_MEMSTORE_SIZE); - registry.removeHistogramMetrics(tableNamePrefix + FLUSH_OUTPUT_SIZE); - registry.removeMetric(tableNamePrefix + FLUSHED_OUTPUT_BYTES); - registry.removeMetric(tableNamePrefix + FLUSHED_MEMSTORE_BYTES); - registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_TIME); - registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_INPUT_FILE_COUNT); - registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_INPUT_SIZE); - registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_OUTPUT_FILE_COUNT); - registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_OUTPUT_SIZE); - registry.removeMetric(tableNamePrefix + COMPACTED_INPUT_BYTES); - registry.removeMetric(tableNamePrefix + COMPACTED_OUTPUT_BYTES); - registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_TIME); - registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_INPUT_FILE_COUNT); - registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_INPUT_SIZE); - registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_OUTPUT_FILE_COUNT); - registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_OUTPUT_SIZE); - registry.removeMetric(tableNamePrefix + MAJOR_COMPACTED_INPUT_BYTES); - registry.removeMetric(tableNamePrefix + MAJOR_COMPACTED_OUTPUT_BYTES); - registry.removeHistogramMetrics(tableNamePrefix + SPLIT_KEY); - registry.removeMetric(tableNamePrefix + SPLIT_REQUEST_KEY); - registry.removeMetric(tableNamePrefix + SPLIT_SUCCESS_KEY); + removeHistogram(FLUSH_TIME); + removeHistogram(FLUSH_MEMSTORE_SIZE); + removeHistogram(FLUSH_OUTPUT_SIZE); + removeNonHistogram(FLUSHED_OUTPUT_BYTES); + removeNonHistogram(FLUSHED_MEMSTORE_BYTES); + removeHistogram(COMPACTION_TIME); + removeHistogram(COMPACTION_INPUT_FILE_COUNT); + removeHistogram(COMPACTION_INPUT_SIZE); + removeHistogram(COMPACTION_OUTPUT_FILE_COUNT); + removeHistogram(COMPACTION_OUTPUT_SIZE); + removeNonHistogram(COMPACTED_INPUT_BYTES); + removeNonHistogram(COMPACTED_OUTPUT_BYTES); + removeHistogram(MAJOR_COMPACTION_TIME); + removeHistogram(MAJOR_COMPACTION_INPUT_FILE_COUNT); + removeHistogram(MAJOR_COMPACTION_INPUT_SIZE); + removeHistogram(MAJOR_COMPACTION_OUTPUT_FILE_COUNT); + removeHistogram(MAJOR_COMPACTION_OUTPUT_SIZE); + removeNonHistogram(MAJOR_COMPACTED_INPUT_BYTES); + removeNonHistogram(MAJOR_COMPACTED_OUTPUT_BYTES); + removeHistogram(SPLIT_KEY); + removeNonHistogram(SPLIT_REQUEST_KEY); + removeNonHistogram(SPLIT_SUCCESS_KEY); } @Override @@ -260,57 +285,59 @@ void snapshot(MetricsRecordBuilder mrb, boolean ignored) { if (closed.get()) { return; } - + // Make sure that these metrics are skipped in MetricsRegionServerSourceImpl; + // see skipTableMetrics and the comment there. if (this.tableWrapperAgg != null) { - mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.CP_REQUEST_COUNT, + mrb.addCounter(createMetricsInfo(MetricsRegionServerSource.CP_REQUEST_COUNT, MetricsRegionServerSource.CP_REQUEST_COUNT_DESC), tableWrapperAgg.getCpRequestsCount(tableName.getNameAsString())); - mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.READ_REQUEST_COUNT, + mrb.addCounter(createMetricsInfo(MetricsRegionServerSource.READ_REQUEST_COUNT, MetricsRegionServerSource.READ_REQUEST_COUNT_DESC), - tableWrapperAgg.getReadRequestCount(tableName.getNameAsString())); - mrb.addCounter( - Interns.info(tableNamePrefix + MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT, - MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT_DESC), - tableWrapperAgg.getFilteredReadRequestCount(tableName.getNameAsString())); - mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.WRITE_REQUEST_COUNT, + tableWrapperAgg.getReadRequestCount(tableName.getNameAsString())); + mrb.addCounter(createMetricsInfo(MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT, + MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT_DESC), + tableWrapperAgg.getFilteredReadRequestCount(tableName.getNameAsString())); + mrb.addCounter(createMetricsInfo(MetricsRegionServerSource.WRITE_REQUEST_COUNT, MetricsRegionServerSource.WRITE_REQUEST_COUNT_DESC), tableWrapperAgg.getWriteRequestCount(tableName.getNameAsString())); - mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.TOTAL_REQUEST_COUNT, + mrb.addCounter(createMetricsInfo(MetricsRegionServerSource.TOTAL_REQUEST_COUNT, MetricsRegionServerSource.TOTAL_REQUEST_COUNT_DESC), tableWrapperAgg.getTotalRequestsCount(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.MEMSTORE_SIZE, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.MEMSTORE_SIZE, MetricsRegionServerSource.MEMSTORE_SIZE_DESC), tableWrapperAgg.getMemStoreSize(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.STOREFILE_COUNT, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.STOREFILE_COUNT, MetricsRegionServerSource.STOREFILE_COUNT_DESC), tableWrapperAgg.getNumStoreFiles(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.STOREFILE_SIZE, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.STOREFILE_SIZE, MetricsRegionServerSource.STOREFILE_SIZE_DESC), tableWrapperAgg.getStoreFileSize(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsTableSource.TABLE_SIZE, - MetricsTableSource.TABLE_SIZE_DESC), + mrb.addGauge(createMetricsInfo(MetricsTableSource.TABLE_SIZE, + MetricsTableSource.TABLE_SIZE_DESC), tableWrapperAgg.getTableSize(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.AVERAGE_REGION_SIZE, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.AVERAGE_REGION_SIZE, MetricsRegionServerSource.AVERAGE_REGION_SIZE_DESC), tableWrapperAgg.getAvgRegionSize(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.REGION_COUNT, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.REGION_COUNT, MetricsRegionServerSource.REGION_COUNT_DESC), tableWrapperAgg.getNumRegions(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.STORE_COUNT, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.STORE_COUNT, MetricsRegionServerSource.STORE_COUNT_DESC), tableWrapperAgg.getNumStores(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.MAX_STORE_FILE_AGE, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.MAX_STORE_FILE_AGE, MetricsRegionServerSource.MAX_STORE_FILE_AGE_DESC), tableWrapperAgg.getMaxStoreFileAge(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.MIN_STORE_FILE_AGE, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.MIN_STORE_FILE_AGE, MetricsRegionServerSource.MIN_STORE_FILE_AGE_DESC), tableWrapperAgg.getMinStoreFileAge(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.AVG_STORE_FILE_AGE, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.AVG_STORE_FILE_AGE, MetricsRegionServerSource.AVG_STORE_FILE_AGE_DESC), tableWrapperAgg.getAvgStoreFileAge(tableName.getNameAsString())); - mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.NUM_REFERENCE_FILES, + mrb.addGauge(createMetricsInfo(MetricsRegionServerSource.NUM_REFERENCE_FILES, MetricsRegionServerSource.NUM_REFERENCE_FILES_DESC), tableWrapperAgg.getNumReferenceFiles(tableName.getNameAsString())); + + addTags(mrb); } } } @@ -342,10 +369,6 @@ public MetricsTableWrapperAggregate getTableWrapper() { return tableWrapperAgg; } - public String getTableNamePrefix() { - return tableNamePrefix; - } - @Override public void incrSplitRequest() { splitRequest.incr(); @@ -421,4 +444,11 @@ public synchronized void updateCompactionOutputSize(boolean isMajor, long bytes) majorCompactedOutputBytes.incr(bytes); } } + + public String getScope() { + return null; + } + + protected void addTags(MetricsRecordBuilder mrb) { + } } diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImplWithTags.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImplWithTags.java new file mode 100644 index 000000000000..d0216b2d50df --- /dev/null +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableSourceImplWithTags.java @@ -0,0 +1,94 @@ +/** + * 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; + +import org.apache.hadoop.hbase.metrics.Interns; +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.hadoop.metrics2.MetricsRecordBuilder; +import org.apache.hadoop.metrics2.MetricsTag; +import org.apache.hadoop.metrics2.lib.MutableFastCounter; +import org.apache.hadoop.metrics2.lib.MutableHistogram; +import org.apache.hadoop.metrics2.lib.MutableSizeHistogram; +import org.apache.hadoop.metrics2.lib.MutableTimeHistogram; + +import org.apache.yetus.audience.InterfaceAudience; + +/** + * MetricsTableSource implementation that uses metrics tags to output table name, rather than + * writing it as a part of the metric name. Note that there are 3 ways to write table metrics in + * HBase currently - MetricsTableSource+registry, MetricsTableSource.snapshot, as well as a + * separate class for latencies. This handles two of them, being MetricsTableSource. + */ +@InterfaceAudience.Private +public class MetricsTableSourceImplWithTags extends MetricsTableSourceImpl { + public final static MetricsInfo TABLE_TAG_INFO = Interns.info("HBaseTable", ""); + private final String tableNameStr; + private final MetricsTag metricsTag; + + public MetricsTableSourceImplWithTags(String tblName, + MetricsTableAggregateSourceImpl aggregate, MetricsTableWrapperAggregate tblWrapperAgg) { + super(tblName, aggregate, tblWrapperAgg); + this.tableNameStr = getTableName(); + this.metricsTag = new MetricsTag(TABLE_TAG_INFO, tableNameStr); + } + + @Override + protected MutableHistogram newHistogram(String name, String desc) { + return registry.newScopedHistogram(tableNameStr, name, desc); + } + + @Override + protected MutableFastCounter newCounter(String name, String desc) { + return registry.newScopedCounter(tableNameStr, name, desc, 0L); + } + + @Override + protected MutableSizeHistogram newSizeHisto(String name, String desc) { + return registry.newScopedSizeHistogram(tableNameStr, name, desc); + } + + @Override + protected MutableTimeHistogram newTimeHisto(String name, String desc) { + return registry.newScopedTimeHistogram(tableNameStr, name, desc); + } + + @Override + protected void removeNonHistogram(String name) { + registry.removeScopedMetric(tableNameStr, name); + } + + @Override + protected void removeHistogram(String name) { + registry.removeScopedHistogramMetrics(tableNameStr, name); + } + + @Override + protected MetricsInfo createMetricsInfo(String name, String desc) { + return Interns.info(name, desc); + } + + @Override + public String getScope() { + return tableNameStr; + } + + @Override + protected void addTags(MetricsRecordBuilder mrb) { + mrb.add(metricsTag); + } +} diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/DynamicMetricsRegistry.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/DynamicMetricsRegistry.java index 7e17ee9bf461..7db5567b4cb1 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/DynamicMetricsRegistry.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/DynamicMetricsRegistry.java @@ -46,11 +46,13 @@ * thread-safe map, as we allow dynamic metrics additions/removals. */ @InterfaceAudience.Private -public class DynamicMetricsRegistry { +public class DynamicMetricsRegistry extends MetricsFactory { private static final Logger LOG = LoggerFactory.getLogger(DynamicMetricsRegistry.class); private final ConcurrentMap metricsMap = Maps.newConcurrentMap(); + private final ConcurrentMap> scopedMetricsMap = + Maps.newConcurrentMap(); private final ConcurrentMap tagsMap = Maps.newConcurrentMap(); private final MetricsInfo metricsInfo; @@ -113,10 +115,59 @@ public MetricsTag getTag(String name) { * @param iVal initial value * @return a new counter object */ + @Override public MutableFastCounter newCounter(String name, String desc, long iVal) { return newCounter(new MetricsInfoImpl(name, desc), iVal); } + public MutableFastCounter newScopedCounter(String scope, String name, String desc, long iVal) { + MutableFastCounter ret = super.newCounter(new MetricsInfoImpl(name, desc), iVal); + return addNewScopedMetricIfAbsent(scope, name, ret, MutableFastCounter.class); + } + + public MutableHistogram newScopedHistogram(String scope, String name, String desc) { + MutableHistogram ret = super.newHistogram(name, desc); + return addNewScopedMetricIfAbsent(scope, name, ret, MutableHistogram.class); + } + + public MutableTimeHistogram newScopedTimeHistogram(String scope, String name, String desc) { + MutableTimeHistogram ret = super.newTimeHistogram(name, desc); + return addNewScopedMetricIfAbsent(scope, name, ret, MutableTimeHistogram.class); + } + + public MutableSizeHistogram newScopedSizeHistogram(String scope, String name, String desc) { + MutableSizeHistogram ret = super.newSizeHistogram(name, desc); + return addNewScopedMetricIfAbsent(scope, name, ret, MutableSizeHistogram.class); + } + + public void removeScopedMetric(String scope, String name) { + // Note: don't call helper.removeObjectName on scoped metrics, they all have the same name. + ConcurrentMap map = scopedMetricsMap.getOrDefault(scope, null); + if (map == null) { + LOG.warn("Cannot remove metric {} - scope {} not found", name, scope); + return; + } + map.remove(name); + if (map.isEmpty()) { + scopedMetricsMap.computeIfPresent(scope, (k, v) -> v.isEmpty() ? null : v); + } + } + + public void removeScopedHistogramMetrics(String scope, String baseName) { + // Note: don't call helper.removeObjectName on scoped metrics, they all have the same name. + ConcurrentMap map = scopedMetricsMap.getOrDefault(scope, null); + if (map == null) { + LOG.warn("Cannot remove metric {} - scope {} not found", baseName, scope); + return; + } + for (String suffix : histogramSuffixes) { + map.remove(baseName + suffix); + } + if (map.isEmpty()) { + scopedMetricsMap.computeIfPresent(scope, (k, v) -> v.isEmpty() ? null : v); + } + } + /** * Create a mutable long integer counter * @param info metadata of the metric @@ -124,7 +175,7 @@ public MutableFastCounter newCounter(String name, String desc, long iVal) { * @return a new counter object */ public MutableFastCounter newCounter(MetricsInfo info, long iVal) { - MutableFastCounter ret = new MutableFastCounter(info, iVal); + MutableFastCounter ret = super.newCounter(info, iVal); return addNewMetricIfAbsent(info.name(), ret, MutableFastCounter.class); } @@ -146,96 +197,10 @@ public MutableGaugeLong newGauge(String name, String desc, long iVal) { * @return a new gauge object */ public MutableGaugeLong newGauge(MetricsInfo info, long iVal) { - MutableGaugeLong ret = new MutableGaugeLong(info, iVal); + MutableGaugeLong ret = super.newGauge(info, iVal); return addNewMetricIfAbsent(info.name(), ret, MutableGaugeLong.class); } - /** - * Create a mutable metric with stats - * @param name of the metric - * @param desc metric description - * @param sampleName of the metric (e.g., "Ops") - * @param valueName of the metric (e.g., "Time" or "Latency") - * @param extended produce extended stat (stdev, min/max etc.) if true. - * @return a new mutable stat metric object - */ - public MutableStat newStat(String name, String desc, - String sampleName, String valueName, boolean extended) { - MutableStat ret = - new MutableStat(name, desc, sampleName, valueName, extended); - return addNewMetricIfAbsent(name, ret, MutableStat.class); - } - - /** - * Create a mutable metric with stats - * @param name of the metric - * @param desc metric description - * @param sampleName of the metric (e.g., "Ops") - * @param valueName of the metric (e.g., "Time" or "Latency") - * @return a new mutable metric object - */ - public MutableStat newStat(String name, String desc, - String sampleName, String valueName) { - return newStat(name, desc, sampleName, valueName, false); - } - - /** - * Create a mutable rate metric - * @param name of the metric - * @return a new mutable metric object - */ - public MutableRate newRate(String name) { - return newRate(name, name, false); - } - - /** - * Create a mutable rate metric - * @param name of the metric - * @param description of the metric - * @return a new mutable rate metric object - */ - public MutableRate newRate(String name, String description) { - return newRate(name, description, false); - } - - /** - * Create a mutable rate metric (for throughput measurement) - * @param name of the metric - * @param desc description - * @param extended produce extended stat (stdev/min/max etc.) if true - * @return a new mutable rate metric object - */ - public MutableRate newRate(String name, String desc, boolean extended) { - return newRate(name, desc, extended, true); - } - - @InterfaceAudience.Private - public MutableRate newRate(String name, String desc, - boolean extended, boolean returnExisting) { - if (returnExisting) { - MutableMetric rate = metricsMap.get(name); - if (rate != null) { - if (rate instanceof MutableRate) { - return (MutableRate) rate; - } - - throw new MetricsException("Unexpected metrics type "+ rate.getClass() - +" for "+ name); - } - } - MutableRate ret = new MutableRate(name, desc, extended); - return addNewMetricIfAbsent(name, ret, MutableRate.class); - } - - /** - * Create a new histogram. - * @param name Name of the histogram. - * @return A new MutableHistogram - */ - public MutableHistogram newHistogram(String name) { - return newHistogram(name, ""); - } - /** * Create a new histogram. * @param name The name of the histogram @@ -243,7 +208,7 @@ public MutableHistogram newHistogram(String name) { * @return A new MutableHistogram */ public MutableHistogram newHistogram(String name, String desc) { - MutableHistogram histo = new MutableHistogram(name, desc); + MutableHistogram histo = super.newHistogram(name, desc); return addNewMetricIfAbsent(name, histo, MutableHistogram.class); } @@ -263,10 +228,10 @@ public MutableTimeHistogram newTimeHistogram(String name) { * @return A new MutableTimeHistogram */ public MutableTimeHistogram newTimeHistogram(String name, String desc) { - MutableTimeHistogram histo = new MutableTimeHistogram(name, desc); + MutableTimeHistogram histo = super.newTimeHistogram(name, desc); return addNewMetricIfAbsent(name, histo, MutableTimeHistogram.class); } - + /** * Create a new histogram with size range counts. * @param name Name of the histogram. @@ -283,37 +248,10 @@ public MutableSizeHistogram newSizeHistogram(String name) { * @return A new MutableSizeHistogram */ public MutableSizeHistogram newSizeHistogram(String name, String desc) { - MutableSizeHistogram histo = new MutableSizeHistogram(name, desc); + MutableSizeHistogram histo = super.newSizeHistogram(name, desc); return addNewMetricIfAbsent(name, histo, MutableSizeHistogram.class); } - - synchronized void add(String name, MutableMetric metric) { - addNewMetricIfAbsent(name, metric, MutableMetric.class); - } - - /** - * Add sample to a stat metric by name. - * @param name of the metric - * @param value of the snapshot to add - */ - public void add(String name, long value) { - MutableMetric m = metricsMap.get(name); - - if (m != null) { - if (m instanceof MutableStat) { - ((MutableStat) m).add(value); - } - else { - throw new MetricsException("Unsupported add(value) for metric "+ name); - } - } - else { - metricsMap.put(name, newRate(name)); // default is a rate metric - add(name, value); - } - } - /** * Set the metrics context tag * @param name of the context @@ -396,6 +334,25 @@ public void snapshot(MetricsRecordBuilder builder, boolean all) { } } + /** + * Sample all the scoped metrics for a given scope and put the snapshot in the builder. + * @param scope scope to snapshot + * @param builder to contain the metrics snapshot + * @param all get all the metrics even if the values are not changed. + */ + public void snapshotScoped(String scope, MetricsRecordBuilder builder, boolean all) { + for (MetricsTag tag : tags()) { + builder.add(tag); + } + ConcurrentMap map = scopedMetricsMap.getOrDefault(scope, null); + if (map == null) { + return; + } + for (MutableMetric metric : map.values()) { + metric.snapshot(builder, all); + } + } + @Override public String toString() { return MoreObjects.toStringHelper(this) .add("info", metricsInfo).add("tags", tags()).add("metrics", metrics()) @@ -502,10 +459,15 @@ public MutableHistogram getHistogram(String histoName) { private T addNewMetricIfAbsent(String name, T ret, Class metricClass) { + return addNewMetricToMapIfAbsent(metricsMap, name, ret, metricClass); + } + + private static T addNewMetricToMapIfAbsent( + ConcurrentMap map, String name, T ret, Class metricClass) { //If the value we get back is null then the put was successful and we will // return that. Otherwise metric should contain the thing that was in // before the put could be completed. - MutableMetric metric = metricsMap.putIfAbsent(name, ret); + MutableMetric metric = map.putIfAbsent(name, ret); if (metric == null) { return ret; } @@ -513,8 +475,16 @@ private T addNewMetricIfAbsent(String name, T ret, return returnExistingWithCast(metric, metricClass, name); } + + private T addNewScopedMetricIfAbsent( + String scope, String name, T ret, Class metricClass) { + ConcurrentMap map = scopedMetricsMap.computeIfAbsent( + scope, k -> Maps.newConcurrentMap()); + return addNewMetricToMapIfAbsent(map, name, ret, metricClass); + } + @SuppressWarnings("unchecked") - private T returnExistingWithCast(MutableMetric metric, + private static T returnExistingWithCast(MutableMetric metric, Class metricClass, String name) { if (!metricClass.isAssignableFrom(metric.getClass())) { throw new MetricsException("Metric already exists in registry for metric name: " + diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MetricsFactory.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MetricsFactory.java new file mode 100644 index 000000000000..0e6a2c7b36a1 --- /dev/null +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MetricsFactory.java @@ -0,0 +1,95 @@ +/** + * 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.metrics2.lib; + +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.yetus.audience.InterfaceAudience; + + +/** + * A superclass of DynamicMetricsRegistry that creates metrics. + * Needed for tags-based metrics to be able to create some metrics without registering them for + * snapshots; and without having tons of null checks and copy-paste everywhere. + * For this to be better, table, region and server metrics that are the same should be all + * managed in one place, and in the same manner (see TO-DOs elsewhere). + */ +@InterfaceAudience.Private +public class MetricsFactory { + + /** + * Create a mutable long integer counter + * @param name of the metric + * @param desc metric description + * @param iVal initial value + * @return a new counter object + */ + public MutableFastCounter newCounter(String name, String desc, long iVal) { + return new MutableFastCounter(new MetricsInfoImpl(name, desc), iVal); + } + + /** + * Create a mutable long integer counter + * @param info metadata of the metric + * @param iVal initial value + * @return a new counter object + */ + public MutableFastCounter newCounter(MetricsInfo info, long iVal) { + return new MutableFastCounter(info, iVal); + } + + /** + * Create a mutable long integer gauge + * @param info metadata of the metric + * @param iVal initial value + * @return a new gauge object + */ + public MutableGaugeLong newGauge(MetricsInfo info, long iVal) { + return new MutableGaugeLong(info, iVal); + } + + /** + * Create a new histogram. + * @param name The name of the histogram + * @param desc The description of the data in the histogram. + * @return A new MutableHistogram + */ + public MutableHistogram newHistogram(String name, String desc) { + return new MutableHistogram(name, desc); + } + + /** + * Create a new histogram with time range counts. + * @param name The name of the histogram + * @param desc The description of the data in the histogram. + * @return A new MutableTimeHistogram + */ + public MutableTimeHistogram newTimeHistogram(String name, String desc) { + return new MutableTimeHistogram(name, desc); + } + + /** + * Create a new histogram with size range counts. + * @param name The name of the histogram + * @param desc The description of the data in the histogram. + * @return A new MutableSizeHistogram + */ + public MutableSizeHistogram newSizeHistogram(String name, String desc) { + return new MutableSizeHistogram(name, desc); + } +} diff --git a/hbase-hadoop2-compat/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperStub.java b/hbase-hadoop2-compat/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperStub.java index 01d914e38ed0..2c4c48d948b9 100644 --- a/hbase-hadoop2-compat/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperStub.java +++ b/hbase-hadoop2-compat/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperStub.java @@ -18,6 +18,8 @@ package org.apache.hadoop.hbase.regionserver; +import org.apache.hadoop.conf.Configuration; + public class MetricsTableWrapperStub implements MetricsTableWrapperAggregate { private String tableName; @@ -100,6 +102,11 @@ public long getNumReferenceFiles(String table) { return 77; } + @Override + public Configuration getConf() { + return null; + } + @Override public long getAvgRegionSize(String table) { return 88; 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 21534cedb10c..cf4e5cc9dc46 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 @@ -27,6 +27,8 @@ import org.apache.yetus.audience.InterfaceStability; import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** *

@@ -39,15 +41,14 @@ @InterfaceStability.Evolving @InterfaceAudience.Private public class MetricsRegionServer { - public static final String RS_ENABLE_TABLE_METRICS_KEY = - "hbase.regionserver.enable.table.latencies"; - public static final boolean RS_ENABLE_TABLE_METRICS_DEFAULT = true; + private static final Logger LOG = LoggerFactory.getLogger(MetricsRegionServer.class); private MetricsRegionServerSource serverSource; private MetricsRegionServerWrapper regionServerWrapper; private RegionServerTableMetrics tableMetrics; private final MetricsTable metricsTable; private MetricsRegionServerQuotaSource quotaSource; + private final Mode modeForTableMetrics, modeForMetricsTable; // See ctor comment. private MetricRegistry metricRegistry; private Timer bulkLoadTimer; @@ -70,6 +71,12 @@ public MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper, Confi quotaSource = CompatibilitySingletonFactory.getInstance(MetricsRegionServerQuotaSource.class); } + private enum Mode { + TABLE, + SERVER, + BOTH + } + MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper, MetricsRegionServerSource serverSource, RegionServerTableMetrics tableMetrics, @@ -78,14 +85,19 @@ public MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper, Confi this.serverSource = serverSource; this.tableMetrics = tableMetrics; this.metricsTable = metricsTable; + // This is ugly, but that's how it is. We have tableMetrics, and metricsTable... + this.modeForTableMetrics = (tableMetrics == null) ? Mode.SERVER + : (tableMetrics.isScoped() ? Mode.TABLE : Mode.BOTH); + this.modeForMetricsTable = (metricsTable == null) ? Mode.SERVER + : (metricsTable.isScoped() ? Mode.TABLE : Mode.BOTH); } /** * Creates an instance of {@link RegionServerTableMetrics} only if the feature is enabled. */ static RegionServerTableMetrics createTableMetrics(Configuration conf) { - if (conf.getBoolean(RS_ENABLE_TABLE_METRICS_KEY, RS_ENABLE_TABLE_METRICS_DEFAULT)) { - return new RegionServerTableMetrics(); + if (MetricsTableSourceImpl.areTableLatenciesEnabled(conf)) { + return new RegionServerTableMetrics(conf); } return null; } @@ -99,139 +111,294 @@ public MetricsRegionServerWrapper getRegionServerWrapper() { return regionServerWrapper; } + /** + * Basically checks table name object for nulls. + * TODO: why would we ever have nulls if per-table is on? + */ + private static Mode deriveMode(Mode mode, Object tn) { + return tn == null ? Mode.SERVER : mode; + } + public void updatePutBatch(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updatePut(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updatePutBatch(tn, t); + break; + case SERVER: + serverSource.updatePutBatch(t); + break; + case BOTH: + tableMetrics.updatePutBatch(tn, t); + serverSource.updatePutBatch(t); + break; } + if (t > 1000) { serverSource.incrSlowPut(); } - serverSource.updatePutBatch(t); } public void updatePut(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updatePut(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updatePut(tn, t); + break; + case SERVER: + serverSource.updatePut(t); + break; + case BOTH: + tableMetrics.updatePut(tn, t); + serverSource.updatePut(t); + break; } - serverSource.updatePut(t); } public void updateDelete(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updateDelete(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateDelete(tn, t); + break; + case SERVER: + serverSource.updateDelete(t); + break; + case BOTH: + tableMetrics.updateDelete(tn, t); + serverSource.updateDelete(t); + break; } - serverSource.updateDelete(t); } public void updateDeleteBatch(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updateDelete(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateDeleteBatch(tn, t); + break; + case SERVER: + serverSource.updateDeleteBatch(t); + break; + case BOTH: + tableMetrics.updateDeleteBatch(tn, t); + serverSource.updateDeleteBatch(t); + break; } if (t > 1000) { serverSource.incrSlowDelete(); } - serverSource.updateDeleteBatch(t); } public void updateCheckAndDelete(long t) { + // TODO: add to table metrics? serverSource.updateCheckAndDelete(t); } public void updateCheckAndPut(long t) { + // TODO: add to table metrics? serverSource.updateCheckAndPut(t); } public void updateGet(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updateGet(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateGet(tn, t); + break; + case SERVER: + serverSource.updateGet(t); + break; + case BOTH: + tableMetrics.updateGet(tn, t); + serverSource.updateGet(t); + break; } if (t > 1000) { serverSource.incrSlowGet(); } - serverSource.updateGet(t); } public void updateIncrement(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updateIncrement(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateIncrement(tn, t); + break; + case SERVER: + serverSource.updateIncrement(t); + break; + case BOTH: + tableMetrics.updateIncrement(tn, t); + serverSource.updateIncrement(t); + break; } if (t > 1000) { serverSource.incrSlowIncrement(); } - serverSource.updateIncrement(t); } public void updateAppend(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updateAppend(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateAppend(tn, t); + break; + case SERVER: + serverSource.updateAppend(t); + break; + case BOTH: + tableMetrics.updateAppend(tn, t); + serverSource.updateAppend(t); + break; } if (t > 1000) { serverSource.incrSlowAppend(); } - serverSource.updateAppend(t); } - public void updateReplay(long t){ + public void updateReplay(long t) { + // TODO: add to table metrics? serverSource.updateReplay(t); } - public void updateScanSize(TableName tn, long scanSize){ - if (tableMetrics != null && tn != null) { - tableMetrics.updateScanSize(tn, scanSize); + public void updateScanSize(TableName tn, long scanSize) { + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateScanSize(tn, scanSize); + break; + case SERVER: + serverSource.updateScanSize(scanSize); + break; + case BOTH: + tableMetrics.updateScanSize(tn, scanSize); + serverSource.updateScanSize(scanSize); + break; } - serverSource.updateScanSize(scanSize); } public void updateScanTime(TableName tn, long t) { - if (tableMetrics != null && tn != null) { - tableMetrics.updateScanTime(tn, t); + switch (deriveMode(modeForTableMetrics, tn)) { + case TABLE: + tableMetrics.updateScanTime(tn, t); + break; + case SERVER: + serverSource.updateScanTime(t); + break; + case BOTH: + tableMetrics.updateScanTime(tn, t); + serverSource.updateScanTime(t); + break; } - serverSource.updateScanTime(t); } - public void updateSplitTime(long t) { - serverSource.updateSplitTime(t); + // TODO: never called + public void updateSplitTime(String tn, long t) { + switch (deriveMode(modeForMetricsTable, tn)) { + case TABLE: + metricsTable.updateSplitTime(tn, t); + break; + case SERVER: + serverSource.updateScanTime(t); + break; + case BOTH: + metricsTable.updateSplitTime(tn, t); + serverSource.updateSplitTime(t); + break; + } } - public void incrSplitRequest() { - serverSource.incrSplitRequest(); + public void incrSplitRequest(String tn) { + switch (deriveMode(modeForMetricsTable, tn)) { + case TABLE: + metricsTable.incrSplitRequest(tn); + break; + case SERVER: + serverSource.incrSplitRequest(); + break; + case BOTH: + metricsTable.incrSplitRequest(tn); + serverSource.incrSplitRequest(); + break; + } } - public void incrSplitSuccess() { - serverSource.incrSplitSuccess(); + // TODO: never called + public void incrSplitSuccess(String tn) { + switch (deriveMode(modeForMetricsTable, tn)) { + case TABLE: + metricsTable.incrSplitSuccess(tn); + break; + case SERVER: + serverSource.incrSplitSuccess(); + break; + case BOTH: + metricsTable.incrSplitSuccess(tn); + serverSource.incrSplitSuccess(); + break; + } } public void updateFlush(String table, long t, long memstoreSize, long fileSize) { + switch (deriveMode(modeForMetricsTable, table)) { + case TABLE: + updateFlushTbl(table, t, memstoreSize, fileSize); + break; + case SERVER: + updateFlushSrv(t, memstoreSize, fileSize); + break; + case BOTH: + updateFlushTbl(table, t, memstoreSize, fileSize); + updateFlushSrv(t, memstoreSize, fileSize); + break; + } + } + + private void updateFlushSrv(long t, long memstoreSize, long fileSize) { serverSource.updateFlushTime(t); serverSource.updateFlushMemStoreSize(memstoreSize); serverSource.updateFlushOutputSize(fileSize); + } - if (table != null) { - metricsTable.updateFlushTime(table, memstoreSize); - metricsTable.updateFlushMemstoreSize(table, memstoreSize); - metricsTable.updateFlushOutputSize(table, fileSize); + private void updateFlushTbl(String table, long t, long memstoreSize, long fileSize) { + metricsTable.updateFlushTime(table, t); + metricsTable.updateFlushMemstoreSize(table, memstoreSize); + metricsTable.updateFlushOutputSize(table, fileSize); + } + + public void updateCompaction(String table, boolean isMajor, long t, int inputFileCount, + int outputFileCount, long inputBytes, long outputBytes) { + switch (deriveMode(modeForMetricsTable, table)) { + case TABLE: + updateCompactionTbl(table, isMajor, t, inputFileCount, + outputFileCount, inputBytes, outputBytes); + break; + case SERVER: + updateCompactionSrv(isMajor, t, inputFileCount, + outputFileCount, inputBytes, outputBytes); + break; + case BOTH: + updateCompactionTbl(table, isMajor, t, inputFileCount, + outputFileCount, inputBytes, outputBytes); + updateCompactionSrv(isMajor, t, inputFileCount, + outputFileCount, inputBytes, outputBytes); + break; } + } + private void updateCompactionTbl(String table, boolean isMajor, long t, int inputFileCount, + int outputFileCount, long inputBytes, long outputBytes) { + metricsTable.updateCompactionTime(table, isMajor, t); + metricsTable.updateCompactionInputFileCount(table, isMajor, inputFileCount); + metricsTable.updateCompactionOutputFileCount(table, isMajor, outputFileCount); + metricsTable.updateCompactionInputSize(table, isMajor, inputBytes); + metricsTable.updateCompactionOutputSize(table, isMajor, outputBytes); } - public void updateCompaction(String table, boolean isMajor, long t, int inputFileCount, int outputFileCount, - long inputBytes, long outputBytes) { + private void updateCompactionSrv(boolean isMajor, long t, int inputFileCount, + int outputFileCount, long inputBytes, long outputBytes) { serverSource.updateCompactionTime(isMajor, t); serverSource.updateCompactionInputFileCount(isMajor, inputFileCount); serverSource.updateCompactionOutputFileCount(isMajor, outputFileCount); serverSource.updateCompactionInputSize(isMajor, inputBytes); serverSource.updateCompactionOutputSize(isMajor, outputBytes); - - if (table != null) { - metricsTable.updateCompactionTime(table, isMajor, t); - metricsTable.updateCompactionInputFileCount(table, isMajor, inputFileCount); - metricsTable.updateCompactionOutputFileCount(table, isMajor, outputFileCount); - metricsTable.updateCompactionInputSize(table, isMajor, inputBytes); - metricsTable.updateCompactionOutputSize(table, isMajor, outputBytes); - } } public void updateBulkLoad(long millis) { + // TODO: add to table metrics? this.bulkLoadTimer.updateMillis(millis); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperImpl.java index 33a6ee0ee280..0719db69b988 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperImpl.java @@ -1006,4 +1006,9 @@ public long getDeleteFamilyBloomHitCount() { public long getTrailerHitCount() { return this.cacheStats.map(CacheStats::getTrailerHitCount).orElse(0L); } + + @Override + public String getConfVar(String name, String defaultValue) { + return regionServer.getConfiguration().get(name, defaultValue); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTable.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTable.java index a3f0dff6b993..0f293691a99b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTable.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTable.java @@ -87,4 +87,8 @@ public void updateCompactionOutputSize(String table, boolean isMajor, long bytes tableSourceAgg.getOrCreateTableSource(table, wrapper) .updateCompactionOutputSize(isMajor, bytes); } + + public boolean isScoped() { + return MetricsTableAggregateSourceImpl.areTablesViaTags(wrapper); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregateImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregateImpl.java index 6b97390d2327..20abd217c65e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregateImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableWrapperAggregateImpl.java @@ -20,14 +20,19 @@ import java.io.Closeable; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.OptionalDouble; +import java.util.OptionalLong; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.CompatibilitySingletonFactory; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; @@ -36,8 +41,13 @@ import org.apache.hbase.thirdparty.com.google.common.collect.Sets; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + @InterfaceAudience.Private public class MetricsTableWrapperAggregateImpl implements MetricsTableWrapperAggregate, Closeable { + private static final Logger LOG = LoggerFactory.getLogger(MetricsTableWrapperAggregateImpl.class); + private final HRegionServer regionServer; private ScheduledExecutorService executor; private Runnable runnable; @@ -60,58 +70,72 @@ public class TableMetricsWrapperRunnable implements Runnable { @Override public void run() { + LOG.debug("Starting to publish the table metrics"); Map localMetricsTableMap = new HashMap<>(); - for (Region r : regionServer.getOnlineRegionsLocalContext()) { - TableName tbl = r.getTableDescriptor().getTableName(); - MetricsTableValues mt = localMetricsTableMap.get(tbl); - if (mt == null) { - mt = new MetricsTableValues(); - localMetricsTableMap.put(tbl, mt); - } - if (r.getStores() != null) { - for (Store store : r.getStores()) { - mt.storeFileCount += store.getStorefilesCount(); - mt.memstoreSize += (store.getMemStoreSize().getDataSize() + - store.getMemStoreSize().getHeapSize() + store.getMemStoreSize().getOffHeapSize()); - mt.storeFileSize += store.getStorefilesSize(); - mt.referenceFileCount += store.getNumReferenceFiles(); - - mt.maxStoreFileAge = Math.max(mt.maxStoreFileAge, store.getMaxStoreFileAge().getAsLong()); - mt.minStoreFileAge = Math.min(mt.minStoreFileAge, store.getMinStoreFileAge().getAsLong()); - mt.totalStoreFileAge = (long)store.getAvgStoreFileAge().getAsDouble() * - store.getStorefilesCount(); - mt.storeCount += 1; + try { + for (Region r : regionServer.getOnlineRegionsLocalContext()) { + TableName tbl = r.getTableDescriptor().getTableName(); + MetricsTableValues mt = localMetricsTableMap.get(tbl); + if (mt == null) { + mt = new MetricsTableValues(); + localMetricsTableMap.put(tbl, mt); + } + mt.cpRequestCount += r.getCpRequestsCount(); + if (r.getStores() != null) { + for (Store store : r.getStores()) { + mt.storeFileCount += store.getStorefilesCount(); + mt.memstoreSize += (store.getMemStoreSize().getDataSize() + + store.getMemStoreSize().getHeapSize() + store.getMemStoreSize().getOffHeapSize()); + mt.storeFileSize += store.getStorefilesSize(); + mt.referenceFileCount += store.getNumReferenceFiles(); + + OptionalLong ol = store.getMaxStoreFileAge(); + if (ol.isPresent()) { + mt.maxStoreFileAge = Math.max(mt.maxStoreFileAge, ol.getAsLong()); + } + ol = store.getMaxStoreFileAge(); + if (ol.isPresent()) { + mt.minStoreFileAge = Math.max(mt.minStoreFileAge, ol.getAsLong()); + } + OptionalDouble od = store.getAvgStoreFileAge(); + if (od.isPresent()) { + mt.totalStoreFileAge = (long)od.getAsDouble() * store.getStorefilesCount(); + } + mt.storeCount += 1; + } + mt.regionCount += 1; + + mt.readRequestCount += r.getReadRequestsCount(); + mt.filteredReadRequestCount += r.getFilteredReadRequestsCount(); + mt.writeRequestCount += r.getWriteRequestsCount(); } - mt.regionCount += 1; - - mt.readRequestCount += r.getReadRequestsCount(); - mt.filteredReadRequestCount += getFilteredReadRequestCount(tbl.getNameAsString()); - mt.writeRequestCount += r.getWriteRequestsCount(); - } - } - for (Map.Entry entry : localMetricsTableMap.entrySet()) { - TableName tbl = entry.getKey(); - if (metricsTableMap.get(tbl) == null) { - // this will add the Wrapper to the list of TableMetrics - CompatibilitySingletonFactory - .getInstance(MetricsRegionServerSourceFactory.class) - .getTableAggregate() - .getOrCreateTableSource(tbl.getNameAsString(), MetricsTableWrapperAggregateImpl.this); + for (Map.Entry entry : localMetricsTableMap.entrySet()) { + TableName tbl = entry.getKey(); + if (metricsTableMap.get(tbl) == null) { + // this will add the Wrapper to the list of TableMetrics + CompatibilitySingletonFactory + .getInstance(MetricsRegionServerSourceFactory.class) + .getTableAggregate() + .getOrCreateTableSource(tbl.getNameAsString(), MetricsTableWrapperAggregateImpl.this); + } + metricsTableMap.put(entry.getKey(), entry.getValue()); } - metricsTableMap.put(entry.getKey(), entry.getValue()); - } - Set existingTableNames = Sets.newHashSet(metricsTableMap.keySet()); - existingTableNames.removeAll(localMetricsTableMap.keySet()); - MetricsTableAggregateSource agg = CompatibilitySingletonFactory - .getInstance(MetricsRegionServerSourceFactory.class).getTableAggregate(); - for (TableName table : existingTableNames) { - agg.deleteTableSource(table.getNameAsString()); - if (metricsTableMap.get(table) != null) { - metricsTableMap.remove(table); + Set existingTableNames = Sets.newHashSet(metricsTableMap.keySet()); + existingTableNames.removeAll(localMetricsTableMap.keySet()); + MetricsTableAggregateSource agg = CompatibilitySingletonFactory + .getInstance(MetricsRegionServerSourceFactory.class).getTableAggregate(); + for (TableName table : existingTableNames) { + agg.deleteTableSource(table.getNameAsString()); + if (metricsTableMap.get(table) != null) { + metricsTableMap.remove(table); + } } + } catch (Exception e) { + // Don't let it fail or it will never run again... + LOG.warn("Metrics publishing task has failed; ignoring the failure", e); } } } @@ -278,6 +302,11 @@ public long getCpRequestCount(String table) { return metricsTable.cpRequestCount; } + @Override + public Configuration getConf() { + return regionServer.conf; + } + @Override public void close() throws IOException { tableMetricsUpdateTask.cancel(true); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerTableMetrics.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerTableMetrics.java index 652a06201481..f2686db22ea5 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerTableMetrics.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerTableMetrics.java @@ -16,6 +16,7 @@ */ package org.apache.hadoop.hbase.regionserver; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.CompatibilitySingletonFactory; import org.apache.hadoop.hbase.TableName; import org.apache.yetus.audience.InterfaceAudience; @@ -23,14 +24,20 @@ /** * Captures operation metrics by table. Separates metrics collection for table metrics away from * {@link MetricsRegionServer} for encapsulation and ease of testing. + * TODO: why does this use a different flow from very similar, other per-table metrics? */ @InterfaceAudience.Private public class RegionServerTableMetrics { private final MetricsTableLatencies latencies; - public RegionServerTableMetrics() { + public RegionServerTableMetrics(Configuration conf) { latencies = CompatibilitySingletonFactory.getInstance(MetricsTableLatencies.class); + // Unlike the other table counters, this doesn't give us an opportunity to supply config + // after we get the object from CompatibilitySingletonFactory... + if (latencies instanceof MetricsTableLatenciesImpl) { + ((MetricsTableLatenciesImpl)latencies).setConf(conf); + } } public void updatePut(TableName table, long time) { @@ -68,4 +75,8 @@ public void updateScanTime(TableName table, long time) { public void updateScanSize(TableName table, long size) { latencies.updateScanSize(table.getNameAsString(), size); } + + public boolean isScoped() { + return latencies.isScoped(); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitRequest.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitRequest.java index 9e806bb6117d..e32c260600fe 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitRequest.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/SplitRequest.java @@ -59,7 +59,7 @@ public String toString() { } private void doSplitting() { - server.metricsRegionServer.incrSplitRequest(); + server.metricsRegionServer.incrSplitRequest(parent.getTable().getNameAsString()); if (user != null && user.getUGI() != null) { user.getUGI().doAs (new PrivilegedAction() { @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.java index b003b4452490..2476314b3031 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.java @@ -579,4 +579,9 @@ public double getMobFileCacheHitPercent() { public long getAverageRegionSize() { return 10000000; } + + @Override + public String getConfVar(String name, String defaultValue) { + return null; + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableLatencies.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableLatencies.java index 43e8d58564f1..05016355c304 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableLatencies.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMetricsTableLatencies.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.CompatibilityFactory; import org.apache.hadoop.hbase.CompatibilitySingletonFactory; import org.apache.hadoop.hbase.HBaseClassTestRule; @@ -50,7 +51,7 @@ public void testTableWrapperAggregateMetrics() throws IOException { assertTrue("'latencies' is actually " + latencies.getClass(), latencies instanceof MetricsTableLatenciesImpl); MetricsTableLatenciesImpl latenciesImpl = (MetricsTableLatenciesImpl) latencies; - RegionServerTableMetrics tableMetrics = new RegionServerTableMetrics(); + RegionServerTableMetrics tableMetrics = new RegionServerTableMetrics(new Configuration()); // Metrics to each table should be disjoint // N.B. each call to assertGauge removes all previously acquired metrics so we have to