001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertTrue; 022 023import com.codahale.metrics.Timer; 024import java.io.IOException; 025import java.util.Arrays; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.HBaseConfiguration; 029import org.apache.hadoop.hbase.HBaseTestingUtility; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.hadoop.hbase.testclassification.MediumTests; 032import org.apache.hadoop.hbase.util.Bytes; 033import org.junit.AfterClass; 034import org.junit.BeforeClass; 035import org.junit.ClassRule; 036import org.junit.Test; 037import org.junit.experimental.categories.Category; 038 039import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.ClientService; 040 041@Category(MediumTests.class) 042public class TestClientTableMetrics { 043 044 @ClassRule 045 public static final HBaseClassTestRule CLASS_RULE = 046 HBaseClassTestRule.forClass(TestClientTableMetrics.class); 047 048 private static HBaseTestingUtility UTIL; 049 private static Connection CONN; 050 private static MetricsConnection METRICS; 051 private static final String tableName = "table_1"; 052 private static final TableName TABLE_1 = TableName.valueOf(tableName); 053 private static final byte[] FAMILY = Bytes.toBytes("f"); 054 055 @BeforeClass 056 public static void beforeClass() throws Exception { 057 Configuration conf = HBaseConfiguration.create(); 058 conf.setBoolean(MetricsConnection.CLIENT_SIDE_METRICS_ENABLED_KEY, true); 059 conf.setBoolean(MetricsConnection.CLIENT_SIDE_TABLE_METRICS_ENABLED_KEY, true); 060 UTIL = new HBaseTestingUtility(conf); 061 UTIL.startMiniCluster(2); 062 UTIL.createTable(TABLE_1, FAMILY); 063 UTIL.waitTableAvailable(TABLE_1); 064 // Only test the sync connection mode. 065 CONN = UTIL.getConnection(); 066 METRICS = ((ConnectionImplementation) CONN).getConnectionMetrics(); 067 } 068 069 @AfterClass 070 public static void afterClass() throws Exception { 071 UTIL.deleteTableIfAny(TABLE_1); 072 UTIL.shutdownMiniCluster(); 073 } 074 075 @Test 076 public void testGetTableMetrics() throws IOException { 077 Table table = CONN.getTable(TABLE_1); 078 table.get(new Get(Bytes.toBytes("row1"))); 079 table.get(new Get(Bytes.toBytes("row2"))); 080 table.get(new Get(Bytes.toBytes("row3"))); 081 table.close(); 082 083 String metricKey = 084 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Get_" + tableName; 085 verifyTableMetrics(metricKey, 3); 086 } 087 088 @Test 089 public void testMutateTableMetrics() throws IOException { 090 Table table = CONN.getTable(TABLE_1); 091 // PUT 092 Put put = new Put(Bytes.toBytes("row1")); 093 put.addColumn(FAMILY, Bytes.toBytes("name"), Bytes.toBytes("tom")); 094 table.put(put); 095 put = new Put(Bytes.toBytes("row2")); 096 put.addColumn(FAMILY, Bytes.toBytes("name"), Bytes.toBytes("jerry")); 097 table.put(put); 098 // DELETE 099 table.delete(new Delete(Bytes.toBytes("row1"))); 100 table.close(); 101 102 String metricKey = 103 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Mutate(Put)_" + tableName; 104 verifyTableMetrics(metricKey, 2); 105 106 metricKey = "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Mutate(Delete)_" 107 + tableName; 108 verifyTableMetrics(metricKey, 1); 109 } 110 111 @Test 112 public void testScanTableMetrics() throws IOException { 113 Table table = CONN.getTable(TABLE_1); 114 table.getScanner(new Scan()); 115 table.close(); 116 117 String metricKey = 118 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Scan_" + tableName; 119 verifyTableMetrics(metricKey, 1); 120 } 121 122 @Test 123 public void testMultiTableMetrics() throws IOException { 124 Table table = CONN.getTable(TABLE_1); 125 table.put(Arrays.asList( 126 new Put(Bytes.toBytes("row1")).addColumn(FAMILY, Bytes.toBytes("name"), Bytes.toBytes("tom")), 127 new Put(Bytes.toBytes("row2")).addColumn(FAMILY, Bytes.toBytes("name"), 128 Bytes.toBytes("jerry")))); 129 table.get(Arrays.asList(new Get(Bytes.toBytes("row1")), new Get(Bytes.toBytes("row2")))); 130 table.close(); 131 132 String metricKey = 133 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Multi_" + tableName; 134 verifyTableMetrics(metricKey, 2); 135 } 136 137 private static void verifyTableMetrics(String metricKey, int expectedVal) { 138 String numOpsSuffix = "_num_ops"; 139 String p95Suffix = "_95th_percentile"; 140 String p99Suffix = "_99th_percentile"; 141 Timer timer = METRICS.getRpcTimers().get(metricKey); 142 long numOps = timer.getCount(); 143 double p95 = timer.getSnapshot().get95thPercentile(); 144 double p99 = timer.getSnapshot().get99thPercentile(); 145 assertEquals("metric: " + metricKey + numOpsSuffix + " val: " + numOps, expectedVal, numOps); 146 assertTrue("metric: " + metricKey + p95Suffix + " val: " + p95, p95 >= 0); 147 assertTrue("metric: " + metricKey + p99Suffix + " val: " + p99, p99 >= 0); 148 } 149}