blob: 61dd14cc16dc53db8bac6c6089331e5704abc4a5 [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;
Jian Li55cbd5c2016-04-06 09:50:20 -070023import org.onlab.metrics.MetricsService;
24import org.onlab.util.Tools;
25import org.onosproject.cfg.ComponentConfigService;
26import org.onosproject.core.CoreService;
27import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070028import org.osgi.service.component.annotations.Activate;
29import org.osgi.service.component.annotations.Component;
30import org.osgi.service.component.annotations.Deactivate;
31import org.osgi.service.component.annotations.Modified;
32import org.osgi.service.component.annotations.Reference;
33import org.osgi.service.component.annotations.ReferenceCardinality;
Jian Li55cbd5c2016-04-06 09:50:20 -070034import org.slf4j.Logger;
35
36import java.net.InetSocketAddress;
37import java.util.Dictionary;
38import java.util.concurrent.TimeUnit;
39
40import static org.slf4j.LoggerFactory.getLogger;
41
42/**
43 * A metric report that reports all metrics value to graphite monitoring server.
44 */
45@Component(immediate = true)
46public class DefaultGraphiteMetricsReporter implements GraphiteMetricsReporter {
47
48 private final Logger log = getLogger(getClass());
49
50 private static final TimeUnit REPORT_TIME_UNIT = TimeUnit.MINUTES;
51 private static final int DEFAULT_REPORT_PERIOD = 1;
52
53 private static final String DEFAULT_METRIC_NAMES = "default";
54 private static final String DEFAULT_ADDRESS = "localhost";
55 private static final int DEFAULT_PORT = 2003;
56 private static final String DEFAULT_METRIC_NAME_PREFIX = "onos";
57
58
Ray Milkeyd84f89b2018-08-17 14:54:17 -070059 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li55cbd5c2016-04-06 09:50:20 -070060 protected CoreService coreService;
61
Ray Milkeyd84f89b2018-08-17 14:54:17 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li55cbd5c2016-04-06 09:50:20 -070063 protected MetricsService metricsService;
64
Ray Milkeyd84f89b2018-08-17 14:54:17 -070065 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li55cbd5c2016-04-06 09:50:20 -070066 protected ComponentConfigService cfgService;
67
Ray Milkeyd84f89b2018-08-17 14:54:17 -070068 //@Property(name = "monitorAll", boolValue = true,
69 // label = "Enable to monitor all of metrics stored in metric registry default is true")
Jian Li55cbd5c2016-04-06 09:50:20 -070070 protected boolean monitorAll = true;
71
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072 //@Property(name = "metricNames", value = DEFAULT_METRIC_NAMES,
73 // label = "Names of metric to be monitored; default metric names are 'default'")
Jian Li55cbd5c2016-04-06 09:50:20 -070074 protected String metricNames = DEFAULT_METRIC_NAMES;
75
Ray Milkeyd84f89b2018-08-17 14:54:17 -070076 //@Property(name = "address", value = DEFAULT_ADDRESS,
77 // label = "IP address of graphite monitoring server; default is localhost")
Jian Li55cbd5c2016-04-06 09:50:20 -070078 protected String address = DEFAULT_ADDRESS;
79
Ray Milkeyd84f89b2018-08-17 14:54:17 -070080 //@Property(name = "port", intValue = DEFAULT_PORT,
81 // label = "Port number of graphite monitoring server; default is 2003")
Jian Li55cbd5c2016-04-06 09:50:20 -070082 protected int port = DEFAULT_PORT;
83
Ray Milkeyd84f89b2018-08-17 14:54:17 -070084 //@Property(name = "reportPeriod", intValue = DEFAULT_REPORT_PERIOD,
85 // label = "Reporting period of graphite monitoring server; default is 1")
Jian Li55cbd5c2016-04-06 09:50:20 -070086 protected int reportPeriod = DEFAULT_REPORT_PERIOD;
87
Ray Milkeyd84f89b2018-08-17 14:54:17 -070088 //@Property(name = "metricNamePrefix", value = DEFAULT_METRIC_NAME_PREFIX,
89 // label = "Prefix of metric name for graphite back-end server; default is 'onos'")
Jian Li55cbd5c2016-04-06 09:50:20 -070090 protected String metricNamePrefix = DEFAULT_METRIC_NAME_PREFIX;
91
92 private Graphite graphite;
93 private GraphiteReporter graphiteReporter;
94
95 @Activate
96 public void activate() {
97 cfgService.registerProperties(getClass());
98 coreService.registerApplication("org.onosproject.graphitemetrics");
99 metricsService.registerReporter(this);
100
101 startReport();
102 log.info("Started");
103 }
104
105 @Deactivate
106 public void deactivate() {
107 cfgService.unregisterProperties(getClass(), false);
108
109 stopReport();
110 metricsService.unregisterReporter(this);
111
112 log.info("Stopped");
113 }
114
115 @Modified
116 public void modified(ComponentContext context) {
117 readComponentConfiguration(context);
118
119 // Restarts reporting
120 stopReport();
121 startReport();
122 }
123
124 public void startReport() {
125 configGraphite();
126 graphiteReporter = buildReporter(graphite);
Jian Li279130d2016-04-06 16:29:44 -0700127
128 try {
sangyun-hanf78f17b2016-04-25 15:22:12 +0900129 graphiteReporter.start(reportPeriod, REPORT_TIME_UNIT);
Jian Li279130d2016-04-06 16:29:44 -0700130 } catch (Exception e) {
131 log.error("Errors during reporting to graphite, msg: {}" + e.getMessage());
132 }
133
Jian Li55cbd5c2016-04-06 09:50:20 -0700134 log.info("Start to report metrics to graphite server.");
135 }
136
137 public void stopReport() {
138 graphiteReporter.stop();
139 graphite = null;
140 graphiteReporter = null;
141 log.info("Stop reporting metrics to graphite server.");
142 }
143
144 @Override
145 public void restartReport() {
146 stopReport();
147 startReport();
148 }
149
150 @Override
151 public void notifyMetricsChange() {
152 graphiteReporter.stop();
153 graphiteReporter = buildReporter(graphite);
Jian Li279130d2016-04-06 16:29:44 -0700154
155 try {
sangyun-hanf78f17b2016-04-25 15:22:12 +0900156 graphiteReporter.start(reportPeriod, REPORT_TIME_UNIT);
Jian Li279130d2016-04-06 16:29:44 -0700157 } catch (Exception e) {
158 log.error("Errors during reporting to graphite, msg: {}" + e.getMessage());
159 }
160
Jian Li55cbd5c2016-04-06 09:50:20 -0700161 log.info("Metric registry has been changed, apply changes.");
162 }
163
164 /**
165 * Filters the metrics to only include a set of the given metrics.
166 *
167 * @param metricRegistry original metric registry
168 * @return filtered metric registry
169 */
170 protected MetricRegistry filter(MetricRegistry metricRegistry) {
171 if (!monitorAll) {
172 final MetricRegistry filtered = new MetricRegistry();
173 metricRegistry.getNames().stream().filter(name ->
174 containsName(name, metricNames)).forEach(name ->
175 filtered.register(name, metricRegistry.getMetrics().get(name)));
176 return filtered;
177 } else {
178 return metricRegistry;
179 }
180 }
181
182 /**
183 * Looks up whether the metric name contains the given prefix keywords.
184 * Note that the keywords are separated with comma as delimiter
185 *
186 * @param full the original metric name that to be compared with
187 * @param prefixes the prefix keywords that are matched against with the metric name
188 * @return boolean value that denotes whether the metric name starts with the given prefix
189 */
190 protected boolean containsName(String full, String prefixes) {
191 String[] prefixArray = StringUtils.split(prefixes, ",");
192 for (String prefix : prefixArray) {
193 if (StringUtils.startsWith(full, StringUtils.trimToEmpty(prefix))) {
194 return true;
195 }
196 }
197 return false;
198 }
199
200 /**
201 * Extracts properties from the component configuration context.
202 *
203 * @param context the component context
204 */
205 private void readComponentConfiguration(ComponentContext context) {
206 Dictionary<?, ?> properties = context.getProperties();
207
208 Boolean newMonitorAll = Tools.isPropertyEnabled(properties, "monitorAll");
209 if (newMonitorAll == null) {
210 log.info("Monitor all metrics is not configured, " +
211 "using current value of {}", monitorAll);
212 } else {
213 monitorAll = newMonitorAll;
214 log.info("Configured. Monitor all metrics is {}, ",
215 monitorAll ? "enabled" : "disabled");
216 }
217
218 String newMetricNames = Tools.get(properties, "metricNames");
219 metricNames = newMetricNames != null ? newMetricNames : DEFAULT_METRIC_NAMES;
220 log.info("Configured. Metric name is {}", metricNames);
221
222 String newAddress = Tools.get(properties, "address");
223 address = newAddress != null ? newAddress : DEFAULT_ADDRESS;
224 log.info("Configured. Graphite monitoring server address is {}", address);
225
226 Integer newPort = Tools.getIntegerProperty(properties, "port");
227 if (newPort == null) {
228 port = DEFAULT_PORT;
229 log.info("Graphite port is not configured, default value is {}", port);
230 } else {
231 port = newPort;
232 log.info("Configured. Graphite port is configured to {}", port);
233 }
234
235 Integer newReportPeriod = Tools.getIntegerProperty(properties, "reportPeriod");
236 if (newReportPeriod == null) {
237 reportPeriod = DEFAULT_REPORT_PERIOD;
238 log.info("Report period of graphite server is not configured, " +
239 "default value is {}", reportPeriod);
240 } else {
241 reportPeriod = newReportPeriod;
242 log.info("Configured. Report period of graphite server" +
243 " is configured to {}", reportPeriod);
244 }
245
246 String newMetricNamePrefix = Tools.get(properties, "metricNamePrefix");
247 metricNamePrefix = newMetricNamePrefix != null ?
248 newMetricNamePrefix : DEFAULT_METRIC_NAME_PREFIX;
249
250 }
251
252 /**
253 * Configures parameters for graphite config.
254 */
255 private void configGraphite() {
256 try {
257 graphite = new Graphite(new InetSocketAddress(address, port));
258 } catch (Exception e) {
259 log.error("Fail to connect to given graphite server! : " + e.getMessage());
260 }
261 }
262
263 /**
264 * Builds reporter with the given graphite config.
265 *
266 * @param graphiteCfg graphite config
267 * @return reporter
268 */
269 private GraphiteReporter buildReporter(Graphite graphiteCfg) {
270 MetricRegistry metricRegistry = metricsService.getMetricRegistry();
271 return GraphiteReporter.forRegistry(filter(metricRegistry))
272 .prefixedWith(metricNamePrefix)
273 .convertRatesTo(TimeUnit.SECONDS)
274 .convertDurationsTo(TimeUnit.MILLISECONDS)
275 .build(graphiteCfg);
276 }
277}