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.Collection;
22 import java.util.concurrent.ConcurrentMap;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.hbase.classification.InterfaceAudience;
27 import org.apache.hadoop.metrics2.MetricsException;
28 import org.apache.hadoop.metrics2.MetricsInfo;
29 import org.apache.hadoop.metrics2.MetricsRecordBuilder;
30 import org.apache.hadoop.metrics2.MetricsTag;
31 import org.apache.hadoop.metrics2.impl.MsInfo;
32
33 import com.google.common.base.Objects;
34 import com.google.common.collect.Maps;
35
36
37
38
39
40
41
42
43
44
45
46
47 @InterfaceAudience.Private
48 public class DynamicMetricsRegistry {
49 private static final Log LOG = LogFactory.getLog(DynamicMetricsRegistry.class);
50
51 private final ConcurrentMap<String, MutableMetric> metricsMap =
52 Maps.newConcurrentMap();
53 private final ConcurrentMap<String, MetricsTag> tagsMap =
54 Maps.newConcurrentMap();
55 private final MetricsInfo metricsInfo;
56 private final DefaultMetricsSystemHelper helper = new DefaultMetricsSystemHelper();
57 private final static String[] histogramSuffixes = new String[]{
58 "_num_ops",
59 "_min",
60 "_max",
61 "_median",
62 "_75th_percentile",
63 "_90th_percentile",
64 "_95th_percentile",
65 "_99th_percentile"};
66
67
68
69
70
71 public DynamicMetricsRegistry(String name) {
72 this(Interns.info(name,name));
73 }
74
75
76
77
78
79 public DynamicMetricsRegistry(MetricsInfo info) {
80 metricsInfo = info;
81 }
82
83
84
85
86 public MetricsInfo info() {
87 return metricsInfo;
88 }
89
90
91
92
93
94
95 public MutableMetric get(String name) {
96 return metricsMap.get(name);
97 }
98
99
100
101
102
103
104 public MetricsTag getTag(String name) {
105 return tagsMap.get(name);
106 }
107
108
109
110
111
112
113
114
115 public MutableCounterInt newCounter(String name, String desc, int iVal) {
116 return newCounter(new MetricsInfoImpl(name, desc), iVal);
117 }
118
119
120
121
122
123
124
125 public MutableCounterInt newCounter(MetricsInfo info, int iVal) {
126 MutableCounterInt ret = new MutableCounterInt(info, iVal);
127 return addNewMetricIfAbsent(info.name(), ret, MutableCounterInt.class);
128 }
129
130
131
132
133
134
135
136
137 public MutableCounterLong newCounter(String name, String desc, long iVal) {
138 return newCounter(new MetricsInfoImpl(name, desc), iVal);
139 }
140
141
142
143
144
145
146
147 public MutableCounterLong newCounter(MetricsInfo info, long iVal) {
148 MutableCounterLong ret = new MutableCounterLong(info, iVal);
149 return addNewMetricIfAbsent(info.name(), ret, MutableCounterLong.class);
150 }
151
152
153
154
155
156
157
158
159 public MutableGaugeInt newGauge(String name, String desc, int iVal) {
160 return newGauge(new MetricsInfoImpl(name, desc), iVal);
161 }
162
163
164
165
166
167
168 public MutableGaugeInt newGauge(MetricsInfo info, int iVal) {
169 MutableGaugeInt ret = new MutableGaugeInt(info, iVal);
170 return addNewMetricIfAbsent(info.name(), ret, MutableGaugeInt.class);
171 }
172
173
174
175
176
177
178
179
180 public MutableGaugeLong newGauge(String name, String desc, long iVal) {
181 return newGauge(new MetricsInfoImpl(name, desc), iVal);
182 }
183
184
185
186
187
188
189
190 public MutableGaugeLong newGauge(MetricsInfo info, long iVal) {
191 MutableGaugeLong ret = new MutableGaugeLong(info, iVal);
192 return addNewMetricIfAbsent(info.name(), ret, MutableGaugeLong.class);
193 }
194
195
196
197
198
199
200
201
202
203
204 public MutableStat newStat(String name, String desc,
205 String sampleName, String valueName, boolean extended) {
206 MutableStat ret =
207 new MutableStat(name, desc, sampleName, valueName, extended);
208 return addNewMetricIfAbsent(name, ret, MutableStat.class);
209 }
210
211
212
213
214
215
216
217
218
219 public MutableStat newStat(String name, String desc,
220 String sampleName, String valueName) {
221 return newStat(name, desc, sampleName, valueName, false);
222 }
223
224
225
226
227
228
229 public MutableRate newRate(String name) {
230 return newRate(name, name, false);
231 }
232
233
234
235
236
237
238
239 public MutableRate newRate(String name, String description) {
240 return newRate(name, description, false);
241 }
242
243
244
245
246
247
248
249
250 public MutableRate newRate(String name, String desc, boolean extended) {
251 return newRate(name, desc, extended, true);
252 }
253
254 @InterfaceAudience.Private
255 public MutableRate newRate(String name, String desc,
256 boolean extended, boolean returnExisting) {
257 if (returnExisting) {
258 MutableMetric rate = metricsMap.get(name);
259 if (rate != null) {
260 if (rate instanceof MutableRate) return (MutableRate) rate;
261 throw new MetricsException("Unexpected metrics type "+ rate.getClass()
262 +" for "+ name);
263 }
264 }
265 MutableRate ret = new MutableRate(name, desc, extended);
266 return addNewMetricIfAbsent(name, ret, MutableRate.class);
267 }
268
269
270
271
272
273
274 public MutableHistogram newHistogram(String name) {
275 return newHistogram(name, "");
276 }
277
278
279
280
281
282
283
284 public MutableHistogram newHistogram(String name, String desc) {
285 MutableHistogram histo = new MutableHistogram(name, desc);
286 return addNewMetricIfAbsent(name, histo, MutableHistogram.class);
287 }
288
289
290
291
292
293
294 public MutableTimeHistogram newTimeHistogram(String name) {
295 return newTimeHistogram(name, "");
296 }
297
298
299
300
301
302
303
304 public MutableTimeHistogram newTimeHistogram(String name, String desc) {
305 MutableTimeHistogram histo = new MutableTimeHistogram(name, desc);
306 return addNewMetricIfAbsent(name, histo, MutableTimeHistogram.class);
307 }
308
309
310
311
312
313
314 public MutableSizeHistogram newSizeHistogram(String name) {
315 return newSizeHistogram(name, "");
316 }
317
318
319
320
321
322
323
324 public MutableSizeHistogram newSizeHistogram(String name, String desc) {
325 MutableSizeHistogram histo = new MutableSizeHistogram(name, desc);
326 return addNewMetricIfAbsent(name, histo, MutableSizeHistogram.class);
327 }
328
329
330
331
332
333
334 public MetricMutableQuantiles newQuantile(String name) {
335 return newQuantile(name, "");
336 }
337
338 public MetricMutableQuantiles newQuantile(String name, String desc) {
339 MetricMutableQuantiles histo = new MetricMutableQuantiles(name, desc, "Ops", "", 60);
340 return addNewMetricIfAbsent(name, histo, MetricMutableQuantiles.class);
341 }
342
343 synchronized void add(String name, MutableMetric metric) {
344 addNewMetricIfAbsent(name, metric, MutableMetric.class);
345 }
346
347
348
349
350
351
352 public void add(String name, long value) {
353 MutableMetric m = metricsMap.get(name);
354
355 if (m != null) {
356 if (m instanceof MutableStat) {
357 ((MutableStat) m).add(value);
358 }
359 else {
360 throw new MetricsException("Unsupported add(value) for metric "+ name);
361 }
362 }
363 else {
364 metricsMap.put(name, newRate(name));
365 add(name, value);
366 }
367 }
368
369
370
371
372
373
374 public DynamicMetricsRegistry setContext(String name) {
375 return tag(MsInfo.Context, name, true);
376 }
377
378
379
380
381
382
383
384
385 public DynamicMetricsRegistry tag(String name, String description, String value) {
386 return tag(name, description, value, false);
387 }
388
389
390
391
392
393
394
395
396
397 public DynamicMetricsRegistry tag(String name, String description, String value,
398 boolean override) {
399 return tag(new MetricsInfoImpl(name, description), value, override);
400 }
401
402
403
404
405
406
407
408
409 public DynamicMetricsRegistry tag(MetricsInfo info, String value, boolean override) {
410 MetricsTag tag = Interns.tag(info, value);
411
412 if (!override) {
413 MetricsTag existing = tagsMap.putIfAbsent(info.name(), tag);
414 if (existing != null) {
415 throw new MetricsException("Tag "+ info.name() +" already exists!");
416 }
417 return this;
418 }
419
420 tagsMap.put(info.name(), tag);
421
422 return this;
423 }
424
425 public DynamicMetricsRegistry tag(MetricsInfo info, String value) {
426 return tag(info, value, false);
427 }
428
429 Collection<MetricsTag> tags() {
430 return tagsMap.values();
431 }
432
433 Collection<MutableMetric> metrics() {
434 return metricsMap.values();
435 }
436
437
438
439
440
441
442 public void snapshot(MetricsRecordBuilder builder, boolean all) {
443 for (MetricsTag tag : tags()) {
444 builder.add(tag);
445 }
446 for (MutableMetric metric : metrics()) {
447 metric.snapshot(builder, all);
448 }
449 }
450
451 @Override public String toString() {
452 return Objects.toStringHelper(this)
453 .add("info", metricsInfo).add("tags", tags()).add("metrics", metrics())
454 .toString();
455 }
456
457
458
459
460
461 public void removeMetric(String name) {
462 helper.removeObjectName(name);
463 metricsMap.remove(name);
464 }
465
466 public void removeHistogramMetrics(String baseName) {
467 for (String suffix:histogramSuffixes) {
468 removeMetric(baseName+suffix);
469 }
470 }
471
472
473
474
475
476
477
478 public MutableGaugeLong getLongGauge(String gaugeName, long potentialStartingValue) {
479
480 MutableMetric metric = metricsMap.get(gaugeName);
481
482
483 if (metric == null) {
484
485
486 MutableGaugeLong newGauge = new MutableGaugeLong(new MetricsInfoImpl(gaugeName, ""),
487 potentialStartingValue);
488
489
490 metric = metricsMap.putIfAbsent(gaugeName, newGauge);
491
492
493
494 if (metric == null) {
495 return newGauge;
496 }
497 }
498
499 if (!(metric instanceof MutableGaugeLong)) {
500 throw new MetricsException("Metric already exists in registry for metric name: " + gaugeName +
501 " and not of type MetricMutableGaugeLong");
502 }
503
504 return (MutableGaugeLong) metric;
505 }
506
507
508
509
510
511
512
513 public MutableCounterLong getLongCounter(String counterName, long potentialStartingValue) {
514
515 MutableMetric counter = metricsMap.get(counterName);
516 if (counter == null) {
517 MutableCounterLong newCounter =
518 new MutableCounterLong(new MetricsInfoImpl(counterName, ""), potentialStartingValue);
519 counter = metricsMap.putIfAbsent(counterName, newCounter);
520 if (counter == null) {
521 return newCounter;
522 }
523 }
524
525
526 if (!(counter instanceof MutableCounterLong)) {
527 throw new MetricsException("Metric already exists in registry for metric name: " +
528 counterName + " and not of type MetricMutableCounterLong");
529 }
530
531 return (MutableCounterLong) counter;
532 }
533
534 public MutableHistogram getHistogram(String histoName) {
535
536 MutableMetric histo = metricsMap.get(histoName);
537 if (histo == null) {
538 MutableHistogram newCounter =
539 new MutableHistogram(new MetricsInfoImpl(histoName, ""));
540 histo = metricsMap.putIfAbsent(histoName, newCounter);
541 if (histo == null) {
542 return newCounter;
543 }
544 }
545
546
547 if (!(histo instanceof MutableHistogram)) {
548 throw new MetricsException("Metric already exists in registry for metric name: " +
549 histoName + " and not of type MutableHistogram");
550 }
551
552 return (MutableHistogram) histo;
553 }
554
555 public MetricMutableQuantiles getQuantile(String histoName) {
556
557 MutableMetric histo = metricsMap.get(histoName);
558 if (histo == null) {
559 MetricMutableQuantiles newCounter =
560 new MetricMutableQuantiles(histoName, "", "Ops", "", 60);
561 histo = metricsMap.putIfAbsent(histoName, newCounter);
562 if (histo == null) {
563 return newCounter;
564 }
565 }
566
567
568 if (!(histo instanceof MetricMutableQuantiles)) {
569 throw new MetricsException("Metric already exists in registry for metric name: " +
570 histoName + " and not of type MutableHistogram");
571 }
572
573 return (MetricMutableQuantiles) histo;
574 }
575
576 private<T extends MutableMetric> T
577 addNewMetricIfAbsent(String name,
578 T ret,
579 Class<T> metricClass) {
580
581
582
583 MutableMetric metric = metricsMap.putIfAbsent(name, ret);
584 if (metric == null) {
585 return ret;
586 }
587
588 return returnExistingWithCast(metric, metricClass, name);
589 }
590
591 @SuppressWarnings("unchecked")
592 private<T> T returnExistingWithCast(MutableMetric metric,
593 Class<T> metricClass, String name) {
594 if (!metricClass.isAssignableFrom(metric.getClass())) {
595 throw new MetricsException("Metric already exists in registry for metric name: " +
596 name + " and not of type " + metricClass +
597 " but instead of type " + metric.getClass());
598 }
599
600 return (T) metric;
601 }
602
603 public void clearMetrics() {
604 for (String name:metricsMap.keySet()) {
605 helper.removeObjectName(name);
606 }
607 metricsMap.clear();
608 }
609 }