blob: 32cf0cf51aeacf10841f361c3e87a98bf1800794 [file] [log] [blame]
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -07001package org.onlab.onos.metrics.topology;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.LinkedList;
6import java.util.List;
7
8import com.codahale.metrics.Gauge;
9import com.codahale.metrics.Meter;
10import com.google.common.collect.ImmutableList;
11import org.apache.felix.scr.annotations.Activate;
12import org.apache.felix.scr.annotations.Component;
13import org.apache.felix.scr.annotations.Deactivate;
14import org.apache.felix.scr.annotations.Reference;
15import org.apache.felix.scr.annotations.ReferenceCardinality;
16import org.apache.felix.scr.annotations.Service;
17import org.onlab.metrics.MetricsComponent;
18import org.onlab.metrics.MetricsFeature;
19import org.onlab.metrics.MetricsService;
20import org.onlab.onos.event.Event;
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -070021import org.onlab.onos.net.device.DeviceEvent;
22import org.onlab.onos.net.device.DeviceListener;
23import org.onlab.onos.net.device.DeviceService;
24import org.onlab.onos.net.host.HostEvent;
25import org.onlab.onos.net.host.HostListener;
26import org.onlab.onos.net.host.HostService;
27import org.onlab.onos.net.link.LinkEvent;
28import org.onlab.onos.net.link.LinkListener;
29import org.onlab.onos.net.link.LinkService;
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -070030import org.onlab.onos.net.topology.TopologyEvent;
31import org.onlab.onos.net.topology.TopologyListener;
32import org.onlab.onos.net.topology.TopologyService;
33import org.slf4j.Logger;
34
35/**
36 * ONOS Topology Metrics Application that collects topology-related metrics.
37 */
38@Component(immediate = true)
39@Service
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -070040public class TopologyMetrics implements TopologyMetricsService {
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -070041 private static final Logger log = getLogger(TopologyMetrics.class);
42
43 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -070044 protected DeviceService deviceService;
45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 protected HostService hostService;
47 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
48 protected LinkService linkService;
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -070050 protected TopologyService topologyService;
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -070051
52 private LinkedList<Event> lastEvents = new LinkedList<>();
53 private static final int LAST_EVENTS_MAX_N = 100;
54
55 private final DeviceListener deviceListener = new InnerDeviceListener();
56 private final HostListener hostListener = new InnerHostListener();
57 private final LinkListener linkListener = new InnerLinkListener();
58 private final TopologyListener topologyListener =
59 new InnerTopologyListener();
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -070060
61 //
62 // Metrics
63 //
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected MetricsService metricsService;
66 //
67 private static final String COMPONENT_NAME = "Topology";
68 private static final String FEATURE_NAME = "EventNotification";
69 private static final String GAUGE_NAME = "LastEventTimestamp.EpochMs";
70 private static final String METER_NAME = "EventRate";
71 //
72 private MetricsComponent metricsComponent;
73 private MetricsFeature metricsFeatureEventNotification;
74 //
75 // Timestamp of the last Topology event (ms from the Epoch)
76 private volatile long lastEventTimestampEpochMs = 0;
77 private Gauge<Long> lastEventTimestampEpochMsGauge;
78 // Rate of the Topology events published to the Topology listeners
79 private Meter eventRateMeter;
80
81 @Activate
82 protected void activate() {
83 clear();
84 registerMetrics();
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -070085
86 // Register for all topology-related events
87 deviceService.addListener(deviceListener);
88 hostService.addListener(hostListener);
89 linkService.addListener(linkListener);
90 topologyService.addListener(topologyListener);
91
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -070092 log.info("ONOS Topology Metrics started.");
93 }
94
95 @Deactivate
96 public void deactivate() {
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -070097 // De-register from all topology-related events
98 deviceService.removeListener(deviceListener);
99 hostService.removeListener(hostListener);
100 linkService.removeListener(linkListener);
101 topologyService.removeListener(topologyListener);
102
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700103 removeMetrics();
104 clear();
105 log.info("ONOS Topology Metrics stopped.");
106 }
107
108 @Override
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -0700109 public List<Event> getEvents() {
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700110 synchronized (lastEvents) {
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -0700111 return ImmutableList.<Event>copyOf(lastEvents);
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700112 }
113 }
114
115 @Override
116 public Gauge<Long> lastEventTimestampEpochMsGauge() {
117 return lastEventTimestampEpochMsGauge;
118 }
119
120 @Override
121 public Meter eventRateMeter() {
122 return eventRateMeter;
123 }
124
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -0700125 /**
126 * Records an event.
127 *
128 * @param event the event to record
129 * @param updateEventRateMeter if true, update the Event Rate Meter
130 */
131 private void recordEvent(Event event, boolean updateEventRateMeter) {
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700132 synchronized (lastEvents) {
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -0700133 lastEventTimestampEpochMs = System.currentTimeMillis();
134 if (updateEventRateMeter) {
135 eventRateMeter.mark(1);
136 }
137
138 //
139 // Keep only the last N events, where N = LAST_EVENTS_MAX_N
140 //
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700141 while (lastEvents.size() >= LAST_EVENTS_MAX_N) {
142 lastEvents.remove();
143 }
144 lastEvents.add(event);
145 }
146 }
147
148 /**
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -0700149 * Inner Device Event Listener class.
150 */
151 private class InnerDeviceListener implements DeviceListener {
152 @Override
153 public void event(DeviceEvent event) {
154 recordEvent(event, true);
155 log.debug("Device Event: time = {} type = {} event = {}",
156 event.time(), event.type(), event);
157 }
158 }
159
160 /**
161 * Inner Host Event Listener class.
162 */
163 private class InnerHostListener implements HostListener {
164 @Override
165 public void event(HostEvent event) {
166 recordEvent(event, true);
167 log.debug("Host Event: time = {} type = {} event = {}",
168 event.time(), event.type(), event);
169 }
170 }
171
172 /**
173 * Inner Link Event Listener class.
174 */
175 private class InnerLinkListener implements LinkListener {
176 @Override
177 public void event(LinkEvent event) {
178 recordEvent(event, true);
179 log.debug("Link Event: time = {} type = {} event = {}",
180 event.time(), event.type(), event);
181 }
182 }
183
184 /**
185 * Inner Topology Event Listener class.
186 */
187 private class InnerTopologyListener implements TopologyListener {
188 @Override
189 public void event(TopologyEvent event) {
190 //
191 // NOTE: Don't update the eventRateMeter, because the real
192 // events are already captured/counted.
193 //
194 recordEvent(event, false);
195 log.debug("Topology Event: time = {} type = {} event = {}",
196 event.time(), event.type(), event);
197 for (Event reason : event.reasons()) {
198 log.debug("Topology Event Reason: time = {} type = {} event = {}",
199 reason.time(), reason.type(), reason);
200 }
201 }
202 }
203
204 /**
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700205 * Clears the internal state.
206 */
207 private void clear() {
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700208 synchronized (lastEvents) {
Pavlin Radoslavov5ba8b282014-10-23 01:03:10 -0700209 lastEventTimestampEpochMs = 0;
Pavlin Radoslavov64d9e472014-10-21 22:01:08 -0700210 lastEvents.clear();
211 }
212 }
213
214 /**
215 * Registers the metrics.
216 */
217 private void registerMetrics() {
218 metricsComponent = metricsService.registerComponent(COMPONENT_NAME);
219 metricsFeatureEventNotification =
220 metricsComponent.registerFeature(FEATURE_NAME);
221 lastEventTimestampEpochMsGauge =
222 metricsService.registerMetric(metricsComponent,
223 metricsFeatureEventNotification,
224 GAUGE_NAME,
225 new Gauge<Long>() {
226 @Override
227 public Long getValue() {
228 return lastEventTimestampEpochMs;
229 }
230 });
231 eventRateMeter =
232 metricsService.createMeter(metricsComponent,
233 metricsFeatureEventNotification,
234 METER_NAME);
235
236 }
237
238 /**
239 * Removes the metrics.
240 */
241 private void removeMetrics() {
242 metricsService.removeMetric(metricsComponent,
243 metricsFeatureEventNotification,
244 GAUGE_NAME);
245 metricsService.removeMetric(metricsComponent,
246 metricsFeatureEventNotification,
247 METER_NAME);
248 }
249}