1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.metrics2.lib;
20
21 import com.yammer.metrics.stats.ExponentiallyDecayingSample;
22 import com.yammer.metrics.stats.Sample;
23 import com.yammer.metrics.stats.Snapshot;
24 import org.apache.hadoop.metrics2.MetricHistogram;
25 import org.apache.hadoop.metrics2.MetricsRecordBuilder;
26
27 import java.util.concurrent.atomic.AtomicLong;
28
29
30
31
32 public class MetricMutableHistogram extends MetricMutable implements MetricHistogram {
33
34 private static final int DEFAULT_SAMPLE_SIZE = 2046;
35
36
37 private static final double DEFAULT_ALPHA = 0.015;
38
39 private final Sample sample;
40 private final AtomicLong min;
41 private final AtomicLong max;
42 private final AtomicLong sum;
43 private final AtomicLong count;
44
45
46 public MetricMutableHistogram(String name, String description) {
47 super(name, description);
48 sample = new ExponentiallyDecayingSample(DEFAULT_SAMPLE_SIZE, DEFAULT_ALPHA);
49 count = new AtomicLong();
50 min = new AtomicLong(Long.MAX_VALUE);
51 max = new AtomicLong(Long.MIN_VALUE);
52 sum = new AtomicLong();
53 }
54
55 public void add(final long val) {
56 setChanged();
57 count.incrementAndGet();
58 sample.update(val);
59 setMax(val);
60 setMin(val);
61 sum.getAndAdd(val);
62 }
63
64 private void setMax(final long potentialMax) {
65 boolean done = false;
66 while (!done) {
67 final long currentMax = max.get();
68 done = currentMax >= potentialMax
69 || max.compareAndSet(currentMax, potentialMax);
70 }
71 }
72
73 private void setMin(long potentialMin) {
74 boolean done = false;
75 while (!done) {
76 final long currentMin = min.get();
77 done = currentMin <= potentialMin
78 || min.compareAndSet(currentMin, potentialMin);
79 }
80 }
81
82 public long getMax() {
83 if (count.get() > 0) {
84 return max.get();
85 }
86 return 0L;
87 }
88
89 public long getMin() {
90 if (count.get() > 0) {
91 return min.get();
92 }
93 return 0L;
94 }
95
96 public double getMean() {
97 long cCount = count.get();
98 if (cCount > 0) {
99 return sum.get() / (double) cCount;
100 }
101 return 0.0;
102 }
103
104
105 @Override
106 public void snapshot(MetricsRecordBuilder metricsRecordBuilder, boolean all) {
107 if (all || changed()) {
108 clearChanged();
109 updateSnapshotMetrics(metricsRecordBuilder);
110 }
111 }
112
113 public void updateSnapshotMetrics(MetricsRecordBuilder metricsRecordBuilder) {
114 final Snapshot s = sample.getSnapshot();
115 metricsRecordBuilder.addCounter(name + NUM_OPS_METRIC_NAME, "", count.get());
116 metricsRecordBuilder.addGauge(name + MIN_METRIC_NAME, "", getMin());
117 metricsRecordBuilder.addGauge(name + MAX_METRIC_NAME, "", getMax());
118 metricsRecordBuilder.addGauge(name + MEAN_METRIC_NAME, "", getMean());
119
120 metricsRecordBuilder.addGauge(name + MEDIAN_METRIC_NAME, "", s.getMedian());
121 metricsRecordBuilder.addGauge(name + SEVENTY_FIFTH_PERCENTILE_METRIC_NAME, "", s.get75thPercentile());
122 metricsRecordBuilder.addGauge(name + NINETIETH_PERCENTILE_METRIC_NAME, "", s.getValue(0.90));
123 metricsRecordBuilder.addGauge(name + NINETY_FIFTH_PERCENTILE_METRIC_NAME, "", s.get95thPercentile());
124 metricsRecordBuilder.addGauge(name + NINETY_NINETH_PERCENTILE_METRIC_NAME, "", s.get99thPercentile());
125 }
126 }