Skip to content

Commit 8c9224f

Browse files
author
Hernan Gelaf-Romer
committed
HBASE-29090: Add server-side load metrics to client results
1 parent 6f8db78 commit 8c9224f

File tree

14 files changed

+329
-20
lines changed

14 files changed

+329
-20
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/client/Get.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public Get(Get get) {
9595
this.setFilter(get.getFilter());
9696
this.setReplicaId(get.getReplicaId());
9797
this.setConsistency(get.getConsistency());
98+
this.setQueryMetricsEnabled(get.isQueryMetricsEnabled());
9899
// from Get
99100
this.cacheBlocks = get.getCacheBlocks();
100101
this.maxVersions = get.getMaxVersions();
@@ -453,6 +454,7 @@ public Map<String, Object> toMap(int maxCols) {
453454
map.put("colFamTimeRangeMap", colFamTimeRangeMapStr);
454455
}
455456
map.put("priority", getPriority());
457+
map.put("queryMetricsEnabled", queryMetricsEnabled);
456458
return map;
457459
}
458460

hbase-client/src/main/java/org/apache/hadoop/hbase/client/Query.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public abstract class Query extends OperationWithAttributes {
4646
protected Consistency consistency = Consistency.STRONG;
4747
protected Map<byte[], TimeRange> colFamTimeRangeMap = Maps.newTreeMap(Bytes.BYTES_COMPARATOR);
4848
protected Boolean loadColumnFamiliesOnDemand = null;
49+
protected boolean queryMetricsEnabled = false;
4950

5051
public Filter getFilter() {
5152
return filter;
@@ -157,6 +158,15 @@ public Query setIsolationLevel(IsolationLevel level) {
157158
return this;
158159
}
159160

161+
public Query setQueryMetricsEnabled(boolean enabled) {
162+
this.queryMetricsEnabled = enabled;
163+
return this;
164+
}
165+
166+
public boolean isQueryMetricsEnabled() {
167+
return queryMetricsEnabled;
168+
}
169+
160170
/**
161171
* Returns The isolation level of this query. If no isolation level was set for this query object,
162172
* then it returns READ_COMMITTED.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hbase.client;
19+
20+
import org.apache.yetus.audience.InterfaceAudience;
21+
22+
@InterfaceAudience.Public
23+
public class QueryMetrics {
24+
private final long blockBytesScanned;
25+
26+
public QueryMetrics(long blockBytesScanned) {
27+
this.blockBytesScanned = blockBytesScanned;
28+
}
29+
30+
public long getBlockBytesScanned() {
31+
return blockBytesScanned;
32+
}
33+
}

hbase-client/src/main/java/org/apache/hadoop/hbase/client/Result.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public class Result implements ExtendedCellScannable, ExtendedCellScanner {
9999
*/
100100
private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
101101
private RegionLoadStats stats;
102+
private QueryMetrics metrics = null;
102103

103104
private final boolean readonly;
104105

@@ -931,6 +932,11 @@ public void setStatistics(RegionLoadStats loadStats) {
931932
this.stats = loadStats;
932933
}
933934

935+
@InterfaceAudience.Private
936+
public void setMetrics(QueryMetrics metrics) {
937+
this.metrics = metrics;
938+
}
939+
934940
/**
935941
* Returns the associated statistics about the region from which this was returned. Can be
936942
* <tt>null</tt> if stats are disabled.
@@ -939,6 +945,11 @@ public RegionLoadStats getStats() {
939945
return stats;
940946
}
941947

948+
/** Returns the query metrics, or {@code null} if we do not enable metrics. */
949+
public QueryMetrics getMetrics() {
950+
return metrics;
951+
}
952+
942953
/**
943954
* All methods modifying state of Result object must call this method to ensure that special
944955
* purpose immutable Results can't be accidentally modified.

hbase-client/src/main/java/org/apache/hadoop/hbase/client/Scan.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ public Scan(Scan scan) throws IOException {
217217
setPriority(scan.getPriority());
218218
readType = scan.getReadType();
219219
super.setReplicaId(scan.getReplicaId());
220+
super.setQueryMetricsEnabled(scan.isQueryMetricsEnabled());
220221
}
221222

222223
/**
@@ -249,6 +250,7 @@ public Scan(Get get) {
249250
this.mvccReadPoint = -1L;
250251
setPriority(get.getPriority());
251252
super.setReplicaId(get.getReplicaId());
253+
super.setQueryMetricsEnabled(get.isQueryMetricsEnabled());
252254
}
253255

254256
public boolean isGetScan() {
@@ -826,6 +828,7 @@ public Map<String, Object> toMap(int maxCols) {
826828
map.put("colFamTimeRangeMap", colFamTimeRangeMapStr);
827829
}
828830
map.put("priority", getPriority());
831+
map.put("queryMetricsEnabled", queryMetricsEnabled);
829832
return map;
830833
}
831834

hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
import org.apache.hadoop.hbase.client.Mutation;
9292
import org.apache.hadoop.hbase.client.OnlineLogRecord;
9393
import org.apache.hadoop.hbase.client.Put;
94+
import org.apache.hadoop.hbase.client.QueryMetrics;
9495
import org.apache.hadoop.hbase.client.RegionInfoBuilder;
9596
import org.apache.hadoop.hbase.client.RegionLoadStats;
9697
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
@@ -659,6 +660,7 @@ public static Get toGet(final ClientProtos.Get proto) throws IOException {
659660
if (proto.hasLoadColumnFamiliesOnDemand()) {
660661
get.setLoadColumnFamiliesOnDemand(proto.getLoadColumnFamiliesOnDemand());
661662
}
663+
get.setQueryMetricsEnabled(proto.getQueryMetricsEnabled());
662664
return get;
663665
}
664666

@@ -1096,6 +1098,7 @@ public static ClientProtos.Scan toScan(final Scan scan) throws IOException {
10961098
if (scan.isNeedCursorResult()) {
10971099
scanBuilder.setNeedCursorResult(true);
10981100
}
1101+
scanBuilder.setQueryMetricsEnabled(scan.isQueryMetricsEnabled());
10991102
return scanBuilder.build();
11001103
}
11011104

@@ -1200,6 +1203,7 @@ public static Scan toScan(final ClientProtos.Scan proto) throws IOException {
12001203
if (proto.getNeedCursorResult()) {
12011204
scan.setNeedCursorResult(true);
12021205
}
1206+
scan.setQueryMetricsEnabled(proto.getQueryMetricsEnabled());
12031207
return scan;
12041208
}
12051209

@@ -1279,6 +1283,7 @@ public static ClientProtos.Get toGet(final Get get) throws IOException {
12791283
if (loadColumnFamiliesOnDemand != null) {
12801284
builder.setLoadColumnFamiliesOnDemand(loadColumnFamiliesOnDemand);
12811285
}
1286+
builder.setQueryMetricsEnabled(get.isQueryMetricsEnabled());
12821287
return builder.build();
12831288
}
12841289

@@ -1434,6 +1439,10 @@ public static ClientProtos.Result toResult(final Result result, boolean encodeTa
14341439
builder.setStale(result.isStale());
14351440
builder.setPartial(result.mayHaveMoreCellsInRow());
14361441

1442+
if (result.getMetrics() != null) {
1443+
builder.setMetrics(toQueryMetrics(result.getMetrics()));
1444+
}
1445+
14371446
return builder.build();
14381447
}
14391448

@@ -1463,6 +1472,9 @@ public static ClientProtos.Result toResultNoData(final Result result) {
14631472
ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
14641473
builder.setAssociatedCellCount(size);
14651474
builder.setStale(result.isStale());
1475+
if (result.getMetrics() != null) {
1476+
builder.setMetrics(toQueryMetrics(result.getMetrics()));
1477+
}
14661478
return builder.build();
14671479
}
14681480

@@ -1503,7 +1515,11 @@ public static Result toResult(final ClientProtos.Result proto, boolean decodeTag
15031515
for (CellProtos.Cell c : values) {
15041516
cells.add(toCell(builder, c, decodeTags));
15051517
}
1506-
return Result.create(cells, null, proto.getStale(), proto.getPartial());
1518+
Result r = Result.create(cells, null, proto.getStale(), proto.getPartial());
1519+
if (proto.hasMetrics()) {
1520+
r.setMetrics(toQueryMetrics(proto.getMetrics()));
1521+
}
1522+
return r;
15071523
}
15081524

15091525
/**
@@ -1548,9 +1564,15 @@ public static Result toResult(final ClientProtos.Result proto, final CellScanner
15481564
}
15491565
}
15501566

1551-
return (cells == null || cells.isEmpty())
1567+
Result r = (cells == null || cells.isEmpty())
15521568
? (proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT)
15531569
: Result.create(cells, null, proto.getStale());
1570+
1571+
if (proto.hasMetrics()) {
1572+
r.setMetrics(toQueryMetrics(proto.getMetrics()));
1573+
}
1574+
1575+
return r;
15541576
}
15551577

15561578
/**
@@ -3811,6 +3833,15 @@ public static ClusterStatusProtos.ServerTask toServerTask(ServerTask task) {
38113833
.setStartTime(task.getStartTime()).setCompletionTime(task.getCompletionTime()).build();
38123834
}
38133835

3836+
public static ClientProtos.QueryMetrics toQueryMetrics(QueryMetrics metrics) {
3837+
return ClientProtos.QueryMetrics.newBuilder()
3838+
.setBlockBytesScanned(metrics.getBlockBytesScanned()).build();
3839+
}
3840+
3841+
public static QueryMetrics toQueryMetrics(ClientProtos.QueryMetrics metrics) {
3842+
return new QueryMetrics(metrics.getBlockBytesScanned());
3843+
}
3844+
38143845
/**
38153846
* Check whether this IPBE indicates EOF or not.
38163847
* <p/>

hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ResponseConverter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.hadoop.hbase.DoNotRetryIOException;
2929
import org.apache.hadoop.hbase.ServerName;
3030
import org.apache.hadoop.hbase.client.CheckAndMutateResult;
31+
import org.apache.hadoop.hbase.client.QueryMetrics;
3132
import org.apache.hadoop.hbase.client.RegionInfo;
3233
import org.apache.hadoop.hbase.client.Result;
3334
import org.apache.hadoop.hbase.client.SingleResponse;
@@ -417,6 +418,7 @@ public static Result[] getResults(CellScanner cellScanner, ScanResponse response
417418
int noOfResults =
418419
cellScanner != null ? response.getCellsPerResultCount() : response.getResultsCount();
419420
Result[] results = new Result[noOfResults];
421+
List<ClientProtos.QueryMetrics> queryMetrics = response.getQueryMetricsList();
420422
for (int i = 0; i < noOfResults; i++) {
421423
if (cellScanner != null) {
422424
// Cells are out in cellblocks. Group them up again as Results. How many to read at a
@@ -453,6 +455,12 @@ public static Result[] getResults(CellScanner cellScanner, ScanResponse response
453455
// Result is pure pb.
454456
results[i] = ProtobufUtil.toResult(response.getResults(i));
455457
}
458+
459+
// Populate result metrics if they exist
460+
if (queryMetrics.size() > i) {
461+
QueryMetrics metrics = ProtobufUtil.toQueryMetrics(queryMetrics.get(i));
462+
results[i].setMetrics(metrics);
463+
}
456464
}
457465
return results;
458466
}

hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestGet.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ public void TestGetRowFromGetCopyConstructor() throws Exception {
182182
get.setMaxResultsPerColumnFamily(10);
183183
get.setRowOffsetPerColumnFamily(11);
184184
get.setCacheBlocks(true);
185+
get.setQueryMetricsEnabled(true);
185186

186187
Get copyGet = new Get(get);
187188
assertEquals(0, Bytes.compareTo(get.getRow(), copyGet.getRow()));
@@ -196,6 +197,7 @@ public void TestGetRowFromGetCopyConstructor() throws Exception {
196197
assertEquals(get.getConsistency(), copyGet.getConsistency());
197198
assertEquals(get.getReplicaId(), copyGet.getReplicaId());
198199
assertEquals(get.getIsolationLevel(), copyGet.getIsolationLevel());
200+
assertTrue(get.isQueryMetricsEnabled());
199201

200202
// from Get class
201203
assertEquals(get.isCheckExistenceOnly(), copyGet.isCheckExistenceOnly());

hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOnlineLogRecord.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,21 @@ public void itSerializesScan() {
4444
Scan scan = new Scan();
4545
scan.withStartRow(Bytes.toBytes(123));
4646
scan.withStopRow(Bytes.toBytes(456));
47-
String expectedOutput =
48-
"{\n" + " \"startTime\": 1,\n" + " \"processingTime\": 2,\n" + " \"queueTime\": 3,\n"
49-
+ " \"responseSize\": 4,\n" + " \"blockBytesScanned\": 5,\n" + " \"fsReadTime\": 6,\n"
50-
+ " \"multiGetsCount\": 6,\n" + " \"multiMutationsCount\": 7,\n" + " \"scan\": {\n"
51-
+ " \"startRow\": \"\\\\x00\\\\x00\\\\x00{\",\n" + " \"targetReplicaId\": -1,\n"
52-
+ " \"batch\": -1,\n" + " \"totalColumns\": 0,\n" + " \"maxResultSize\": -1,\n"
53-
+ " \"families\": {},\n" + " \"priority\": -1,\n" + " \"caching\": -1,\n"
54-
+ " \"includeStopRow\": false,\n" + " \"consistency\": \"STRONG\",\n"
55-
+ " \"maxVersions\": 1,\n" + " \"storeOffset\": 0,\n" + " \"mvccReadPoint\": -1,\n"
56-
+ " \"includeStartRow\": true,\n" + " \"needCursorResult\": false,\n"
57-
+ " \"stopRow\": \"\\\\x00\\\\x00\\\\x01\\\\xC8\",\n" + " \"storeLimit\": -1,\n"
58-
+ " \"limit\": -1,\n" + " \"cacheBlocks\": true,\n"
59-
+ " \"readType\": \"DEFAULT\",\n" + " \"allowPartialResults\": false,\n"
60-
+ " \"reversed\": false,\n" + " \"timeRange\": [\n" + " 0,\n"
61-
+ " 9223372036854775807\n" + " ]\n" + " }\n" + "}";
47+
String expectedOutput = "{\n" + " \"startTime\": 1,\n" + " \"processingTime\": 2,\n"
48+
+ " \"queueTime\": 3,\n" + " \"responseSize\": 4,\n" + " \"blockBytesScanned\": 5,\n"
49+
+ " \"fsReadTime\": 6,\n" + " \"multiGetsCount\": 6,\n" + " \"multiMutationsCount\": 7,\n"
50+
+ " \"scan\": {\n" + " \"totalColumns\": 0,\n" + " \"maxResultSize\": -1,\n"
51+
+ " \"caching\": -1,\n" + " \"includeStopRow\": false,\n"
52+
+ " \"consistency\": \"STRONG\",\n" + " \"maxVersions\": 1,\n"
53+
+ " \"mvccReadPoint\": -1,\n" + " \"includeStartRow\": true,\n"
54+
+ " \"stopRow\": \"\\\\x00\\\\x00\\\\x01\\\\xC8\",\n" + " \"limit\": -1,\n"
55+
+ " \"timeRange\": [\n" + " 0,\n" + " 9223372036854775807\n" + " ],\n"
56+
+ " \"startRow\": \"\\\\x00\\\\x00\\\\x00{\",\n" + " \"targetReplicaId\": -1,\n"
57+
+ " \"batch\": -1,\n" + " \"families\": {},\n" + " \"priority\": -1,\n"
58+
+ " \"storeOffset\": 0,\n" + " \"queryMetricsEnabled\": false,\n"
59+
+ " \"needCursorResult\": false,\n" + " \"storeLimit\": -1,\n"
60+
+ " \"cacheBlocks\": true,\n" + " \"readType\": \"DEFAULT\",\n"
61+
+ " \"allowPartialResults\": false,\n" + " \"reversed\": false\n" + " }\n" + "}";
6262
OnlineLogRecord o = new OnlineLogRecord(1, 2, 3, 4, 5, 6, null, null, null, null, null, null,
6363
null, 6, 7, 0, scan, Collections.emptyMap(), Collections.emptyMap());
6464
String actualOutput = o.toJsonPrettyPrint();

hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ public void testGetToScan() throws Exception {
7676
.setAttribute("att_v0", Bytes.toBytes("att_v0"))
7777
.setColumnFamilyTimeRange(Bytes.toBytes("cf"), 0, 123).setReplicaId(3)
7878
.setACL("test_user", new Permission(Permission.Action.READ))
79-
.setAuthorizations(new Authorizations("test_label")).setPriority(3);
79+
.setAuthorizations(new Authorizations("test_label")).setQueryMetricsEnabled(true)
80+
.setPriority(3);
8081

8182
Scan scan = new Scan(get);
8283
assertEquals(get.getCacheBlocks(), scan.getCacheBlocks());
@@ -100,6 +101,7 @@ public void testGetToScan() throws Exception {
100101
assertEquals(get.getACL(), scan.getACL());
101102
assertEquals(get.getAuthorizations().getLabels(), scan.getAuthorizations().getLabels());
102103
assertEquals(get.getPriority(), scan.getPriority());
104+
assertEquals(get.isQueryMetricsEnabled(), scan.isQueryMetricsEnabled());
103105
}
104106

105107
@Test
@@ -216,7 +218,7 @@ public void testScanCopyConstructor() throws Exception {
216218
.setReplicaId(3).setReversed(true).setRowOffsetPerColumnFamily(5)
217219
.setStartStopRowForPrefixScan(Bytes.toBytes("row_")).setScanMetricsEnabled(true)
218220
.setReadType(ReadType.STREAM).withStartRow(Bytes.toBytes("row_1"))
219-
.withStopRow(Bytes.toBytes("row_2")).setTimeRange(0, 13);
221+
.withStopRow(Bytes.toBytes("row_2")).setTimeRange(0, 13).setQueryMetricsEnabled(true);
220222

221223
// create a copy of existing scan object
222224
Scan scanCopy = new Scan(scan);
@@ -252,6 +254,7 @@ public void testScanCopyConstructor() throws Exception {
252254
assertEquals(scan.getStartRow(), scanCopy.getStartRow());
253255
assertEquals(scan.getStopRow(), scanCopy.getStopRow());
254256
assertEquals(scan.getTimeRange(), scanCopy.getTimeRange());
257+
assertEquals(scan.isQueryMetricsEnabled(), scanCopy.isQueryMetricsEnabled());
255258

256259
assertTrue("Make sure copy constructor adds all the fields in the copied object",
257260
EqualsBuilder.reflectionEquals(scan, scanCopy));

0 commit comments

Comments
 (0)