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.HBaseTestingUtil; 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 HBaseTestingUtil 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 HBaseTestingUtil(conf); 061 UTIL.startMiniCluster(2); 062 UTIL.createTable(TABLE_1, FAMILY); 063 UTIL.waitTableAvailable(TABLE_1); 064 CONN = UTIL.getConnection(); 065 METRICS = ((AsyncConnectionImpl) CONN.toAsyncConnection()).getConnectionMetrics().get(); 066 } 067 068 @AfterClass 069 public static void afterClass() throws Exception { 070 UTIL.deleteTableIfAny(TABLE_1); 071 UTIL.shutdownMiniCluster(); 072 } 073 074 @Test 075 public void testGetTableMetrics() throws IOException { 076 Table table = CONN.getTable(TABLE_1); 077 table.get(new Get(Bytes.toBytes("row1"))); 078 table.get(new Get(Bytes.toBytes("row2"))); 079 table.get(new Get(Bytes.toBytes("row3"))); 080 table.close(); 081 082 String metricKey = 083 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Get_" + tableName; 084 verifyTableMetrics(metricKey, 3); 085 } 086 087 @Test 088 public void testMutateTableMetrics() throws IOException { 089 Table table = CONN.getTable(TABLE_1); 090 // PUT 091 Put put = new Put(Bytes.toBytes("row1")); 092 put.addColumn(FAMILY, Bytes.toBytes("name"), Bytes.toBytes("tom")); 093 table.put(put); 094 put = new Put(Bytes.toBytes("row2")); 095 put.addColumn(FAMILY, Bytes.toBytes("name"), Bytes.toBytes("jerry")); 096 table.put(put); 097 // DELETE 098 table.delete(new Delete(Bytes.toBytes("row1"))); 099 table.close(); 100 101 String metricKey = 102 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Mutate(Put)_" + tableName; 103 verifyTableMetrics(metricKey, 2); 104 105 metricKey = "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Mutate(Delete)_" 106 + tableName; 107 verifyTableMetrics(metricKey, 1); 108 } 109 110 @Test 111 public void testScanTableMetrics() throws IOException { 112 Table table = CONN.getTable(TABLE_1); 113 table.getScanner(new Scan()); 114 table.close(); 115 116 String metricKey = 117 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Scan_" + tableName; 118 verifyTableMetrics(metricKey, 1); 119 } 120 121 @Test 122 public void testMultiTableMetrics() throws IOException { 123 Table table = CONN.getTable(TABLE_1); 124 table.put(Arrays.asList( 125 new Put(Bytes.toBytes("row1")).addColumn(FAMILY, Bytes.toBytes("name"), Bytes.toBytes("tom")), 126 new Put(Bytes.toBytes("row2")).addColumn(FAMILY, Bytes.toBytes("name"), 127 Bytes.toBytes("jerry")))); 128 table.get(Arrays.asList(new Get(Bytes.toBytes("row1")), new Get(Bytes.toBytes("row2")))); 129 table.close(); 130 131 String metricKey = 132 "rpcCallDurationMs_" + ClientService.getDescriptor().getName() + "_Multi_" + tableName; 133 verifyTableMetrics(metricKey, 2); 134 } 135 136 private static void verifyTableMetrics(String metricKey, int expectedVal) { 137 String numOpsSuffix = "_num_ops"; 138 String p95Suffix = "_95th_percentile"; 139 String p99Suffix = "_99th_percentile"; 140 Timer timer = METRICS.getRpcTimers().get(metricKey); 141 long numOps = timer.getCount(); 142 double p95 = timer.getSnapshot().get95thPercentile(); 143 double p99 = timer.getSnapshot().get99thPercentile(); 144 assertEquals("metric: " + metricKey + numOpsSuffix + " val: " + numOps, expectedVal, numOps); 145 assertTrue("metric: " + metricKey + p95Suffix + " val: " + p95, p95 >= 0); 146 assertTrue("metric: " + metricKey + p99Suffix + " val: " + p99, p99 >= 0); 147 } 148}