blob: c4995a52d6ec2ecf3406b96d4ace9d01ed0db6cb [file] [log] [blame]
Jian Li55cbd5c2016-04-06 09:50:20 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Li55cbd5c2016-04-06 09:50:20 -07003 *
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);
Jian Li279130d2016-04-06 16:29:44 -0700128
129 try {
sangyun-hanf78f17b2016-04-25 15:22:12 +0900130 graphiteReporter.start(reportPeriod, REPORT_TIME_UNIT);
Jian Li279130d2016-04-06 16:29:44 -0700131 } catch (Exception e) {
132 log.error("Errors during reporting to graphite, msg: {}" + e.getMessage());
133 }
134
Jian Li55cbd5c2016-04-06 09:50:20 -0700135 log.info("Start to report metrics to graphite server.");
136 }
137
138 public void stopReport() {
139 graphiteReporter.stop();
140 graphite = null;
141 graphiteReporter = null;
142 log.info("Stop reporting metrics to graphite server.");
143 }
144
145 @Override
146 public void restartReport() {
147 stopReport();
148 startReport();
149 }
150
151 @Override
152 public void notifyMetricsChange() {
153 graphiteReporter.stop();
154 graphiteReporter = buildReporter(graphite);
Jian Li279130d2016-04-06 16:29:44 -0700155
156 try {
sangyun-hanf78f17b2016-04-25 15:22:12 +0900157 graphiteReporter.start(reportPeriod, REPORT_TIME_UNIT);
Jian Li279130d2016-04-06 16:29:44 -0700158 } catch (Exception e) {
159 log.error("Errors during reporting to graphite, msg: {}" + e.getMessage());
160 }
161
Jian Li55cbd5c2016-04-06 09:50:20 -0700162 log.info("Metric registry has been changed, apply changes.");
163 }
164
165 /**
166 * Filters the metrics to only include a set of the given metrics.
167 *
168 * @param metricRegistry original metric registry
169 * @return filtered metric registry
170 */
171 protected MetricRegistry filter(MetricRegistry metricRegistry) {
172 if (!monitorAll) {
173 final MetricRegistry filtered = new MetricRegistry();
174 metricRegistry.getNames().stream().filter(name ->
175 containsName(name, metricNames)).forEach(name ->
176 filtered.register(name, metricRegistry.getMetrics().get(name)));
177 return filtered;
178 } else {
179 return metricRegistry;
180 }
181 }
182
183 /**
184 * Looks up whether the metric name contains the given prefix keywords.
185 * Note that the keywords are separated with comma as delimiter
186 *
187 * @param full the original metric name that to be compared with
188 * @param prefixes the prefix keywords that are matched against with the metric name
189 * @return boolean value that denotes whether the metric name starts with the given prefix
190 */
191 protected boolean containsName(String full, String prefixes) {
192 String[] prefixArray = StringUtils.split(prefixes, ",");
193 for (String prefix : prefixArray) {
194 if (StringUtils.startsWith(full, StringUtils.trimToEmpty(prefix))) {
195 return true;
196 }
197 }
198 return false;
199 }
200
201 /**
202 * Extracts properties from the component configuration context.
203 *
204 * @param context the component context
205 */
206 private void readComponentConfiguration(ComponentContext context) {
207 Dictionary<?, ?> properties = context.getProperties();
208
209 Boolean newMonitorAll = Tools.isPropertyEnabled(properties, "monitorAll");
210 if (newMonitorAll == null) {
211 log.info("Monitor all metrics is not configured, " +
212 "using current value of {}", monitorAll);
213 } else {
214 monitorAll = newMonitorAll;
215 log.info("Configured. Monitor all metrics is {}, ",
216 monitorAll ? "enabled" : "disabled");
217 }
218
219 String newMetricNames = Tools.get(properties, "metricNames");
220 metricNames = newMetricNames != null ? newMetricNames : DEFAULT_METRIC_NAMES;
221 log.info("Configured. Metric name is {}", metricNames);
222
223 String newAddress = Tools.get(properties, "address");
224 address = newAddress != null ? newAddress : DEFAULT_ADDRESS;
225 log.info("Configured. Graphite monitoring server address is {}", address);
226
227 Integer newPort = Tools.getIntegerProperty(properties, "port");
228 if (newPort == null) {
229 port = DEFAULT_PORT;
230 log.info("Graphite port is not configured, default value is {}", port);
231 } else {
232 port = newPort;
233 log.info("Configured. Graphite port is configured to {}", port);
234 }
235
236 Integer newReportPeriod = Tools.getIntegerProperty(properties, "reportPeriod");
237 if (newReportPeriod == null) {
238 reportPeriod = DEFAULT_REPORT_PERIOD;
239 log.info("Report period of graphite server is not configured, " +
240 "default value is {}", reportPeriod);
241 } else {
242 reportPeriod = newReportPeriod;
243 log.info("Configured. Report period of graphite server" +
244 " is configured to {}", reportPeriod);
245 }
246
247 String newMetricNamePrefix = Tools.get(properties, "metricNamePrefix");
248 metricNamePrefix = newMetricNamePrefix != null ?
249 newMetricNamePrefix : DEFAULT_METRIC_NAME_PREFIX;
250
251 }
252
253 /**
254 * Configures parameters for graphite config.
255 */
256 private void configGraphite() {
257 try {
258 graphite = new Graphite(new InetSocketAddress(address, port));
259 } catch (Exception e) {
260 log.error("Fail to connect to given graphite server! : " + e.getMessage());
261 }
262 }
263
264 /**
265 * Builds reporter with the given graphite config.
266 *
267 * @param graphiteCfg graphite config
268 * @return reporter
269 */
270 private GraphiteReporter buildReporter(Graphite graphiteCfg) {
271 MetricRegistry metricRegistry = metricsService.getMetricRegistry();
272 return GraphiteReporter.forRegistry(filter(metricRegistry))
273 .prefixedWith(metricNamePrefix)
274 .convertRatesTo(TimeUnit.SECONDS)
275 .convertDurationsTo(TimeUnit.MILLISECONDS)
276 .build(graphiteCfg);
277 }
278}