001package org.avaje.metric;
002
003import java.util.Collection;
004import java.util.Iterator;
005import java.util.List;
006import java.util.ServiceLoader;
007
008import org.avaje.metric.spi.SpiMetricManager;
009import org.avaje.metric.statistics.MetricStatistics;
010
011/**
012 * Manages the creation and registration of Metrics.
013 * <p>
014 * Provides methods to allow agents to go through the registered metrics and gather/report the
015 * statistics.
016 * <p>
017 * This uses a service locator to initialise a underlying PluginMetricManager instance. A default
018 * implementation of PluginMetricManager is provided by <em>avaje-metric-core</em>.
019 */
020public class MetricManager {
021
022  /**
023   * The implementation that is found via service loader.
024   */
025  private static final SpiMetricManager mgr = initialiseProvider();
026
027  /**
028   * The default implementation which is avaje-metric-core.
029   */
030  private static final String DEFAULT_PROVIDER = "org.avaje.metric.core.DefaultMetricManager";
031
032  /**
033   * Finds and returns the implementation of PluginMetricManager using the ServiceLoader.
034   */
035  private static SpiMetricManager initialiseProvider() {
036
037    ServiceLoader<SpiMetricManager> loader = ServiceLoader.load(SpiMetricManager.class);
038    Iterator<SpiMetricManager> it = loader.iterator();
039    if (it.hasNext()) {
040      return it.next();
041    }
042    try {
043      Class<?> clazz = Class.forName(DEFAULT_PROVIDER);
044      return (SpiMetricManager) clazz.newInstance();
045
046    } catch (ClassNotFoundException e) {
047      throw new RuntimeException("Provider " + DEFAULT_PROVIDER + " not found", e);
048
049    } catch (Exception e) {
050      throw new RuntimeException("Provider " + DEFAULT_PROVIDER + " could not be instantiated: " + e, e);
051    }
052  }
053
054  /**
055   * When a request completes it is reported to the manager.
056   */
057  public static void reportTiming(RequestTiming requestTiming) {
058    mgr.reportTiming(requestTiming);
059  }
060
061  /**
062   * Add a metric supplier to the manager. These metrics are then included in the reporting.
063   */
064  public static void addSupplier(MetricSupplier supplier) {
065    mgr.addSupplier(supplier);
066  }
067
068  /**
069   * Create a MetricName based on a class and name.
070   * <p>
071   * Often the name maps to a method name.
072   */
073  public static MetricName name(Class<?> cls, String name) {
074    return mgr.name(cls, name);
075  }
076
077  /**
078   * Create a Metric name by parsing a name that is expected to include periods (dot notation
079   * similar to package.Class.method).
080   */
081  public static MetricName name(String name) {
082    return mgr.name(name);
083  }
084
085  /**
086   * Return a MetricNameCache for the given class.
087   * <p>
088   * The MetricNameCache can be used to derive MetricName objects dynamically with relatively less
089   * overhead.
090   * </p>
091   */
092  public static MetricNameCache getMetricNameCache(Class<?> cls) {
093    return mgr.getMetricNameCache(cls);
094  }
095
096  /**
097   * Return a MetricNameCache for a given base metric name.
098   * <p>
099   * The MetricNameCache can be used to derive MetricName objects dynamically with relatively less
100   * overhead.
101   * </p>
102   */
103  public static MetricNameCache getMetricNameCache(MetricName baseName) {
104    return mgr.getMetricNameCache(baseName);
105  }
106
107  /**
108   * Return a BucketTimedMetric given the name and bucket ranges.
109   */
110  public static TimedMetric getTimedMetric(MetricName name, int... bucketRanges) {
111    return mgr.getTimedMetric(name, bucketRanges);
112  }
113
114  /**
115   * Return a BucketTimedMetric given the name and bucket ranges.
116   */
117  public static TimedMetric getTimedMetric(Class<?> cls, String name, int... bucketRanges) {
118    return getTimedMetric(name(cls, name), bucketRanges);
119  }
120
121  /**
122   * Return a BucketTimedMetric given the name and bucket ranges.
123   */
124  public static TimedMetric getTimedMetric(String name, int... bucketRanges) {
125    return getTimedMetric(name(name), bucketRanges);
126  }
127
128  /**
129   * Return a TimedMetric given the name.
130   */
131  public static TimedMetric getTimedMetric(MetricName name) {
132    return mgr.getTimedMetric(name);
133  }
134
135  /**
136   * Return a TimedMetric using the Class, name to derive the MetricName.
137   */
138  public static TimedMetric getTimedMetric(Class<?> cls, String eventName) {
139    return getTimedMetric(name(cls, eventName));
140  }
141
142  /**
143   * Return a TimedMetric given the name.
144   */
145  public static TimedMetric getTimedMetric(String name) {
146    return getTimedMetric(name(name));
147  }
148
149  /**
150   * Return a CounterMetric given the name.
151   */
152  public static CounterMetric getCounterMetric(MetricName name) {
153    return mgr.getCounterMetric(name);
154  }
155
156  /**
157   * Return a CounterMetric given the name.
158   */
159  public static CounterMetric getCounterMetric(String name) {
160    return getCounterMetric(name(name));
161  }
162
163  /**
164   * Return a CounterMetric using the Class and name to derive the MetricName.
165   */
166  public static CounterMetric getCounterMetric(Class<?> cls, String eventName) {
167    return getCounterMetric(name(cls, eventName));
168  }
169
170  /**
171   * Return a ValueMetric given the name.
172   */
173  public static ValueMetric getValueMetric(MetricName name) {
174    return mgr.getValueMetric(name);
175  }
176
177  /**
178   * Return a ValueMetric using the Class and name to derive the MetricName.
179   */
180  public static ValueMetric getValueMetric(Class<?> cls, String eventName) {
181    return getValueMetric(name(cls, eventName));
182  }
183
184  /**
185   * Return a ValueMetric given the name.
186   */
187  public static ValueMetric getValueMetric(String name) {
188    return getValueMetric(name(name));
189  }
190
191  /**
192   * Return the TimedMetricGroup with a based metric name.
193   */
194  public static TimedMetricGroup getTimedMetricGroup(MetricName baseName) {
195    return mgr.getTimedMetricGroup(baseName);
196  }
197
198  /**
199   * Return the TimedMetricGroup with a class providing the base metric name.
200   * <p>
201   * The package name is the 'group' and the simple class name the 'type'.
202   */
203  public static TimedMetricGroup getTimedMetricGroup(Class<?> cls) {
204    return getTimedMetricGroup(name(cls,""));
205  }
206
207  /**
208   * Return a TimedMetricGroup with a common group and type name.
209   *
210   * @param name
211   *          the metric name
212   *
213   * @return the TimedMetricGroup used to create TimedMetric's that have a common base name.
214   */
215  public static TimedMetricGroup getTimedMetricGroup(String name) {
216    return getTimedMetricGroup(MetricName.of(name));
217  }
218
219  /**
220   * Create and register a GaugeMetric using the gauge supplied.
221   */
222  public static GaugeDoubleMetric register(MetricName name, GaugeDouble gauge) {
223    return mgr.register(name, gauge);
224  }
225
226  /**
227   * Create and register a GaugeMetric using the gauge supplied.
228   */
229  public static GaugeDoubleMetric register(String name, GaugeDouble gauge) {
230    return mgr.register(name(name), gauge);
231  }
232
233  /**
234   * Create and register a GaugeCounterMetric using the gauge supplied.
235   */
236  public static GaugeLongMetric register(MetricName name, GaugeLong gauge) {
237    return mgr.register(name, gauge);
238  }
239
240  /**
241   * Create and register a GaugeCounterMetric using the gauge supplied.
242   */
243  public static GaugeLongMetric register(String name, GaugeLong gauge) {
244    return mgr.register(name(name), gauge);
245  }
246
247  /**
248   * Return all the non-JVM registered metrics.
249   */
250  public static Collection<Metric> getMetrics() {
251    return mgr.getMetrics();
252  }
253
254  /**
255   * Return the core JVM metrics.
256   */
257  public static Collection<Metric> getJvmMetrics() {
258    return mgr.getJvmMetrics();
259  }
260
261  /**
262   * Return all the non-JVM registered metrics that are not empty.
263   */
264  public static List<MetricStatistics> collectNonEmptyMetrics() {
265    return mgr.collectNonEmptyMetrics();
266  }
267
268  /**
269   * Return JVM metrics that are not empty.
270   */
271  public static List<MetricStatistics> collectNonEmptyJvmMetrics() {
272    return mgr.collectNonEmptyJvmMetrics();
273  }
274
275  /**
276   * Return the built in JVM metrics support to register collection of all or some
277   * of the built in JVM metrics.
278   */
279  public static JvmMetrics jvmMetrics() {
280    return mgr;
281  }
282
283  /**
284   * Return the API for managing request timing.
285   */
286  public static RequestTimingManager requestTimingManager() {
287    return mgr;
288  }
289
290}