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