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.metrics;
19
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.concurrent.atomic.AtomicLong;
23
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.classification.InterfaceStability;
26
27 import com.google.common.collect.ImmutableMap;
28
29 /**
30 * Provides server side metrics related to scan operations.
31 */
32 @InterfaceAudience.Public
33 @InterfaceStability.Evolving
34 public class ServerSideScanMetrics {
35 /**
36 * Hash to hold the String -> Atomic Long mappings for each metric
37 */
38 private final Map<String, AtomicLong> counters = new HashMap<String, AtomicLong>();
39
40 /**
41 * Create a new counter with the specified name
42 * @param counterName
43 * @return {@link AtomicLong} instance for the counter with counterName
44 */
45 protected AtomicLong createCounter(String counterName) {
46 AtomicLong c = new AtomicLong(0);
47 counters.put(counterName, c);
48 return c;
49 }
50
51 public static final String COUNT_OF_ROWS_SCANNED_KEY = "ROWS_SCANNED";
52 public static final String COUNT_OF_ROWS_FILTERED_KEY = "ROWS_FILTERED";
53
54 /**
55 * number of rows filtered during scan RPC
56 */
57 public final AtomicLong countOfRowsFiltered = createCounter(COUNT_OF_ROWS_FILTERED_KEY);
58
59 /**
60 * number of rows scanned during scan RPC. Not every row scanned will be returned to the client
61 * since rows may be filtered.
62 */
63 public final AtomicLong countOfRowsScanned = createCounter(COUNT_OF_ROWS_SCANNED_KEY);
64
65 /**
66 * @param counterName
67 * @param value
68 */
69 public void setCounter(String counterName, long value) {
70 AtomicLong c = this.counters.get(counterName);
71 if (c != null) {
72 c.set(value);
73 }
74 }
75
76 /**
77 * @param counterName
78 * @return true if a counter exists with the counterName
79 */
80 public boolean hasCounter(String counterName) {
81 return this.counters.containsKey(counterName);
82 }
83
84 /**
85 * @param counterName
86 * @return {@link AtomicLong} instance for this counter name, null if counter does not exist.
87 */
88 public AtomicLong getCounter(String counterName) {
89 return this.counters.get(counterName);
90 }
91
92 /**
93 * @param counterName
94 * @param delta
95 */
96 public void addToCounter(String counterName, long delta) {
97 AtomicLong c = this.counters.get(counterName);
98 if (c != null) {
99 c.addAndGet(delta);
100 }
101 }
102
103 /**
104 * Get all of the values since the last time this function was called. Calling this function will
105 * reset all AtomicLongs in the instance back to 0.
106 * @return A Map of String -> Long for metrics
107 */
108 public Map<String, Long> getMetricsMap() {
109 // Create a builder
110 ImmutableMap.Builder<String, Long> builder = ImmutableMap.builder();
111 // For every entry add the value and reset the AtomicLong back to zero
112 for (Map.Entry<String, AtomicLong> e : this.counters.entrySet()) {
113 builder.put(e.getKey(), e.getValue().getAndSet(0));
114 }
115 // Build the immutable map so that people can't mess around with it.
116 return builder.build();
117 }
118 }