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.commons.lang.StringUtils;
25 import org.apache.hadoop.metrics2.MetricHistogram;
26 import org.apache.hadoop.metrics2.MetricsInfo;
27 import org.apache.hadoop.metrics2.MetricsRecordBuilder;
28
29 import java.util.concurrent.atomic.AtomicLong;
30
31
32
33
34 public class MutableHistogram extends MutableMetric implements MetricHistogram {
35
36 private static final int DEFAULT_SAMPLE_SIZE = 2046;
37
38
39 private static final double DEFAULT_ALPHA = 0.015;
40
41 private final String name;
42 private final String desc;
43 private final Sample sample;
44 private final AtomicLong min;
45 private final AtomicLong max;
46 private final AtomicLong sum;
47 private final AtomicLong count;
48
49 public MutableHistogram(MetricsInfo info) {
50 this(info.name(), info.description());
51 }
52
53 public MutableHistogram(String name, String description) {
54 this.name = StringUtils.capitalize(name);
55 this.desc = StringUtils.uncapitalize(description);
56 sample = new ExponentiallyDecayingSample(DEFAULT_SAMPLE_SIZE, DEFAULT_ALPHA);
57 count = new AtomicLong();
58 min = new AtomicLong(Long.MAX_VALUE);
59 max = new AtomicLong(Long.MIN_VALUE);
60 sum = new AtomicLong();
61 }
62
63 public void add(final long val) {
64 setChanged();
65 count.incrementAndGet();
66 sample.update(val);
67 setMax(val);
68 setMin(val);
69 sum.getAndAdd(val);
70 }
71
72 private void setMax(final long potentialMax) {
73 boolean done = false;
74 while (!done) {
75 final long currentMax = max.get();
76 done = currentMax >= potentialMax
77 || max.compareAndSet(currentMax, potentialMax);
78 }
79 }
80
81 private void setMin(long potentialMin) {
82 boolean done = false;
83 while (!done) {
84 final long currentMin = min.get();
85 done = currentMin <= potentialMin
86 || min.compareAndSet(currentMin, potentialMin);
87 }
88 }
89
90 public long getMax() {
91 if (count.get() > 0) {
92 return max.get();
93 }
94 return 0L;
95 }
96
97 public long getMin() {
98 if (count.get() > 0) {
99 return min.get();
100 }
101 return 0L;
102 }
103
104 public double getMean() {
105 long cCount = count.get();
106 if (cCount > 0) {
107 return sum.get() / (double) cCount;
108 }
109 return 0.0;
110 }
111
112 @Override
113 public void snapshot(MetricsRecordBuilder metricsRecordBuilder, boolean all) {
114 if (all || changed()) {
115 clearChanged();
116 final Snapshot s = sample.getSnapshot();
117 metricsRecordBuilder.addCounter(Interns.info(name + NUM_OPS_METRIC_NAME, desc), count.get());
118
119 metricsRecordBuilder.addGauge(Interns.info(name + MIN_METRIC_NAME, desc), getMin());
120 metricsRecordBuilder.addGauge(Interns.info(name + MAX_METRIC_NAME, desc), getMax());
121 metricsRecordBuilder.addGauge(Interns.info(name + MEAN_METRIC_NAME, desc), getMean());
122
123 metricsRecordBuilder.addGauge(Interns.info(name + MEDIAN_METRIC_NAME, desc), s.getMedian());
124 metricsRecordBuilder.addGauge(Interns.info(name + SEVENTY_FIFTH_PERCENTILE_METRIC_NAME, desc),
125 s.get75thPercentile());
126 metricsRecordBuilder.addGauge(Interns.info(name + NINETY_FIFTH_PERCENTILE_METRIC_NAME, desc),
127 s.get95thPercentile());
128 metricsRecordBuilder.addGauge(Interns.info(name + NINETY_NINETH_PERCENTILE_METRIC_NAME, desc),
129 s.get99thPercentile());
130 }
131 }
132 }