/*
* Copyright The Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.apache.hadoop.hbase.regionserver.metrics;
import static org.apache.hadoop.hbase.regionserver.metrics.SchemaMetrics.
BOOL_VALUES;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.MediumTests;
import org.apache.hadoop.hbase.io.hfile.BlockType;
import org.apache.hadoop.hbase.io.hfile.BlockType.BlockCategory;
import org.apache.hadoop.hbase.regionserver.metrics.SchemaMetrics.
BlockMetricType;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ClassSize;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@Category(MediumTests.class)
@RunWith(Parameterized.class)
public class TestSchemaMetrics {
private final String TABLE_NAME = "myTable";
private final String CF_NAME = "myColumnFamily";
private final boolean useTableName;
private Map<String, Long> startingMetrics;
@Parameters
public static Collection<Object[]> parameters() {
return HBaseTestingUtility.BOOLEAN_PARAMETERIZED;
}
public TestSchemaMetrics(boolean useTableName) {
this.useTableName = useTableName;
SchemaMetrics.setUseTableNameInTest(useTableName);
}
@Before
public void setUp() {
startingMetrics = SchemaMetrics.getMetricsSnapshot();
};
@Test
public void testNaming() {
final String metricPrefix = (useTableName ? "tbl." +
TABLE_NAME + "." : "") + "cf." + CF_NAME + ".";
SchemaMetrics schemaMetrics = SchemaMetrics.getInstance(TABLE_NAME,
CF_NAME);
SchemaMetrics ALL_CF_METRICS = SchemaMetrics.ALL_SCHEMA_METRICS;
// fsReadTimeMetric
assertEquals(metricPrefix + "fsRead", schemaMetrics.getBlockMetricName(
BlockCategory.ALL_CATEGORIES, false, BlockMetricType.READ_TIME));
// compactionReadTimeMetric
assertEquals(metricPrefix + "compactionRead",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, true,
BlockMetricType.READ_TIME));
// fsBlockReadCntMetric
assertEquals(metricPrefix + "fsBlockReadCnt",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, false,
BlockMetricType.READ_COUNT));
// fsBlockReadCacheHitCntMetric
assertEquals(metricPrefix + "fsBlockReadCacheHitCnt",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, false,
BlockMetricType.CACHE_HIT));
// fsBlockReadCacheMissCntMetric
assertEquals(metricPrefix + "fsBlockReadCacheMissCnt",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, false,
BlockMetricType.CACHE_MISS));
// compactionBlockReadCntMetric
assertEquals(metricPrefix + "compactionBlockReadCnt",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, true,
BlockMetricType.READ_COUNT));
// compactionBlockReadCacheHitCntMetric
assertEquals(metricPrefix + "compactionBlockReadCacheHitCnt",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, true,
BlockMetricType.CACHE_HIT));
// compactionBlockReadCacheMissCntMetric
assertEquals(metricPrefix + "compactionBlockReadCacheMissCnt",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, true,
BlockMetricType.CACHE_MISS));
// fsMetaBlockReadCntMetric
assertEquals("fsMetaBlockReadCnt", ALL_CF_METRICS.getBlockMetricName(
BlockCategory.META, false, BlockMetricType.READ_COUNT));
// fsMetaBlockReadCacheHitCntMetric
assertEquals("fsMetaBlockReadCacheHitCnt",
ALL_CF_METRICS.getBlockMetricName(BlockCategory.META, false,
BlockMetricType.CACHE_HIT));
// fsMetaBlockReadCacheMissCntMetric
assertEquals("fsMetaBlockReadCacheMissCnt",
ALL_CF_METRICS.getBlockMetricName(BlockCategory.META, false,
BlockMetricType.CACHE_MISS));
// Per-(column family, block type) statistics.
assertEquals(metricPrefix + "bt.Index.fsBlockReadCnt",
schemaMetrics.getBlockMetricName(BlockCategory.INDEX, false,
BlockMetricType.READ_COUNT));
assertEquals(metricPrefix + "bt.Data.compactionBlockReadCacheHitCnt",
schemaMetrics.getBlockMetricName(BlockCategory.DATA, true,
BlockMetricType.CACHE_HIT));
// A special case for Meta blocks
assertEquals(metricPrefix + "compactionMetaBlockReadCacheHitCnt",
schemaMetrics.getBlockMetricName(BlockCategory.META, true,
BlockMetricType.CACHE_HIT));
// Cache metrics
assertEquals(metricPrefix + "blockCacheSize",
schemaMetrics.getBlockMetricName(BlockCategory.ALL_CATEGORIES, false,
BlockMetricType.CACHE_SIZE));
assertEquals(metricPrefix + "bt.Index.blockCacheNumEvicted",
schemaMetrics.getBlockMetricName(BlockCategory.INDEX, false,
BlockMetricType.EVICTED));
assertEquals("bt.Data.blockCacheNumCached",
ALL_CF_METRICS.getBlockMetricName(BlockCategory.DATA, false,
BlockMetricType.CACHED));
assertEquals("blockCacheNumCached", ALL_CF_METRICS.getBlockMetricName(
BlockCategory.ALL_CATEGORIES, false, BlockMetricType.CACHED));
// "Non-compaction aware" metrics
try {
ALL_CF_METRICS.getBlockMetricName(BlockCategory.ALL_CATEGORIES, true,
BlockMetricType.CACHE_SIZE);
fail("Exception expected");
} catch (IllegalArgumentException ex) {
}
// Bloom metrics
assertEquals("keyMaybeInBloomCnt", ALL_CF_METRICS.getBloomMetricName(true));
assertEquals(metricPrefix + "keyNotInBloomCnt",
schemaMetrics.getBloomMetricName(false));
schemaMetrics.printMetricNames();
}
public void checkMetrics() {
SchemaMetrics.validateMetricChanges(startingMetrics);
}
@Test
public void testIncrements() {
Random rand = new Random(23982737L);
for (int i = 1; i <= 3; ++i) {
final String tableName = "table" + i;
for (int j = 1; j <= 3; ++j) {
final String cfName = "cf" + j;
SchemaMetrics sm = SchemaMetrics.getInstance(tableName, cfName);
for (boolean isInBloom : BOOL_VALUES) {
sm.updateBloomMetrics(isInBloom);
checkMetrics();
}
for (BlockCategory blockCat : BlockType.BlockCategory.values()) {
if (blockCat == BlockCategory.ALL_CATEGORIES) {
continue;
}
for (boolean isCompaction : BOOL_VALUES) {
sm.updateOnCacheHit(blockCat, isCompaction);
checkMetrics();
sm.updateOnCacheMiss(blockCat, isCompaction, rand.nextInt());
checkMetrics();
}
for (boolean isEviction : BOOL_VALUES) {
sm.updateOnCachePutOrEvict(blockCat, (isEviction ? -1 : 1)
* rand.nextInt(1024 * 1024), isEviction);
}
}
}
}
}
@Test
public void testGenerateSchemaMetricsPrefix() {
String tableName = "table1";
int numCF = 3;
StringBuilder expected = new StringBuilder();
if (useTableName) {
expected.append("tbl.");
expected.append(tableName);
expected.append(".");
}
expected.append("cf.");
Set<byte[]> families = new HashSet<byte[]>();
for (int i = 1; i <= numCF; i++) {
String cf = "cf" + i;
families.add(Bytes.toBytes(cf));
expected.append(cf);
if (i == numCF) {
expected.append(".");
} else {
expected.append("~");
}
}
String result = SchemaMetrics.generateSchemaMetricsPrefix(tableName,
families);
assertEquals(expected.toString(), result);
}
@org.junit.Rule
public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
}