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}