org.apache.hadoop.hbase.metrics.ExactCounterMetric Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hbase-server Show documentation
Show all versions of hbase-server Show documentation
Server functionality for HBase
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.metrics;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.metrics.MetricsRecord;
import org.apache.hadoop.metrics.util.MetricsBase;
import org.apache.hadoop.metrics.util.MetricsRegistry;
import org.cliffc.high_scale_lib.Counter;
import com.google.common.collect.Lists;
@Deprecated
public class ExactCounterMetric extends MetricsBase {
private static final int DEFAULT_TOP_N = 5;
// only publish stats on the topN items (default to DEFAULT_TOP_N)
private final int topN;
private final ConcurrentMap counts = new ConcurrentHashMap();
// all access to the 'counts' map should use this lock.
// take a write lock iff you want to guarantee exclusive access
// (the map stripes locks internally, so it's already thread safe -
// this lock is just so you can take a consistent snapshot of data)
private final ReadWriteLock lock;
/**
* Constructor to create a new counter metric
* @param nam the name to publish this metric under
* @param registry where the metrics object will be registered
* @param description metrics description
* @param topN how many 'keys' to publish metrics on
*/
public ExactCounterMetric(final String nam, final MetricsRegistry registry,
final String description, int topN) {
super(nam, description);
this.lock = new ReentrantReadWriteLock();
this.topN = topN;
if (registry != null) {
registry.add(nam, this);
}
}
/**
* Constructor creates a new ExactCounterMetric
* @param nam the name of the metrics to be used to publish the metric
* @param registry where the metrics object will be registered
*/
public ExactCounterMetric(final String nam, MetricsRegistry registry) {
this(nam, registry, NO_DESCRIPTION, DEFAULT_TOP_N);
}
/**
* Relies on an external lock on {@link #lock} for thread safety.
*/
private Counter getOrCreateCounter(String type){
Counter cnt = counts.get(type);
if (cnt == null){
cnt = new Counter();
counts.put(type, cnt);
}
return cnt;
}
public void update(String type) {
this.lock.readLock().lock();
try {
getOrCreateCounter(type).increment();
} finally {
this.lock.readLock().unlock();
}
}
public void update(String type, long count) {
this.lock.readLock().lock();
try {
getOrCreateCounter(type).add(count);
} finally {
this.lock.readLock().unlock();
}
}
public List> getTop(int n) {
final List> countsSnapshot =
Lists.newArrayListWithCapacity(this.counts.size());
// no updates are allowed while I'm holding this lock, so move fast
this.lock.writeLock().lock();
try {
for(Entry entry : this.counts.entrySet()) {
countsSnapshot.add(Pair.newPair(entry.getKey(),
entry.getValue().get()));
}
} finally {
this.lock.writeLock().unlock();
}
Collections.sort(countsSnapshot, new Comparator>() {
@Override
public int compare(Pair a, Pair b) {
return b.getSecond().compareTo(a.getSecond());
}
});
return countsSnapshot.subList(0, Math.min(n, countsSnapshot.size()));
}
@Override
public void pushMetric(MetricsRecord mr) {
final List> topKeys = getTop(Integer.MAX_VALUE);
int sum = 0;
int counter = 0;
for (Pair keyCount : topKeys) {
counter++;
// only push stats on the topN keys
if (counter <= this.topN) {
mr.setMetric(getName() + "_" + keyCount.getFirst(),
keyCount.getSecond());
}
sum += keyCount.getSecond();
}
mr.setMetric(getName() + "_map_size", this.counts.size());
mr.setMetric(getName() + "_total_count", sum);
}
}