diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MutableHistogram.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MutableHistogram.java index 381dbbb..35cd655 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MutableHistogram.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/metrics2/lib/MutableHistogram.java @@ -19,6 +19,8 @@ package org.apache.hadoop.metrics2.lib; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.commons.lang.StringUtils; import org.apache.hadoop.hbase.classification.InterfaceAudience; @@ -48,6 +50,8 @@ public class MutableHistogram extends MutableMetric implements MetricHistogram { private final AtomicLong max; private final AtomicLong sum; private final AtomicLong count; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private long lastCount = 0L; public MutableHistogram(MetricsInfo info) { this(info.name(), info.description()); @@ -64,12 +68,17 @@ public class MutableHistogram extends MutableMetric implements MetricHistogram { } public void add(final long val) { - setChanged(); - count.incrementAndGet(); - sample.update(val); - setMax(val); - setMin(val); - sum.getAndAdd(val); + lock.readLock().lock(); + try { + setChanged(); + count.incrementAndGet(); + sample.update(val); + setMax(val); + setMin(val); + sum.getAndAdd(val); + } finally { + lock.readLock().unlock(); + } } private void setMax(final long potentialMax) { @@ -91,45 +100,66 @@ public class MutableHistogram extends MutableMetric implements MetricHistogram { } public long getMax() { - if (count.get() > 0) { + if (count.get() - lastCount > 0) { return max.get(); } return 0L; } public long getMin() { - if (count.get() > 0) { + if (count.get() - lastCount > 0) { return min.get(); } return 0L; } public double getMean() { - long cCount = count.get(); + long cCount = count.get() - lastCount; if (cCount > 0) { return sum.get() / (double) cCount; } return 0.0; } + private void reset() { + sum.set(0); + lastCount = count.get(); + setMin(Long.MAX_VALUE); + setMax(Long.MIN_VALUE); + } + @Override public void snapshot(MetricsRecordBuilder metricsRecordBuilder, boolean all) { - if (all || changed()) { - clearChanged(); - final Snapshot s = sample.getSnapshot(); - metricsRecordBuilder.addCounter(Interns.info(name + NUM_OPS_METRIC_NAME, desc), count.get()); - - metricsRecordBuilder.addGauge(Interns.info(name + MIN_METRIC_NAME, desc), getMin()); - metricsRecordBuilder.addGauge(Interns.info(name + MAX_METRIC_NAME, desc), getMax()); - metricsRecordBuilder.addGauge(Interns.info(name + MEAN_METRIC_NAME, desc), getMean()); - - metricsRecordBuilder.addGauge(Interns.info(name + MEDIAN_METRIC_NAME, desc), s.getMedian()); - metricsRecordBuilder.addGauge(Interns.info(name + SEVENTY_FIFTH_PERCENTILE_METRIC_NAME, desc), - s.get75thPercentile()); - metricsRecordBuilder.addGauge(Interns.info(name + NINETY_FIFTH_PERCENTILE_METRIC_NAME, desc), - s.get95thPercentile()); - metricsRecordBuilder.addGauge(Interns.info(name + NINETY_NINETH_PERCENTILE_METRIC_NAME, desc), - s.get99thPercentile()); + lock.writeLock().lock(); + try{ + if (all || changed()) { + clearChanged(); + final Snapshot s = sample.getSnapshot(); + metricsRecordBuilder.addCounter( + Interns.info(name + NUM_OPS_METRIC_NAME, desc), count.get()); + + metricsRecordBuilder.addGauge( + Interns.info(name + MIN_METRIC_NAME, desc), getMin()); + metricsRecordBuilder.addGauge( + Interns.info(name + MAX_METRIC_NAME, desc), getMax()); + metricsRecordBuilder.addGauge( + Interns.info(name + MEAN_METRIC_NAME, desc), getMean()); + reset(); + + metricsRecordBuilder.addGauge( + Interns.info(name + MEDIAN_METRIC_NAME, desc), s.getMedian()); + metricsRecordBuilder.addGauge( + Interns.info(name + SEVENTY_FIFTH_PERCENTILE_METRIC_NAME, desc), + s.get75thPercentile()); + metricsRecordBuilder.addGauge( + Interns.info(name + NINETY_FIFTH_PERCENTILE_METRIC_NAME, desc), + s.get95thPercentile()); + metricsRecordBuilder.addGauge( + Interns.info(name + NINETY_NINETH_PERCENTILE_METRIC_NAME, desc), + s.get99thPercentile()); + } + } finally { + lock.writeLock().unlock(); } } }