Skip to content

Commit 771e184

Browse files
ZhaoBQReidddddd
authored andcommitted
HBASE-22975 Add read and write QPS metrics at server level and table level
Signed-off-by Reid Chan <reidchan@apache.org>
1 parent 7239ccb commit 771e184

File tree

6 files changed

+247
-0
lines changed

6 files changed

+247
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.hadoop.hbase.regionserver;
18+
19+
import org.apache.hadoop.hbase.TableName;
20+
import org.apache.hadoop.hbase.classification.InterfaceAudience;
21+
22+
/**
23+
* Query Per Second for each table in a RegionServer.
24+
*/
25+
@InterfaceAudience.Private
26+
public interface MetricsTableQueryMeter {
27+
28+
/**
29+
* Update table read QPS
30+
* @param tableName The table the metric is for
31+
* @param count Number of occurrences to record
32+
*/
33+
void updateTableReadQueryMeter(TableName tableName, long count);
34+
35+
/**
36+
* Update table read QPS
37+
* @param tableName The table the metric is for
38+
*/
39+
void updateTableReadQueryMeter(TableName tableName);
40+
41+
/**
42+
* Update table write QPS
43+
* @param tableName The table the metric is for
44+
* @param count Number of occurrences to record
45+
*/
46+
void updateTableWriteQueryMeter(TableName tableName, long count);
47+
48+
/**
49+
* Update table write QPS
50+
* @param tableName The table the metric is for
51+
*/
52+
void updateTableWriteQueryMeter(TableName tableName);
53+
}

hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsTableLatenciesImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import org.apache.hadoop.hbase.classification.InterfaceAudience;
2323
import org.apache.hadoop.hbase.metrics.BaseSourceImpl;
2424
import org.apache.hadoop.metrics2.MetricHistogram;
25+
import org.apache.hadoop.metrics2.MetricsCollector;
26+
import org.apache.hadoop.metrics2.MetricsRecordBuilder;
2527
import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
2628

2729
import com.google.common.annotations.VisibleForTesting;
@@ -172,4 +174,15 @@ public void updateScanSize(String tableName, long scanSize) {
172174
public void updateScanTime(String tableName, long t) {
173175
getOrCreateTableHistogram(tableName).updateScanTime(t);
174176
}
177+
178+
@Override
179+
public void getMetrics(MetricsCollector metricsCollector, boolean all) {
180+
MetricsRecordBuilder mrb = metricsCollector.addRecord(metricsName);
181+
// source is registered in supers constructor, sometimes called before the whole initialization.
182+
metricsRegistry.snapshot(mrb, all);
183+
if (metricsAdapter != null) {
184+
// snapshot MetricRegistry as well
185+
metricsAdapter.snapshotAllMetrics(registry, mrb);
186+
}
187+
}
175188
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.hadoop.hbase.regionserver;
18+
19+
import java.util.Map;
20+
import java.util.concurrent.ConcurrentHashMap;
21+
22+
import org.apache.hadoop.hbase.TableName;
23+
import org.apache.hadoop.hbase.classification.InterfaceAudience;
24+
import org.apache.hadoop.hbase.metrics.Meter;
25+
import org.apache.hadoop.hbase.metrics.MetricRegistry;
26+
27+
/**
28+
* Implementation of {@link MetricsTableQueryMeter} to track query per second for each table in
29+
* a RegionServer.
30+
*/
31+
@InterfaceAudience.Private
32+
public class MetricsTableQueryMeterImpl implements MetricsTableQueryMeter {
33+
private final Map<TableName, TableMeters> metersByTable = new ConcurrentHashMap<>();
34+
private final MetricRegistry metricRegistry;
35+
36+
private final static String TABLE_READ_QUERY_PER_SECOND = "tableReadQueryPerSecond";
37+
private final static String TABLE_WRITE_QUERY_PER_SECOND = "tableWriteQueryPerSecond";
38+
39+
public MetricsTableQueryMeterImpl(MetricRegistry metricRegistry) {
40+
this.metricRegistry = metricRegistry;
41+
}
42+
43+
private static class TableMeters {
44+
final Meter tableReadQueryMeter;
45+
final Meter tableWriteQueryMeter;
46+
47+
TableMeters(MetricRegistry metricRegistry, TableName tableName) {
48+
this.tableReadQueryMeter = metricRegistry.meter(qualifyMetricsName(tableName,
49+
TABLE_READ_QUERY_PER_SECOND));
50+
this.tableWriteQueryMeter =
51+
metricRegistry.meter(qualifyMetricsName(tableName, TABLE_WRITE_QUERY_PER_SECOND));
52+
}
53+
54+
public void updateTableReadQueryMeter(long count) {
55+
tableReadQueryMeter.mark(count);
56+
}
57+
58+
public void updateTableReadQueryMeter() {
59+
tableReadQueryMeter.mark();
60+
}
61+
62+
public void updateTableWriteQueryMeter(long count) {
63+
tableWriteQueryMeter.mark(count);
64+
}
65+
66+
public void updateTableWriteQueryMeter() {
67+
tableWriteQueryMeter.mark();
68+
}
69+
}
70+
71+
private static String qualifyMetricsName(TableName tableName, String metric) {
72+
StringBuilder sb = new StringBuilder();
73+
sb.append("Namespace_").append(tableName.getNamespaceAsString());
74+
sb.append("_table_").append(tableName.getQualifierAsString());
75+
sb.append("_metric_").append(metric);
76+
return sb.toString();
77+
}
78+
79+
private TableMeters getOrCreateTableMeter(TableName tableName) {
80+
TableMeters meters = metersByTable.get(tableName);
81+
if (meters == null) {
82+
meters = new TableMeters(metricRegistry, tableName);
83+
metersByTable.put(tableName, meters);
84+
}
85+
return meters;
86+
}
87+
88+
@Override
89+
public void updateTableReadQueryMeter(TableName tableName, long count) {
90+
getOrCreateTableMeter(tableName).updateTableReadQueryMeter(count);
91+
}
92+
93+
@Override
94+
public void updateTableReadQueryMeter(TableName tableName) {
95+
getOrCreateTableMeter(tableName).updateTableReadQueryMeter();
96+
}
97+
98+
@Override
99+
public void updateTableWriteQueryMeter(TableName tableName, long count) {
100+
getOrCreateTableMeter(tableName).updateTableWriteQueryMeter(count);
101+
}
102+
103+
@Override
104+
public void updateTableWriteQueryMeter(TableName tableName) {
105+
getOrCreateTableMeter(tableName).updateTableWriteQueryMeter();
106+
}
107+
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3160,6 +3160,10 @@ OperationStatus[] batchMutate(BatchOperationInProgress<?> batchOp) throws IOExce
31603160
}
31613161
}
31623162
} finally {
3163+
if (rsServices != null && rsServices.getMetrics() != null) {
3164+
rsServices.getMetrics().updateWriteQueryMeter(this.htableDescriptor.
3165+
getTableName(), batchOp.operations.length);
3166+
}
31633167
closeRegionOperation(op);
31643168
}
31653169
return batchOp.retCodeDetails;
@@ -6258,6 +6262,9 @@ public boolean nextRaw(List<Cell> outResults, ScannerContext scannerContext)
62586262
if (!outResults.isEmpty()) {
62596263
readRequestsCount.increment();
62606264
}
6265+
if (rsServices != null && rsServices.getMetrics() != null) {
6266+
rsServices.getMetrics().updateReadQueryMeter(getRegionInfo().getTable());
6267+
}
62616268

62626269
// If the size limit was reached it means a partial Result is being returned. Returning a
62636270
// partial Result means that we should not reset the filters; filters should only be reset in
@@ -7644,6 +7651,11 @@ public void processRowsWithLocks(RowProcessor<?,?> processor, long timeout,
76447651
if (txid != 0) {
76457652
syncOrDefer(txid, getEffectiveDurability(processor.useDurability()));
76467653
}
7654+
7655+
if (rsServices != null && rsServices.getMetrics() != null) {
7656+
rsServices.getMetrics().updateWriteQueryMeter(this.htableDescriptor.
7657+
getTableName(), mutations.size());
7658+
}
76477659
walSyncSuccessful = true;
76487660
// 12. call postBatchMutate hook
76497661
processor.postBatchMutate(this);
@@ -7949,6 +7961,10 @@ public Result append(Append mutate, long nonceGroup, long nonce) throws IOExcept
79497961
if(txid != 0){
79507962
syncOrDefer(txid, durability);
79517963
}
7964+
if (rsServices != null && rsServices.getMetrics() != null) {
7965+
rsServices.getMetrics().updateWriteQueryMeter(this.htableDescriptor.
7966+
getTableName());
7967+
}
79527968
doRollBackMemstore = false;
79537969
} finally {
79547970
if (rowLock != null) {
@@ -8078,6 +8094,10 @@ public Result increment(Increment mutation, long nonceGroup, long nonce)
80788094
// will yield indeterminate results.
80798095
return doIncrement(mutation, nonceGroup, nonce);
80808096
} finally {
8097+
if (rsServices != null && rsServices.getMetrics() != null) {
8098+
rsServices.getMetrics().updateWriteQueryMeter(this.htableDescriptor.
8099+
getTableName());
8100+
}
80818101
if (this.metricsRegion != null) this.metricsRegion.updateIncrement();
80828102
closeRegionOperation(op);
80838103
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServer.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.hadoop.hbase.TableName;
2222
import org.apache.hadoop.hbase.classification.InterfaceAudience;
2323
import org.apache.hadoop.hbase.classification.InterfaceStability;
24+
import org.apache.hadoop.hbase.metrics.Meter;
2425
import org.apache.hadoop.hbase.metrics.MetricRegistries;
2526
import org.apache.hadoop.hbase.metrics.MetricRegistry;
2627
import org.apache.hadoop.hbase.metrics.Timer;
@@ -49,6 +50,8 @@ public class MetricsRegionServer {
4950

5051
private MetricRegistry metricRegistry;
5152
private Timer bulkLoadTimer;
53+
private Meter serverReadQueryMeter;
54+
private Meter serverWriteQueryMeter;
5255

5356
public MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper, Configuration conf) {
5457
this(regionServerWrapper,
@@ -62,6 +65,8 @@ public MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper, Confi
6265

6366
// create and use metrics from the new hbase-metrics based registry.
6467
bulkLoadTimer = metricRegistry.timer("Bulkload");
68+
serverReadQueryMeter = metricRegistry.meter("ServerReadQueryPerSecond");
69+
serverWriteQueryMeter = metricRegistry.meter("ServerWriteQueryPerSecond");
6570
}
6671

6772
MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper,
@@ -211,4 +216,33 @@ public void updateCompaction(boolean isMajor, long t, int inputFileCount, int ou
211216
public void updateBulkLoad(long millis) {
212217
this.bulkLoadTimer.updateMillis(millis);
213218
}
219+
220+
221+
public void updateReadQueryMeter(TableName tn, long count) {
222+
if (tableMetrics != null && tn != null) {
223+
tableMetrics.updateTableReadQueryMeter(tn, count);
224+
}
225+
this.serverReadQueryMeter.mark(count);
226+
}
227+
228+
public void updateReadQueryMeter(TableName tn) {
229+
if (tableMetrics != null && tn != null) {
230+
tableMetrics.updateTableReadQueryMeter(tn);
231+
}
232+
this.serverReadQueryMeter.mark();
233+
}
234+
235+
public void updateWriteQueryMeter(TableName tn, long count) {
236+
if (tableMetrics != null && tn != null) {
237+
tableMetrics.updateTableWriteQueryMeter(tn, count);
238+
}
239+
this.serverWriteQueryMeter.mark(count);
240+
}
241+
242+
public void updateWriteQueryMeter(TableName tn) {
243+
if (tableMetrics != null && tn != null) {
244+
tableMetrics.updateTableWriteQueryMeter(tn);
245+
}
246+
this.serverWriteQueryMeter.mark();
247+
}
214248
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionServerTableMetrics.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
2020
import org.apache.hadoop.hbase.TableName;
2121
import org.apache.hadoop.hbase.classification.InterfaceAudience;
22+
import org.apache.hadoop.hbase.metrics.MetricRegistries;
2223

2324
/**
2425
* Captures operation metrics by table. Separates metrics collection for table metrics away from
@@ -28,9 +29,12 @@
2829
public class RegionServerTableMetrics {
2930

3031
private final MetricsTableLatencies latencies;
32+
private final MetricsTableQueryMeter queryMeter;
3133

3234
public RegionServerTableMetrics() {
3335
latencies = CompatibilitySingletonFactory.getInstance(MetricsTableLatencies.class);
36+
queryMeter = new MetricsTableQueryMeterImpl(MetricRegistries.global().
37+
get(((MetricsTableLatenciesImpl) latencies).getMetricRegistryInfo()).get());
3438
}
3539

3640
public void updatePut(TableName table, long time) {
@@ -68,4 +72,20 @@ public void updateScanTime(TableName table, long time) {
6872
public void updateScanSize(TableName table, long size) {
6973
latencies.updateScanSize(table.getNameAsString(), size);
7074
}
75+
76+
public void updateTableReadQueryMeter(TableName table, long count) {
77+
queryMeter.updateTableReadQueryMeter(table, count);
78+
}
79+
80+
public void updateTableReadQueryMeter(TableName table) {
81+
queryMeter.updateTableReadQueryMeter(table);
82+
}
83+
84+
public void updateTableWriteQueryMeter(TableName table, long count) {
85+
queryMeter.updateTableWriteQueryMeter(table, count);
86+
}
87+
88+
public void updateTableWriteQueryMeter(TableName table) {
89+
queryMeter.updateTableWriteQueryMeter(table);
90+
}
7191
}

0 commit comments

Comments
 (0)