blob: cce61029313fcf3306f424f5a2b1adb329340215 [file] [log] [blame]
Jian Lie1d97c92016-03-22 10:21:44 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Lie1d97c92016-03-22 10:21:44 -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.influxdbmetrics;
17
18import com.codahale.metrics.MetricRegistry;
19import com.izettle.metrics.influxdb.InfluxDbHttpSender;
20import com.izettle.metrics.influxdb.InfluxDbReporter;
21import org.apache.commons.lang.StringUtils;
Jian Lie1d97c92016-03-22 10:21:44 -070022import org.onlab.metrics.MetricsService;
23import org.onlab.util.Tools;
24import org.onosproject.cfg.ComponentConfigService;
25import org.onosproject.cluster.ClusterService;
26import org.onosproject.cluster.ControllerNode;
27import org.onosproject.core.CoreService;
28import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070029import org.osgi.service.component.annotations.Activate;
30import org.osgi.service.component.annotations.Component;
31import org.osgi.service.component.annotations.Deactivate;
32import org.osgi.service.component.annotations.Modified;
33import org.osgi.service.component.annotations.Reference;
34import org.osgi.service.component.annotations.ReferenceCardinality;
Jian Lie1d97c92016-03-22 10:21:44 -070035import org.slf4j.Logger;
36
37import java.util.Dictionary;
38import java.util.concurrent.TimeUnit;
39
Ray Milkey4694e062018-10-31 13:17:18 -070040import static org.onosproject.influxdbmetrics.OsgiPropertyConstants.METRIC_NAMES;
41import static org.onosproject.influxdbmetrics.OsgiPropertyConstants.METRIC_NAMES_DEFAULT;
42import static org.onosproject.influxdbmetrics.OsgiPropertyConstants.MONITOR_ALL;
43import static org.onosproject.influxdbmetrics.OsgiPropertyConstants.MONITOR_ALL_DEFAULT;
Jian Lie1d97c92016-03-22 10:21:44 -070044import static org.slf4j.LoggerFactory.getLogger;
45
46/**
47 * A Metric reporter that reports all metrics value to influxDB server.
48 */
Ray Milkey4694e062018-10-31 13:17:18 -070049@Component(
50 immediate = true,
51 service = InfluxDbMetricsReporter.class,
52 property = {
53 MONITOR_ALL + ":Boolean=" + MONITOR_ALL_DEFAULT,
54 METRIC_NAMES + "=" + METRIC_NAMES_DEFAULT
55 }
56)
Jian Lie1d97c92016-03-22 10:21:44 -070057public class DefaultInfluxDbMetricsReporter implements InfluxDbMetricsReporter {
58 private final Logger log = getLogger(getClass());
59
60 private static final int REPORT_PERIOD = 1;
61 private static final TimeUnit REPORT_TIME_UNIT = TimeUnit.MINUTES;
62
63 private static final String DEFAULT_PROTOCOL = "http";
Ray Milkey4694e062018-10-31 13:17:18 -070064
Jian Lie1d97c92016-03-22 10:21:44 -070065 private static final String SEPARATOR = ":";
66 private static final int DEFAULT_CONN_TIMEOUT = 1000;
67 private static final int DEFAULT_READ_TIMEOUT = 1000;
68
Ray Milkeyd84f89b2018-08-17 14:54:17 -070069 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1d97c92016-03-22 10:21:44 -070070 protected CoreService coreService;
71
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1d97c92016-03-22 10:21:44 -070073 protected MetricsService metricsService;
74
Ray Milkeyd84f89b2018-08-17 14:54:17 -070075 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1d97c92016-03-22 10:21:44 -070076 protected ComponentConfigService cfgService;
77
Ray Milkeyd84f89b2018-08-17 14:54:17 -070078 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Lie1d97c92016-03-22 10:21:44 -070079 protected ClusterService clusterService;
80
Ray Milkey4694e062018-10-31 13:17:18 -070081 /** Enable to monitor all of metrics stored in metric registry default is true. */
82 protected boolean monitorAll = MONITOR_ALL_DEFAULT;
Jian Lie1d97c92016-03-22 10:21:44 -070083
Ray Milkey4694e062018-10-31 13:17:18 -070084 /** Names of metric to be monitored in third party monitoring server; default metric names are 'default'. */
85 protected String metricNames = METRIC_NAMES_DEFAULT;
Jian Lie1d97c92016-03-22 10:21:44 -070086
87 protected String address;
88 protected int port;
89 protected String database;
90 protected String username;
91 protected String password;
92
93 private InfluxDbReporter influxDbReporter;
94 private InfluxDbHttpSender influxDbHttpSender;
95
96 @Activate
97 public void activate() {
98 cfgService.registerProperties(getClass());
99 coreService.registerApplication("org.onosproject.influxdbmetrics");
Jian Li55cbd5c2016-04-06 09:50:20 -0700100 metricsService.registerReporter(this);
101
102 startReport();
Jian Lie1d97c92016-03-22 10:21:44 -0700103
104 log.info("Started");
105 }
106
107 @Deactivate
108 public void deactivate() {
109 cfgService.unregisterProperties(getClass(), false);
110
Jian Li55cbd5c2016-04-06 09:50:20 -0700111 stopReport();
112 metricsService.unregisterReporter(this);
113
Jian Lie1d97c92016-03-22 10:21:44 -0700114 log.info("Stopped");
115 }
116
117 @Modified
118 public void modified(ComponentContext context) {
119 readComponentConfiguration(context);
120 restartReport();
121 }
122
123 @Override
124 public void startReport() {
Jian Li55cbd5c2016-04-06 09:50:20 -0700125 configSender();
126 influxDbReporter = buildReporter(influxDbHttpSender);
Jian Li279130d2016-04-06 16:29:44 -0700127
128 try {
129 influxDbReporter.start(REPORT_PERIOD, REPORT_TIME_UNIT);
130 } catch (Exception e) {
131 log.error("Errors during reporting to InfluxDB, msg: {}" + e.getMessage());
132 }
Jian Li55cbd5c2016-04-06 09:50:20 -0700133 log.info("Start to report metrics to influxDB.");
Jian Lie1d97c92016-03-22 10:21:44 -0700134 }
135
136 @Override
137 public void stopReport() {
138 influxDbReporter.stop();
139 influxDbHttpSender = null;
140 influxDbReporter = null;
141 log.info("Stop reporting metrics to influxDB.");
142 }
143
144 @Override
145 public void restartReport() {
146 stopReport();
147 startReport();
148 }
149
150 @Override
Jian Li55cbd5c2016-04-06 09:50:20 -0700151 public void notifyMetricsChange() {
152 influxDbReporter.stop();
153 influxDbReporter = buildReporter(influxDbHttpSender);
Jian Li279130d2016-04-06 16:29:44 -0700154
155 try {
156 influxDbReporter.start(REPORT_PERIOD, REPORT_TIME_UNIT);
157 } catch (Exception e) {
158 log.error("Errors during reporting to InfluxDB, 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 @Override
Jian Lie1d97c92016-03-22 10:21:44 -0700165 public void config(String address, int port, String database,
166 String username, String password) {
167 this.address = address;
168 this.port = port;
169 this.database = database;
170 this.username = username;
171 this.password = password;
172 }
173
174 /**
175 * Filters the metrics to only include a set of the given metrics.
176 *
177 * @param metricRegistry original metric registry
178 * @return filtered metric registry
179 */
180 protected MetricRegistry filter(MetricRegistry metricRegistry) {
181 if (!monitorAll) {
182 final MetricRegistry filtered = new MetricRegistry();
183 metricRegistry.getNames().stream().filter(name ->
184 containsName(name, metricNames)).forEach(name ->
185 filtered.register(name, metricRegistry.getMetrics().get(name)));
186 return filtered;
187 } else {
188 return metricRegistry;
189 }
190 }
191
192 /**
193 * Appends node IP prefix to all performance metrics.
194 *
195 * @param metricRegistry original metric registry
196 * @return prefix added metric registry
197 */
198 protected MetricRegistry addHostPrefix(MetricRegistry metricRegistry) {
199 MetricRegistry moddedRegistry = new MetricRegistry();
200 ControllerNode node = clusterService.getLocalNode();
201 String prefix = node.id().id() + ".";
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700202 metricRegistry.getNames().forEach(name ->
Jian Lie1d97c92016-03-22 10:21:44 -0700203 moddedRegistry.register(prefix + name, metricRegistry.getMetrics().get(name)));
204
205 return moddedRegistry;
206 }
207
208 /**
209 * Looks up whether the metric name contains the given prefix keywords.
210 * Note that the keywords are separated with comma as delimiter.
211 *
212 * @param full the original metric name that to be compared with
213 * @param prefixes the prefix keywords that are matched against with the metric name
214 * @return boolean value that denotes whether the metric name starts with the given prefix
215 */
216 protected boolean containsName(String full, String prefixes) {
217 String[] prefixArray = StringUtils.split(prefixes, ",");
218 for (String prefix : prefixArray) {
219 if (StringUtils.startsWith(full, StringUtils.trimToEmpty(prefix))) {
220 return true;
221 }
222 }
223 return false;
224 }
225
226 /**
227 * Extracts properties from the component configuration context.
228 *
229 * @param context the component context
230 */
231 private void readComponentConfiguration(ComponentContext context) {
232 Dictionary<?, ?> properties = context.getProperties();
233
Ray Milkey4694e062018-10-31 13:17:18 -0700234 String metricNameStr = Tools.get(properties, METRIC_NAMES);
235 metricNames = metricNameStr != null ? metricNameStr : METRIC_NAMES_DEFAULT;
Jian Lie1d97c92016-03-22 10:21:44 -0700236 log.info("Configured. Metric name is {}", metricNames);
237
Ray Milkey4694e062018-10-31 13:17:18 -0700238 Boolean monitorAllEnabled = Tools.isPropertyEnabled(properties, MONITOR_ALL);
Jian Lie1d97c92016-03-22 10:21:44 -0700239 if (monitorAllEnabled == null) {
240 log.info("Monitor all metrics is not configured, " +
241 "using current value of {}", monitorAll);
242 } else {
243 monitorAll = monitorAllEnabled;
244 log.info("Configured. Monitor all metrics is {}",
245 monitorAll ? "enabled" : "disabled");
246 }
247 }
Jian Li55cbd5c2016-04-06 09:50:20 -0700248
249 /**
250 * Configures parameters for sender.
251 */
252 private void configSender() {
253 try {
254 influxDbHttpSender = new InfluxDbHttpSender(DEFAULT_PROTOCOL, address,
255 port, database, username + SEPARATOR + password, REPORT_TIME_UNIT,
256 DEFAULT_CONN_TIMEOUT, DEFAULT_READ_TIMEOUT);
257 } catch (Exception e) {
258 log.error("Fail to connect to given influxDB server!");
259 }
260 }
261
262 /**
263 * Builds reporter with the given sender.
264 *
265 * @param sender sender
266 * @return reporter
267 */
268 private InfluxDbReporter buildReporter(InfluxDbHttpSender sender) {
269 MetricRegistry mr = metricsService.getMetricRegistry();
270 return InfluxDbReporter.forRegistry(addHostPrefix(filter(mr)))
271 .convertRatesTo(TimeUnit.SECONDS)
272 .convertDurationsTo(TimeUnit.MILLISECONDS)
273 .build(sender);
274 }
Jian Lie1d97c92016-03-22 10:21:44 -0700275}