001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client.metrics; 019 020import java.util.HashMap; 021import java.util.Map; 022import java.util.concurrent.atomic.AtomicLong; 023 024import org.apache.yetus.audience.InterfaceAudience; 025 026import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap; 027 028/** 029 * Provides server side metrics related to scan operations. 030 */ 031@InterfaceAudience.Public 032public class ServerSideScanMetrics { 033 /** 034 * Hash to hold the String -> Atomic Long mappings for each metric 035 */ 036 private final Map<String, AtomicLong> counters = new HashMap<>(); 037 038 /** 039 * Create a new counter with the specified name 040 * @param counterName 041 * @return {@link AtomicLong} instance for the counter with counterName 042 */ 043 protected AtomicLong createCounter(String counterName) { 044 AtomicLong c = new AtomicLong(0); 045 counters.put(counterName, c); 046 return c; 047 } 048 049 public static final String COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME = "ROWS_SCANNED"; 050 public static final String COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME = "ROWS_FILTERED"; 051 052 /** 053 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 054 * (<a href="https://issues.apache.org/jira/browse/HBASE-17886">HBASE-17886</a>). 055 * Use {@link #COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME}. 056 */ 057 @Deprecated 058 public static final String COUNT_OF_ROWS_SCANNED_KEY = COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME; 059 060 /** 061 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 062 * (<a href="https://issues.apache.org/jira/browse/HBASE-17886">HBASE-17886</a>). 063 * Use {@link #COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME}. 064 */ 065 @Deprecated 066 public static final String COUNT_OF_ROWS_FILTERED_KEY = COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME; 067 068 /** 069 * number of rows filtered during scan RPC 070 */ 071 public final AtomicLong countOfRowsFiltered = createCounter(COUNT_OF_ROWS_FILTERED_KEY_METRIC_NAME); 072 073 /** 074 * number of rows scanned during scan RPC. Not every row scanned will be returned to the client 075 * since rows may be filtered. 076 */ 077 public final AtomicLong countOfRowsScanned = createCounter(COUNT_OF_ROWS_SCANNED_KEY_METRIC_NAME); 078 079 /** 080 * @param counterName 081 * @param value 082 */ 083 public void setCounter(String counterName, long value) { 084 AtomicLong c = this.counters.get(counterName); 085 if (c != null) { 086 c.set(value); 087 } 088 } 089 090 /** 091 * @param counterName 092 * @return true if a counter exists with the counterName 093 */ 094 public boolean hasCounter(String counterName) { 095 return this.counters.containsKey(counterName); 096 } 097 098 /** 099 * @param counterName 100 * @return {@link AtomicLong} instance for this counter name, null if counter does not exist. 101 */ 102 public AtomicLong getCounter(String counterName) { 103 return this.counters.get(counterName); 104 } 105 106 /** 107 * @param counterName 108 * @param delta 109 */ 110 public void addToCounter(String counterName, long delta) { 111 AtomicLong c = this.counters.get(counterName); 112 if (c != null) { 113 c.addAndGet(delta); 114 } 115 } 116 117 /** 118 * Get all of the values since the last time this function was called. Calling this function will 119 * reset all AtomicLongs in the instance back to 0. 120 * @return A Map of String -> Long for metrics 121 */ 122 public Map<String, Long> getMetricsMap() { 123 return getMetricsMap(true); 124 } 125 126 /** 127 * Get all of the values. If reset is true, we will reset the all AtomicLongs back to 0. 128 * @param reset whether to reset the AtomicLongs to 0. 129 * @return A Map of String -> Long for metrics 130 */ 131 public Map<String, Long> getMetricsMap(boolean reset) { 132 // Create a builder 133 ImmutableMap.Builder<String, Long> builder = ImmutableMap.builder(); 134 for (Map.Entry<String, AtomicLong> e : this.counters.entrySet()) { 135 long value = reset ? e.getValue().getAndSet(0) : e.getValue().get(); 136 builder.put(e.getKey(), value); 137 } 138 // Build the immutable map so that people can't mess around with it. 139 return builder.build(); 140 } 141}