/******************************************************************************* * Copyright (c) 2005, 2017 springside.github.io * * Licensed under the Apache License, Version 2.0 (the "License"); *******************************************************************************/ package org.springside.modules.metrics; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.springside.modules.metrics.metric.Counter; import org.springside.modules.metrics.metric.Gauge; import org.springside.modules.metrics.metric.Histogram; import org.springside.modules.metrics.metric.Timer; /** * 注册中心, 用户创建Metrics的入口. * * 支持多线程并发的取得或创建metrics. */ public class MetricRegistry { public static final MetricRegistry INSTANCE = new MetricRegistry(); private Double[] defaultPcts = new Double[] {}; // 从get的性能考虑,没有使用ConcurrentSkipListMap而是仍然使用ConcurrentHashMap. private ConcurrentMap<String, Gauge> gauges = new ConcurrentHashMap<String, Gauge>(); private ConcurrentMap<String, Counter> counters = new ConcurrentHashMap<String, Counter>(); private ConcurrentMap<String, Histogram> histograms = new ConcurrentHashMap<String, Histogram>(); private ConcurrentMap<String, Timer> timers = new ConcurrentHashMap<String, Timer>(); private List<MetricRegistryListener> listeners = new ArrayList<MetricRegistryListener>(); /** * 在注册中心注册Gauge. */ public void registerGauge(String name, Gauge gauge) { gauges.put(name, gauge); } /** * 在注册中心获取或创建Counter. */ public Counter counter(String name) { if (counters.containsKey(name)) { return counters.get(name); } else { Counter counter = new Counter(); return register(counters, name, counter); } } /** * 在注册中心获取或创建Histogram, 并设置所需的百分比计算. * * @param pcts 设定百分位数,可选值如99, 99.99,为空时使用MetricRegistry的默认值 */ public Histogram histogram(String name, Double... pcts) { if (histograms.containsKey(name)) { return histograms.get(name); } else { Histogram histogram = new Histogram(((pcts != null) && (pcts.length > 0)) ? pcts : defaultPcts); return register(histograms, name, histogram); } } /** * 在注册中心获取或创建Timer, 并设置所需的百分比计算. * * @param pcts 设定百分位数,可选值如99, 99.99,为空时使用MetricRegistry的默认值 */ public Timer timer(String name, Double... pcts) { if (timers.containsKey(name)) { return timers.get(name); } else { Timer timer = new Timer(((pcts != null) && (pcts.length > 0) ? pcts : defaultPcts)); return register(timers, name, timer); } } /** * 快速清理注册表中全部Metrics. */ public void clearAll() { //通知Listener for (MetricRegistryListener listener : listeners) { for (String key : gauges.keySet()) { listener.onGaugeRemoved(key); } for (String key : counters.keySet()) { listener.onCounterRemoved(key); } for (String key : histograms.keySet()) { listener.onHistogramRemoved(key); } for (String key : timers.keySet()) { listener.onTimerRemoved(key); } } //清空注册 gauges.clear(); counters.clear(); histograms.clear(); timers.clear(); } private <T> T register(ConcurrentMap<String, T> metrics, String name, T newMetric) { T existingMetric = metrics.putIfAbsent(name, newMetric); if (existingMetric != null) { return existingMetric; } else { notifyNewMetric(name, newMetric); return newMetric; } } /** * 通知Listener有新Metrics加入 */ private void notifyNewMetric(String name, Object newMetric) { for (MetricRegistryListener listener : listeners) { if (newMetric instanceof Gauge) { listener.onGaugeAdded(name, (Gauge) newMetric); } if (newMetric instanceof Counter) { listener.onCounterAdded(name, (Counter) newMetric); } if (newMetric instanceof Histogram) { listener.onHistogramAdded(name, (Histogram) newMetric); } if (newMetric instanceof Timer) { listener.onTimerAdded(name, (Timer) newMetric); } } } /** * 返回所有Gauge, 无序. */ public Map<String, Gauge> getGauges() { return gauges; } /** * 返回所有Counter, 无序. */ public Map<String, Counter> getCounters() { return counters; } /** * 返回所有Histogram, 无序. */ public Map<String, Histogram> getHistograms() { return histograms; } /** * 返回所有Timer, 无序. */ public Map<String, Timer> getTimers() { return timers; } /** * 重新设置默认的百分位数. */ public void setDefaultPcts(Double[] defaultPcts) { this.defaultPcts = defaultPcts; } /** * 加入Listener,侦听Metrics的增删变化 */ public void addListener(MetricRegistryListener listener) { listeners.add(listener); } /** * 格式化以"."分割的Metrics Name的辅助函数. */ public static String name(String name, String... subNames) { StringBuilder builder = new StringBuilder(name); if (subNames != null) { for (String s : subNames) { if ((s != null) && !s.isEmpty()) { builder.append('.').append(s); } } } return builder.toString(); } /** * 返回按metrics name排序的Map的辅助函数. * * 从get的性能考虑,没有使用ConcurrentSkipListMap,而某些Reporter可能需要固定的顺序 */ public static <T> SortedMap<String, T> getSortedMetrics(Map<String, T> metrics) { return new TreeMap<String, T>(metrics); } }