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