blob: 89453a7a15d30e90de8e36f242977ae77685873a [file] [log] [blame]
Jian Li55cbd5c2016-04-06 09:50:20 -07001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.graphitemetrics;
17
18
19import com.codahale.metrics.MetricRegistry;
20import com.codahale.metrics.graphite.Graphite;
21import com.codahale.metrics.graphite.GraphiteReporter;
22import org.apache.commons.lang.StringUtils;
23import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Modified;
27import org.apache.felix.scr.annotations.Property;
28import org.apache.felix.scr.annotations.Reference;
29import org.apache.felix.scr.annotations.ReferenceCardinality;
30import org.onlab.metrics.MetricsService;
31import org.onlab.util.Tools;
32import org.onosproject.cfg.ComponentConfigService;
33import org.onosproject.core.CoreService;
34import org.osgi.service.component.ComponentContext;
35import org.slf4j.Logger;
36
37import java.net.InetSocketAddress;
38import java.util.Dictionary;
39import java.util.concurrent.TimeUnit;
40
41import static org.slf4j.LoggerFactory.getLogger;
42
43/**
44 * A metric report that reports all metrics value to graphite monitoring server.
45 */
46@Component(immediate = true)
47public class DefaultGraphiteMetricsReporter implements GraphiteMetricsReporter {
48
49 private final Logger log = getLogger(getClass());
50
51 private static final TimeUnit REPORT_TIME_UNIT = TimeUnit.MINUTES;
52 private static final int DEFAULT_REPORT_PERIOD = 1;
53
54 private static final String DEFAULT_METRIC_NAMES = "default";
55 private static final String DEFAULT_ADDRESS = "localhost";
56 private static final int DEFAULT_PORT = 2003;
57 private static final String DEFAULT_METRIC_NAME_PREFIX = "onos";
58
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected CoreService coreService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected MetricsService metricsService;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected ComponentConfigService cfgService;
68
69 @Property(name = "monitorAll", boolValue = true,
70 label = "Enable to monitor all of metrics stored in metric registry default is true")
71 protected boolean monitorAll = true;
72
73 @Property(name = "metricNames", value = DEFAULT_METRIC_NAMES,
74 label = "Names of metric to be monitored; default metric names are 'default'")
75 protected String metricNames = DEFAULT_METRIC_NAMES;
76
77 @Property(name = "address", value = DEFAULT_ADDRESS,
78 label = "IP address of graphite monitoring server; default is localhost")
79 protected String address = DEFAULT_ADDRESS;
80
81 @Property(name = "port", intValue = DEFAULT_PORT,
82 label = "Port number of graphite monitoring server; default is 2003")
83 protected int port = DEFAULT_PORT;
84
85 @Property(name = "reportPeriod", intValue = DEFAULT_REPORT_PERIOD,
86 label = "Reporting period of graphite monitoring server; default is 1")
87 protected int reportPeriod = DEFAULT_REPORT_PERIOD;
88
89 @Property(name = "metricNamePrefix", value = DEFAULT_METRIC_NAME_PREFIX,
90 label = "Prefix of metric name for graphite back-end server; default is 'onos'")
91 protected String metricNamePrefix = DEFAULT_METRIC_NAME_PREFIX;
92
93 private Graphite graphite;
94 private GraphiteReporter graphiteReporter;
95
96 @Activate
97 public void activate() {
98 cfgService.registerProperties(getClass());
99 coreService.registerApplication("org.onosproject.graphitemetrics");
100 metricsService.registerReporter(this);
101
102 startReport();
103 log.info("Started");
104 }
105
106 @Deactivate
107 public void deactivate() {
108 cfgService.unregisterProperties(getClass(), false);
109
110 stopReport();
111 metricsService.unregisterReporter(this);
112
113 log.info("Stopped");
114 }
115
116 @Modified
117 public void modified(ComponentContext context) {
118 readComponentConfiguration(context);
119
120 // Restarts reporting
121 stopReport();
122 startReport();
123 }
124
125 public void startReport() {
126 configGraphite();
127 graphiteReporter = buildReporter(graphite);
128 graphiteReporter.start(reportPeriod, REPORT_TIME_UNIT);
129 log.info("Start to report metrics to graphite server.");
130 }
131
132 public void stopReport() {
133 graphiteReporter.stop();
134 graphite = null;
135 graphiteReporter = null;
136 log.info("Stop reporting metrics to graphite server.");
137 }
138
139 @Override
140 public void restartReport() {
141 stopReport();
142 startReport();
143 }
144
145 @Override
146 public void notifyMetricsChange() {
147 graphiteReporter.stop();
148 graphiteReporter = buildReporter(graphite);
149 graphiteReporter.start(DEFAULT_REPORT_PERIOD, REPORT_TIME_UNIT);
150 log.info("Metric registry has been changed, apply changes.");
151 }
152
153 /**
154 * Filters the metrics to only include a set of the given metrics.
155 *
156 * @param metricRegistry original metric registry
157 * @return filtered metric registry
158 */
159 protected MetricRegistry filter(MetricRegistry metricRegistry) {
160 if (!monitorAll) {
161 final MetricRegistry filtered = new MetricRegistry();
162 metricRegistry.getNames().stream().filter(name ->
163 containsName(name, metricNames)).forEach(name ->
164 filtered.register(name, metricRegistry.getMetrics().get(name)));
165 return filtered;
166 } else {
167 return metricRegistry;
168 }
169 }
170
171 /**
172 * Looks up whether the metric name contains the given prefix keywords.
173 * Note that the keywords are separated with comma as delimiter
174 *
175 * @param full the original metric name that to be compared with
176 * @param prefixes the prefix keywords that are matched against with the metric name
177 * @return boolean value that denotes whether the metric name starts with the given prefix
178 */
179 protected boolean containsName(String full, String prefixes) {
180 String[] prefixArray = StringUtils.split(prefixes, ",");
181 for (String prefix : prefixArray) {
182 if (StringUtils.startsWith(full, StringUtils.trimToEmpty(prefix))) {
183 return true;
184 }
185 }
186 return false;
187 }
188
189 /**
190 * Extracts properties from the component configuration context.
191 *
192 * @param context the component context
193 */
194 private void readComponentConfiguration(ComponentContext context) {
195 Dictionary<?, ?> properties = context.getProperties();
196
197 Boolean newMonitorAll = Tools.isPropertyEnabled(properties, "monitorAll");
198 if (newMonitorAll == null) {
199 log.info("Monitor all metrics is not configured, " +
200 "using current value of {}", monitorAll);
201 } else {
202 monitorAll = newMonitorAll;
203 log.info("Configured. Monitor all metrics is {}, ",
204 monitorAll ? "enabled" : "disabled");
205 }
206
207 String newMetricNames = Tools.get(properties, "metricNames");
208 metricNames = newMetricNames != null ? newMetricNames : DEFAULT_METRIC_NAMES;
209 log.info("Configured. Metric name is {}", metricNames);
210
211 String newAddress = Tools.get(properties, "address");
212 address = newAddress != null ? newAddress : DEFAULT_ADDRESS;
213 log.info("Configured. Graphite monitoring server address is {}", address);
214
215 Integer newPort = Tools.getIntegerProperty(properties, "port");
216 if (newPort == null) {
217 port = DEFAULT_PORT;
218 log.info("Graphite port is not configured, default value is {}", port);
219 } else {
220 port = newPort;
221 log.info("Configured. Graphite port is configured to {}", port);
222 }
223
224 Integer newReportPeriod = Tools.getIntegerProperty(properties, "reportPeriod");
225 if (newReportPeriod == null) {
226 reportPeriod = DEFAULT_REPORT_PERIOD;
227 log.info("Report period of graphite server is not configured, " +
228 "default value is {}", reportPeriod);
229 } else {
230 reportPeriod = newReportPeriod;
231 log.info("Configured. Report period of graphite server" +
232 " is configured to {}", reportPeriod);
233 }
234
235 String newMetricNamePrefix = Tools.get(properties, "metricNamePrefix");
236 metricNamePrefix = newMetricNamePrefix != null ?
237 newMetricNamePrefix : DEFAULT_METRIC_NAME_PREFIX;
238
239 }
240
241 /**
242 * Configures parameters for graphite config.
243 */
244 private void configGraphite() {
245 try {
246 graphite = new Graphite(new InetSocketAddress(address, port));
247 } catch (Exception e) {
248 log.error("Fail to connect to given graphite server! : " + e.getMessage());
249 }
250 }
251
252 /**
253 * Builds reporter with the given graphite config.
254 *
255 * @param graphiteCfg graphite config
256 * @return reporter
257 */
258 private GraphiteReporter buildReporter(Graphite graphiteCfg) {
259 MetricRegistry metricRegistry = metricsService.getMetricRegistry();
260 return GraphiteReporter.forRegistry(filter(metricRegistry))
261 .prefixedWith(metricNamePrefix)
262 .convertRatesTo(TimeUnit.SECONDS)
263 .convertDurationsTo(TimeUnit.MILLISECONDS)
264 .build(graphiteCfg);
265 }
266}