View Javadoc

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  
19  package org.apache.hadoop.hbase.client.metrics;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  import java.util.concurrent.atomic.AtomicLong;
24  
25  import org.apache.hadoop.hbase.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.classification.InterfaceStability;
27  
28  import com.google.common.collect.ImmutableMap;
29  
30  
31  /**
32   * Provides client-side metrics related to scan operations.
33   * The data can be passed to mapreduce framework or other systems.
34   * We use atomic longs so that one thread can increment,
35   * while another atomically resets to zero after the values are reported
36   * to hadoop's counters.
37   *
38   * Some of these metrics are general for any client operation such as put
39   * However, there is no need for this. So they are defined under scan operation
40   * for now.
41   */
42  @InterfaceAudience.Public
43  @InterfaceStability.Evolving
44  public class ScanMetrics {
45  
46    /**
47     * Hash to hold the String -> Atomic Long mappings.
48     */
49    private final Map<String, AtomicLong> counters = new HashMap<String, AtomicLong>();
50  
51    // AtomicLongs to hold the metrics values.  These are all updated through ClientScanner and
52    // ScannerCallable.  They are atomic longs so that atomic getAndSet can be used to reset the
53    // values after progress is passed to hadoop's counters.
54  
55  
56    /**
57     * number of RPC calls
58     */
59    public final AtomicLong countOfRPCcalls = createCounter("RPC_CALLS");
60  
61    /**
62     * number of remote RPC calls
63     */
64    public final AtomicLong countOfRemoteRPCcalls = createCounter("REMOTE_RPC_CALLS");
65  
66    /**
67     * sum of milliseconds between sequential next calls
68     */
69    public final AtomicLong sumOfMillisSecBetweenNexts = createCounter("MILLIS_BETWEEN_NEXTS");
70  
71    /**
72     * number of NotServingRegionException caught
73     */
74    public final AtomicLong countOfNSRE = createCounter("NOT_SERVING_REGION_EXCEPTION");
75  
76    /**
77     * number of bytes in Result objects from region servers
78     */
79    public final AtomicLong countOfBytesInResults = createCounter("BYTES_IN_RESULTS");
80  
81    /**
82     * number of bytes in Result objects from remote region servers
83     */
84    public final AtomicLong countOfBytesInRemoteResults = createCounter("BYTES_IN_REMOTE_RESULTS");
85  
86    /**
87     * number of regions
88     */
89    public final AtomicLong countOfRegions = createCounter("REGIONS_SCANNED");
90  
91    /**
92     * number of RPC retries
93     */
94    public final AtomicLong countOfRPCRetries = createCounter("RPC_RETRIES");
95  
96    /**
97     * number of remote RPC retries
98     */
99    public final AtomicLong countOfRemoteRPCRetries = createCounter("REMOTE_RPC_RETRIES");
100 
101   /**
102    * constructor
103    */
104   public ScanMetrics() {
105   }
106 
107   private AtomicLong createCounter(String counterName) {
108     AtomicLong c = new AtomicLong(0);
109     counters.put(counterName, c);
110     return c;
111   }
112 
113   public void setCounter(String counterName, long value) {
114     AtomicLong c = this.counters.get(counterName);
115     if (c != null) {
116       c.set(value);
117     }
118   }
119 
120   /**
121    * Get all of the values since the last time this function was called.
122    *
123    * Calling this function will reset all AtomicLongs in the instance back to 0.
124    *
125    * @return A Map of String -> Long for metrics
126    */
127   public Map<String, Long> getMetricsMap() {
128     //Create a builder
129     ImmutableMap.Builder<String, Long> builder = ImmutableMap.builder();
130     //For every entry add the value and reset the AtomicLong back to zero
131     for (Map.Entry<String, AtomicLong> e : this.counters.entrySet()) {
132       builder.put(e.getKey(), e.getValue().getAndSet(0));
133     }
134     //Build the immutable map so that people can't mess around with it.
135     return builder.build();
136   }
137 
138 }