blob: 1b03794886c9897f6d5316ab084fdf06af95f163 [file] [log] [blame]
sangyun-han805219a2016-03-26 12:58:27 +09001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
sangyun-han805219a2016-03-26 12:58:27 +09003 *
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.util.Tools;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onlab.metrics.MetricsService;
34import org.onosproject.cfg.ComponentConfigService;
35import org.osgi.service.component.ComponentContext;
36import org.slf4j.Logger;
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 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
94 private ApplicationId appId;
95 private Graphite graphite;
96 private GraphiteReporter graphiteReporter;
97
98 @Activate
99 public void activate() {
100 cfgService.registerProperties(getClass());
101 appId = coreService.registerApplication("org.onosproject.metrics.reporter");
102
103 startReport();
104 log.info("Started");
105 }
106
107 @Deactivate
108 public void deactivate() {
109 cfgService.unregisterProperties(getClass(), false);
110
111 stopReport();
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 try {
126 graphite = new Graphite(new InetSocketAddress(address, port));
127
128 MetricRegistry metricRegistry = metricsService.getMetricRegistry();
129
130 graphiteReporter = GraphiteReporter.forRegistry(filter(metricRegistry))
131 .prefixedWith(metricNamePrefix)
132 .convertRatesTo(TimeUnit.SECONDS)
133 .convertDurationsTo(TimeUnit.MILLISECONDS)
134 .build(graphite);
135
136 graphiteReporter.start(reportPeriod, REPORT_TIME_UNIT);
137 log.info("Start to report metrics to graphite.");
138 } catch (Exception e) {
139 log.error("Fail to connect to given graphite server! : " + e.getMessage());
140 }
141 }
142
143 public void stopReport() {
144 graphiteReporter.stop();
145 graphite = null;
146 graphiteReporter = null;
147 }
148
149 /**
150 * Filters the metrics to only include a set of the given metrics.
151 *
152 * @param metricRegistry original metric registry
153 * @return filtered metric registry
154 */
155 protected MetricRegistry filter(MetricRegistry metricRegistry) {
156 if (!monitorAll) {
157 final MetricRegistry filtered = new MetricRegistry();
158 metricRegistry.getNames().stream().filter(name ->
159 containsName(name, metricNames)).forEach(name ->
160 filtered.register(name, metricRegistry.getMetrics().get(name)));
161 return filtered;
162 } else {
163 return metricRegistry;
164 }
165 }
166
167 /**
168 * Looks up whether the metric name contains the given prefix keywords.
169 * Note that the keywords are separated with comma as delimiter
170 *
171 * @param full the original metric name that to be compared with
172 * @param prefixes the prefix keywords that are matched against with the metric name
173 * @return boolean value that denotes whether the metric name starts with the given prefix
174 */
175 protected boolean containsName(String full, String prefixes) {
176 String[] prefixArray = StringUtils.split(prefixes, ",");
177 for (String prefix : prefixArray) {
178 if (StringUtils.startsWith(full, StringUtils.trimToEmpty(prefix))) {
179 return true;
180 }
181 }
182 return false;
183 }
184
185 /**
186 * Extracts properties from the component configuration context.
187 *
188 * @param context the component context
189 */
190 private void readComponentConfiguration(ComponentContext context) {
191 Dictionary<?, ?> properties = context.getProperties();
192
193 Boolean newMonitorAll = Tools.isPropertyEnabled(properties, "monitorAll");
194 if (newMonitorAll == null) {
195 log.info("Monitor all metrics is not configured, " +
196 "using current value of {}", monitorAll);
197 } else {
198 monitorAll = newMonitorAll;
199 log.info("Configured. Monitor all metrics is {}, ",
200 monitorAll ? "enabled" : "disabled");
201 }
202
203 String newMetricNames = Tools.get(properties, "metricNames");
204 metricNames = newMetricNames != null ? newMetricNames : DEFAULT_METRIC_NAMES;
205 log.info("Configured. Metric name is {}", metricNames);
206
207 String newAddress = Tools.get(properties, "address");
208 address = newAddress != null ? newAddress : DEFAULT_ADDRESS;
209 log.info("Configured. Graphite monitoring server address is {}", address);
210
211 Integer newPort = Tools.getIntegerProperty(properties, "port");
212 if (newPort == null) {
213 port = DEFAULT_PORT;
214 log.info("Graphite port is not configured, default value is {}", port);
215 } else {
216 port = newPort;
217 log.info("Configured. Graphite port is configured to {}", port);
218 }
219
220 Integer newReportPeriod = Tools.getIntegerProperty(properties, "reportPeriod");
221 if (newReportPeriod == null) {
222 reportPeriod = DEFAULT_REPORT_PERIOD;
223 log.info("Report period of graphite server is not configured, " +
224 "default value is {}", reportPeriod);
225 } else {
226 reportPeriod = newReportPeriod;
227 log.info("Configured. Report period of graphite server" +
228 " is configured to {}", reportPeriod);
229 }
230
231 String newMetricNamePrefix = Tools.get(properties, "metricNamePrefix");
232 metricNamePrefix = newMetricNamePrefix != null ?
233 newMetricNamePrefix : DEFAULT_METRIC_NAME_PREFIX;
234
235 }
236}