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_METRIC_NAME = "ROWS_SCANNED";
52 public static final String COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME = "ROWS_FILTERED";
53
54 /** @deprecated Use {@link #COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME} instead */
55 public static final String COUNT_OF_ROWS_SCANNED_KEY = COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME;
56 /** @deprecated Use {@link #COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME} instead */
57 public static final String COUNT_OF_ROWS_FILTERED_KEY = COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME;
58
59 /**
60 * number of rows filtered during scan RPC
61 */
62 public final AtomicLong countOfRowsFiltered = createCounter(COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME);
63
64 /**
65 * number of rows scanned during scan RPC. Not every row scanned will be returned to the client
66 * since rows may be filtered.
67 */
68 public final AtomicLong countOfRowsScanned = createCounter(COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME);
69
70 /**
71 * @param counterName
72 * @param value
73 */
74 public void setCounter(String counterName, long value) {
75 AtomicLong c = this.counters.get(counterName);
76 if (c != null) {
77 c.set(value);
78 }
79 }
80
81 /**
82 * @param counterName
83 * @return true if a counter exists with the counterName
84 */
85 public boolean hasCounter(String counterName) {
86 return this.counters.containsKey(counterName);
87 }
88
89 /**
90 * @param counterName
91 * @return {@link AtomicLong} instance for this counter name, null if counter does not exist.
92 */
93 public AtomicLong getCounter(String counterName) {
94 return this.counters.get(counterName);
95 }
96
97 /**
98 * @param counterName
99 * @param delta
100 */
101 public void addToCounter(String counterName, long delta) {
102 AtomicLong c = this.counters.get(counterName);
103 if (c != null) {
104 c.addAndGet(delta);
105 }
106 }
107
108 /**
109 * Get all of the values since the last time this function was called. Calling this function will
110 * reset all AtomicLongs in the instance back to 0.
111 * @return A Map of String -> Long for metrics
112 */
113 public Map<String, Long> getMetricsMap() {
114 // Create a builder
115 ImmutableMap.Builder<String, Long> builder = ImmutableMap.builder();
116 // For every entry add the value and reset the AtomicLong back to zero
117 for (Map.Entry<String, AtomicLong> e : this.counters.entrySet()) {
118 builder.put(e.getKey(), e.getValue().getAndSet(0));
119 }
120 // Build the immutable map so that people can't mess around with it.
121 return builder.build();
122 }
123 }