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