blob: b0985131750f353cec1cc47ceda3ee9a3a8858a3 [file] [log] [blame]
pankaj390abbc2014-10-01 17:01:05 -07001package org.onlab.metrics;
2
3import java.util.Map;
pankaj5de84112014-10-02 15:33:28 -07004import java.util.concurrent.ConcurrentHashMap;
pankaj390abbc2014-10-01 17:01:05 -07005import java.util.concurrent.ConcurrentMap;
pankaj5de84112014-10-02 15:33:28 -07006import java.util.concurrent.TimeUnit;
pankaj390abbc2014-10-01 17:01:05 -07007
pankajf6577b62014-10-02 16:38:38 -07008import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
pankaj9c060c02014-10-08 10:21:29 -070011import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
pankajf6577b62014-10-02 16:38:38 -070013
pankaj390abbc2014-10-01 17:01:05 -070014import com.codahale.metrics.Counter;
15import com.codahale.metrics.Gauge;
16import com.codahale.metrics.Histogram;
17import com.codahale.metrics.Meter;
18import com.codahale.metrics.Metric;
19import com.codahale.metrics.MetricFilter;
20import com.codahale.metrics.MetricRegistry;
pankaj9c060c02014-10-08 10:21:29 -070021import com.codahale.metrics.Slf4jReporter;
pankaj390abbc2014-10-01 17:01:05 -070022import com.codahale.metrics.Timer;
23
24/**
25 * This class holds the Metrics registry for ONOS.
26 * All metrics (Counter, Histogram, Timer, Meter, Gauge) use a hierarchical
27 * string-based naming scheme: COMPONENT.FEATURE.NAME.
28 * Example: "Topology.Counters.TopologyUpdates".
29 * The COMPONENT and FEATURE names have to be registered in advance before
30 * a metric can be created. Example:
31 * <pre>
32 * <code>
33 * private final MetricsManager.MetricsComponent COMPONENT =
34 * MetricsManager.registerComponent("Topology");
35 * private final MetricsManager.MetricsFeature FEATURE =
36 * COMPONENT.registerFeature("Counters");
37 * private final Counter counterTopologyUpdates =
38 * MetricsManager.createCounter(COMPONENT, FEATURE, "TopologyUpdates");
39 * </code>
40 * </pre>
41 * Gauges are slightly different because they are not created directly in
42 * this class, but are allocated by the caller and passed in for registration:
43 * <pre>
44 * <code>
45 * private final Gauge<Long> gauge =
46 * new {@literal Gauge<Long>}() {
47 * {@literal @}Override
48 * public Long getValue() {
49 * return gaugeValue;
50 * }
51 * };
52 * MetricsManager.registerMetric(COMPONENT, FEATURE, GAUGE_NAME, gauge);
53 * </code>
54 * </pre>
55 */
pankajf6577b62014-10-02 16:38:38 -070056@Component(immediate = true)
pankaj390abbc2014-10-01 17:01:05 -070057public final class MetricsManager implements MetricsService {
58
pankaj9c060c02014-10-08 10:21:29 -070059 private final Logger log = LoggerFactory.getLogger(getClass());
pankaj390abbc2014-10-01 17:01:05 -070060 /**
61 * Registry to hold the Components defined in the system.
62 */
pankaje138e272014-10-02 15:17:11 -070063 private ConcurrentMap<String, MetricsComponent> componentsRegistry;
pankaj390abbc2014-10-01 17:01:05 -070064
65 /**
66 * Registry for the Metrics objects created in the system.
67 */
pankaj5de84112014-10-02 15:33:28 -070068 private final MetricRegistry metricsRegistry;
pankaj390abbc2014-10-01 17:01:05 -070069
pankaj5de84112014-10-02 15:33:28 -070070 /**
71 * Default Reporter for this metrics manager.
72 */
pankaj9c060c02014-10-08 10:21:29 -070073 private final Slf4jReporter reporter;
pankaje138e272014-10-02 15:17:11 -070074
pankaj5de84112014-10-02 15:33:28 -070075 public MetricsManager() {
pankaj5de84112014-10-02 15:33:28 -070076 this.metricsRegistry = new MetricRegistry();
pankaj9c060c02014-10-08 10:21:29 -070077 this.reporter = Slf4jReporter.forRegistry(this.metricsRegistry)
78 .outputTo(log)
pankaj5de84112014-10-02 15:33:28 -070079 .convertRatesTo(TimeUnit.SECONDS)
pankaj7378e552014-10-08 10:29:26 -070080 .convertDurationsTo(TimeUnit.NANOSECONDS)
pankaj366ce8b2014-10-07 17:18:37 -070081 .build();
pankaj9c060c02014-10-08 10:21:29 -070082 reporter.start(1, TimeUnit.MINUTES);
pankaje138e272014-10-02 15:17:11 -070083 }
pankaj390abbc2014-10-01 17:01:05 -070084
pankajf6577b62014-10-02 16:38:38 -070085 @Activate
86 public void activate() {
pankaj9e34ff22014-10-06 13:21:03 -070087 this.componentsRegistry = new ConcurrentHashMap<>();
88 reporter.start(10, TimeUnit.SECONDS);
pankajf6577b62014-10-02 16:38:38 -070089 }
90
91 @Deactivate
92 public void deactivate() {
pankaj9e34ff22014-10-06 13:21:03 -070093 reporter.stop();
pankajf6577b62014-10-02 16:38:38 -070094 }
95
pankaj390abbc2014-10-01 17:01:05 -070096 /**
97 * Registers a component.
98 *
99 * @param name name of the Component to register
100 * @return MetricsComponent object that can be used to create Metrics.
101 */
pankaj3855bcb2014-10-01 18:17:31 -0700102 @Override
pankaj390abbc2014-10-01 17:01:05 -0700103 public MetricsComponent registerComponent(final String name) {
104 MetricsComponent component = componentsRegistry.get(name);
105 if (component == null) {
106 final MetricsComponent createdComponent = new MetricsComponent(name);
107 component = componentsRegistry.putIfAbsent(name, createdComponent);
108 if (component == null) {
109 component = createdComponent;
110 }
111 }
112 return component;
113 }
114
115 /**
116 * Generates a name for a Metric from its component and feature.
117 *
118 * @param component component the metric is defined in
119 * @param feature feature the metric is defined in
120 * @param metricName local name of the metric
121 *
122 * @return full name of the metric
123 */
pankaj3855bcb2014-10-01 18:17:31 -0700124 private String generateName(final MetricsComponent component,
pankaj390abbc2014-10-01 17:01:05 -0700125 final MetricsFeature feature,
126 final String metricName) {
127 return MetricRegistry.name(component.getName(),
128 feature.getName(),
129 metricName);
130 }
131
132 /**
133 * Creates a Counter metric.
134 *
135 * @param component component the Counter is defined in
136 * @param feature feature the Counter is defined in
137 * @param metricName local name of the metric
138 * @return the created Counter Meteric
139 */
pankaj3855bcb2014-10-01 18:17:31 -0700140 @Override
pankaj390abbc2014-10-01 17:01:05 -0700141 public Counter createCounter(final MetricsComponent component,
142 final MetricsFeature feature,
143 final String metricName) {
144 final String name = generateName(component, feature, metricName);
145 return metricsRegistry.counter(name);
146 }
147
148 /**
149 * Creates a Histogram metric.
150 *
151 * @param component component the Histogram is defined in
152 * @param feature feature the Histogram is defined in
153 * @param metricName local name of the metric
154 * @return the created Histogram Metric
155 */
pankaj3855bcb2014-10-01 18:17:31 -0700156 @Override
pankaj390abbc2014-10-01 17:01:05 -0700157 public Histogram createHistogram(final MetricsComponent component,
158 final MetricsFeature feature,
159 final String metricName) {
160 final String name = generateName(component, feature, metricName);
161 return metricsRegistry.histogram(name);
162 }
163
164 /**
165 * Creates a Timer metric.
166 *
167 * @param component component the Timer is defined in
168 * @param feature feature the Timeer is defined in
169 * @param metricName local name of the metric
170 * @return the created Timer Metric
171 */
pankaj3855bcb2014-10-01 18:17:31 -0700172 @Override
pankaj390abbc2014-10-01 17:01:05 -0700173 public Timer createTimer(final MetricsComponent component,
174 final MetricsFeature feature,
175 final String metricName) {
176 final String name = generateName(component, feature, metricName);
177 return metricsRegistry.timer(name);
178 }
179
180 /**
181 * Creates a Meter metric.
182 *
183 * @param component component the Meter is defined in
184 * @param feature feature the Meter is defined in
185 * @param metricName local name of the metric
186 * @return the created Meter Metric
187 */
pankaj3855bcb2014-10-01 18:17:31 -0700188 @Override
pankaj390abbc2014-10-01 17:01:05 -0700189 public Meter createMeter(final MetricsComponent component,
190 final MetricsFeature feature,
191 final String metricName) {
192 final String name = generateName(component, feature, metricName);
193 return metricsRegistry.meter(name);
194 }
195
196 /**
197 * Registers an already created Metric. This is used for situation where a
198 * caller needs to allocate its own Metric, but still register it with the
199 * system.
200 *
201 * @param <T> Metric type
202 * @param component component the Metric is defined in
203 * @param feature feature the Metric is defined in
204 * @param metricName local name of the metric
205 * @param metric Metric to register
206 * @return the registered Metric
207 */
pankaj3855bcb2014-10-01 18:17:31 -0700208 @Override
pankaj390abbc2014-10-01 17:01:05 -0700209 public <T extends Metric> T registerMetric(
210 final MetricsComponent component,
211 final MetricsFeature feature,
212 final String metricName,
213 final T metric) {
214 final String name = generateName(component, feature, metricName);
215 metricsRegistry.register(name, metric);
216 return metric;
217 }
218
219 /**
220 * Fetches the existing Timers.
221 *
222 * @param filter filter to use to select Timers
223 * @return a map of the Timers that match the filter, with the key as the
224 * name String to the Timer.
225 */
pankaj3855bcb2014-10-01 18:17:31 -0700226 @Override
pankaj390abbc2014-10-01 17:01:05 -0700227 public Map<String, Timer> getTimers(final MetricFilter filter) {
228 return metricsRegistry.getTimers(filter);
229 }
230
231 /**
232 * Fetches the existing Gauges.
233 *
234 * @param filter filter to use to select Gauges
235 * @return a map of the Gauges that match the filter, with the key as the
236 * name String to the Gauge.
237 */
pankaj3855bcb2014-10-01 18:17:31 -0700238 @Override
pankaj390abbc2014-10-01 17:01:05 -0700239 public Map<String, Gauge> getGauges(final MetricFilter filter) {
240 return metricsRegistry.getGauges(filter);
241 }
242
243 /**
244 * Fetches the existing Counters.
245 *
246 * @param filter filter to use to select Counters
247 * @return a map of the Counters that match the filter, with the key as the
248 * name String to the Counter.
249 */
pankaj3855bcb2014-10-01 18:17:31 -0700250 @Override
pankaj390abbc2014-10-01 17:01:05 -0700251 public Map<String, Counter> getCounters(final MetricFilter filter) {
252 return metricsRegistry.getCounters(filter);
253 }
254
255 /**
256 * Fetches the existing Meters.
257 *
258 * @param filter filter to use to select Meters
259 * @return a map of the Meters that match the filter, with the key as the
260 * name String to the Meter.
261 */
pankaj3855bcb2014-10-01 18:17:31 -0700262 @Override
pankaj390abbc2014-10-01 17:01:05 -0700263 public Map<String, Meter> getMeters(final MetricFilter filter) {
264 return metricsRegistry.getMeters(filter);
265 }
266
267 /**
268 * Fetches the existing Histograms.
269 *
270 * @param filter filter to use to select Histograms
271 * @return a map of the Histograms that match the filter, with the key as the
272 * name String to the Histogram.
273 */
pankaj3855bcb2014-10-01 18:17:31 -0700274 @Override
pankaj390abbc2014-10-01 17:01:05 -0700275 public Map<String, Histogram> getHistograms(final MetricFilter filter) {
276 return metricsRegistry.getHistograms(filter);
277 }
278
279 /**
280 * Removes all Metrics that match a given filter.
281 *
282 * @param filter filter to use to select the Metrics to remove.
283 */
pankaj3855bcb2014-10-01 18:17:31 -0700284 @Override
pankaj390abbc2014-10-01 17:01:05 -0700285 public void removeMatching(final MetricFilter filter) {
286 metricsRegistry.removeMatching(filter);
287 }
288}
289