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 org.apache.hadoop.classification.InterfaceAudience;
22 import org.apache.hadoop.classification.InterfaceStability;
23 import org.apache.hadoop.metrics2.MetricHistogram;
24 import org.apache.hadoop.metrics2.MetricsExecutor;
25 import org.apache.hadoop.metrics2.MetricsRecordBuilder;
26 import org.apache.hadoop.metrics2.util.MetricQuantile;
27 import org.apache.hadoop.metrics2.util.MetricSampleQuantiles;
28
29 import java.io.IOException;
30 import java.util.Map;
31 import java.util.concurrent.TimeUnit;
32
33
34
35
36
37
38 @InterfaceAudience.Public
39 @InterfaceStability.Evolving
40 public class MetricMutableQuantiles extends MetricMutable implements MetricHistogram {
41
42 static final MetricQuantile[] quantiles = {new MetricQuantile(0.50, 0.050),
43 new MetricQuantile(0.75, 0.025), new MetricQuantile(0.90, 0.010),
44 new MetricQuantile(0.95, 0.005), new MetricQuantile(0.99, 0.001)};
45
46 static final String[] quantilesSuffix = {"_Median",
47 "_75th_percentile", "_90th_percentile",
48 "_95th_percentile", "_99th_percentile"};
49
50 private final int interval;
51
52 private MetricSampleQuantiles estimator;
53 private long previousCount = 0;
54 private MetricsExecutor executor;
55
56 protected Map<MetricQuantile, Long> previousSnapshot = null;
57
58
59
60
61
62
63
64
65
66
67
68 public MetricMutableQuantiles(String name, String description, String sampleName,
69 String valueName, int interval) {
70 super(name, description);
71
72 estimator = new MetricSampleQuantiles(quantiles);
73
74 executor = new MetricsExecutorImpl();
75
76 this.interval = interval;
77 executor.getExecutor().scheduleAtFixedRate(new RolloverSample(this),
78 interval,
79 interval,
80 TimeUnit.SECONDS);
81 }
82
83 public MetricMutableQuantiles(String name, String description) {
84 this(name, description, "Ops", "", 60);
85 }
86
87 @Override
88 public synchronized void snapshot(MetricsRecordBuilder builder, boolean all) {
89 if (all || changed()) {
90 builder.addCounter(name + "NumOps", description, previousCount);
91 for (int i = 0; i < quantiles.length; i++) {
92 long newValue = 0;
93
94 if (previousSnapshot != null) {
95 newValue = previousSnapshot.get(quantiles[i]);
96 }
97 builder.addGauge(name + quantilesSuffix[i], description, newValue);
98 }
99 if (changed()) {
100 clearChanged();
101 }
102 }
103 }
104
105 public synchronized void add(long value) {
106 estimator.insert(value);
107 }
108
109 public int getInterval() {
110 return interval;
111 }
112
113
114 private static class RolloverSample implements Runnable {
115
116 MetricMutableQuantiles parent;
117
118 public RolloverSample(MetricMutableQuantiles parent) {
119 this.parent = parent;
120 }
121
122 @Override
123 public void run() {
124 synchronized (parent) {
125 try {
126 parent.previousCount = parent.estimator.getCount();
127 parent.previousSnapshot = parent.estimator.snapshot();
128 } catch (IOException e) {
129
130 parent.previousCount = 0;
131 parent.previousSnapshot = null;
132 }
133 parent.estimator.clear();
134 }
135 parent.setChanged();
136 }
137
138 }
139 }