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