blob: e2a4532167297d815c12a468d1973998b1daedcc [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;
21import org.onlab.onos.net.topology.TopologyEvent;
22import org.onlab.onos.net.topology.TopologyListener;
23import org.onlab.onos.net.topology.TopologyService;
24import org.slf4j.Logger;
25
26/**
27 * ONOS Topology Metrics Application that collects topology-related metrics.
28 */
29@Component(immediate = true)
30@Service
31public class TopologyMetrics implements TopologyMetricsService,
32 TopologyListener {
33 private static final Logger log = getLogger(TopologyMetrics.class);
34
35 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
36 protected TopologyService topologyService;
37 private LinkedList<TopologyEvent> lastEvents = new LinkedList<>();
38 private static final int LAST_EVENTS_MAX_N = 10;
39
40 //
41 // Metrics
42 //
43 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
44 protected MetricsService metricsService;
45 //
46 private static final String COMPONENT_NAME = "Topology";
47 private static final String FEATURE_NAME = "EventNotification";
48 private static final String GAUGE_NAME = "LastEventTimestamp.EpochMs";
49 private static final String METER_NAME = "EventRate";
50 //
51 private MetricsComponent metricsComponent;
52 private MetricsFeature metricsFeatureEventNotification;
53 //
54 // Timestamp of the last Topology event (ms from the Epoch)
55 private volatile long lastEventTimestampEpochMs = 0;
56 private Gauge<Long> lastEventTimestampEpochMsGauge;
57 // Rate of the Topology events published to the Topology listeners
58 private Meter eventRateMeter;
59
60 @Activate
61 protected void activate() {
62 clear();
63 registerMetrics();
64 topologyService.addListener(this);
65 log.info("ONOS Topology Metrics started.");
66 }
67
68 @Deactivate
69 public void deactivate() {
70 topologyService.removeListener(this);
71 removeMetrics();
72 clear();
73 log.info("ONOS Topology Metrics stopped.");
74 }
75
76 @Override
77 public List<TopologyEvent> getEvents() {
78 synchronized (lastEvents) {
79 return ImmutableList.<TopologyEvent>copyOf(lastEvents);
80 }
81 }
82
83 @Override
84 public Gauge<Long> lastEventTimestampEpochMsGauge() {
85 return lastEventTimestampEpochMsGauge;
86 }
87
88 @Override
89 public Meter eventRateMeter() {
90 return eventRateMeter;
91 }
92
93 @Override
94 public void event(TopologyEvent event) {
95 lastEventTimestampEpochMs = System.currentTimeMillis();
96 //
97 // NOTE: If we want to count each "reason" as a separate event,
98 // then we should use 'event.reason().size()' instead of '1' to
99 // mark the meter below.
100 //
101 eventRateMeter.mark(1);
102
103 log.debug("Topology Event: time = {} type = {} subject = {}",
104 event.time(), event.type(), event.subject());
105 for (Event reason : event.reasons()) {
106 log.debug("Topology Event Reason: time = {} type = {} subject = {}",
107 reason.time(), reason.type(), reason.subject());
108 }
109
110 //
111 // Keep only the last N events, where N = LAST_EVENTS_MAX_N
112 //
113 synchronized (lastEvents) {
114 while (lastEvents.size() >= LAST_EVENTS_MAX_N) {
115 lastEvents.remove();
116 }
117 lastEvents.add(event);
118 }
119 }
120
121 /**
122 * Clears the internal state.
123 */
124 private void clear() {
125 lastEventTimestampEpochMs = 0;
126 synchronized (lastEvents) {
127 lastEvents.clear();
128 }
129 }
130
131 /**
132 * Registers the metrics.
133 */
134 private void registerMetrics() {
135 metricsComponent = metricsService.registerComponent(COMPONENT_NAME);
136 metricsFeatureEventNotification =
137 metricsComponent.registerFeature(FEATURE_NAME);
138 lastEventTimestampEpochMsGauge =
139 metricsService.registerMetric(metricsComponent,
140 metricsFeatureEventNotification,
141 GAUGE_NAME,
142 new Gauge<Long>() {
143 @Override
144 public Long getValue() {
145 return lastEventTimestampEpochMs;
146 }
147 });
148 eventRateMeter =
149 metricsService.createMeter(metricsComponent,
150 metricsFeatureEventNotification,
151 METER_NAME);
152
153 }
154
155 /**
156 * Removes the metrics.
157 */
158 private void removeMetrics() {
159 metricsService.removeMetric(metricsComponent,
160 metricsFeatureEventNotification,
161 GAUGE_NAME);
162 metricsService.removeMetric(metricsComponent,
163 metricsFeatureEventNotification,
164 METER_NAME);
165 }
166}