Update the TopologyMetrics module to listen for all topology-related events:
Devices, Hosts, Links, TopologyEvent Now the semantics for updating the metrics are: * Any topology-related event (DeviceEvent, HostEvent, LinkEvent, TopologyEvent) will update the Lost Topology Event Timestamp * Only the DeviceEvent, HostEvent and LinkEvent will be counted in measuring the event rate; TopologyEvent is excluded, because it is generated as a result of some of those events Also, increased the number of saved events from 10 to 100. Change-Id: Ie759ee69869cddc617d7ad5b8b75a622e2571620
Showing
3 changed files
with
138 additions
and
65 deletions
... | @@ -18,6 +18,15 @@ import org.onlab.metrics.MetricsComponent; | ... | @@ -18,6 +18,15 @@ import org.onlab.metrics.MetricsComponent; |
18 | import org.onlab.metrics.MetricsFeature; | 18 | import org.onlab.metrics.MetricsFeature; |
19 | import org.onlab.metrics.MetricsService; | 19 | import org.onlab.metrics.MetricsService; |
20 | import org.onlab.onos.event.Event; | 20 | import org.onlab.onos.event.Event; |
21 | +import org.onlab.onos.net.device.DeviceEvent; | ||
22 | +import org.onlab.onos.net.device.DeviceListener; | ||
23 | +import org.onlab.onos.net.device.DeviceService; | ||
24 | +import org.onlab.onos.net.host.HostEvent; | ||
25 | +import org.onlab.onos.net.host.HostListener; | ||
26 | +import org.onlab.onos.net.host.HostService; | ||
27 | +import org.onlab.onos.net.link.LinkEvent; | ||
28 | +import org.onlab.onos.net.link.LinkListener; | ||
29 | +import org.onlab.onos.net.link.LinkService; | ||
21 | import org.onlab.onos.net.topology.TopologyEvent; | 30 | import org.onlab.onos.net.topology.TopologyEvent; |
22 | import org.onlab.onos.net.topology.TopologyListener; | 31 | import org.onlab.onos.net.topology.TopologyListener; |
23 | import org.onlab.onos.net.topology.TopologyService; | 32 | import org.onlab.onos.net.topology.TopologyService; |
... | @@ -28,14 +37,26 @@ import org.slf4j.Logger; | ... | @@ -28,14 +37,26 @@ import org.slf4j.Logger; |
28 | */ | 37 | */ |
29 | @Component(immediate = true) | 38 | @Component(immediate = true) |
30 | @Service | 39 | @Service |
31 | -public class TopologyMetrics implements TopologyMetricsService, | 40 | +public class TopologyMetrics implements TopologyMetricsService { |
32 | - TopologyListener { | ||
33 | private static final Logger log = getLogger(TopologyMetrics.class); | 41 | private static final Logger log = getLogger(TopologyMetrics.class); |
34 | 42 | ||
35 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 43 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
44 | + 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) | ||
36 | protected TopologyService topologyService; | 50 | protected TopologyService topologyService; |
37 | - private LinkedList<TopologyEvent> lastEvents = new LinkedList<>(); | 51 | + |
38 | - private static final int LAST_EVENTS_MAX_N = 10; | 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(); | ||
39 | 60 | ||
40 | // | 61 | // |
41 | // Metrics | 62 | // Metrics |
... | @@ -61,22 +82,33 @@ public class TopologyMetrics implements TopologyMetricsService, | ... | @@ -61,22 +82,33 @@ public class TopologyMetrics implements TopologyMetricsService, |
61 | protected void activate() { | 82 | protected void activate() { |
62 | clear(); | 83 | clear(); |
63 | registerMetrics(); | 84 | registerMetrics(); |
64 | - topologyService.addListener(this); | 85 | + |
86 | + // Register for all topology-related events | ||
87 | + deviceService.addListener(deviceListener); | ||
88 | + hostService.addListener(hostListener); | ||
89 | + linkService.addListener(linkListener); | ||
90 | + topologyService.addListener(topologyListener); | ||
91 | + | ||
65 | log.info("ONOS Topology Metrics started."); | 92 | log.info("ONOS Topology Metrics started."); |
66 | } | 93 | } |
67 | 94 | ||
68 | @Deactivate | 95 | @Deactivate |
69 | public void deactivate() { | 96 | public void deactivate() { |
70 | - topologyService.removeListener(this); | 97 | + // De-register from all topology-related events |
98 | + deviceService.removeListener(deviceListener); | ||
99 | + hostService.removeListener(hostListener); | ||
100 | + linkService.removeListener(linkListener); | ||
101 | + topologyService.removeListener(topologyListener); | ||
102 | + | ||
71 | removeMetrics(); | 103 | removeMetrics(); |
72 | clear(); | 104 | clear(); |
73 | log.info("ONOS Topology Metrics stopped."); | 105 | log.info("ONOS Topology Metrics stopped."); |
74 | } | 106 | } |
75 | 107 | ||
76 | @Override | 108 | @Override |
77 | - public List<TopologyEvent> getEvents() { | 109 | + public List<Event> getEvents() { |
78 | synchronized (lastEvents) { | 110 | synchronized (lastEvents) { |
79 | - return ImmutableList.<TopologyEvent>copyOf(lastEvents); | 111 | + return ImmutableList.<Event>copyOf(lastEvents); |
80 | } | 112 | } |
81 | } | 113 | } |
82 | 114 | ||
... | @@ -90,27 +122,22 @@ public class TopologyMetrics implements TopologyMetricsService, | ... | @@ -90,27 +122,22 @@ public class TopologyMetrics implements TopologyMetricsService, |
90 | return eventRateMeter; | 122 | return eventRateMeter; |
91 | } | 123 | } |
92 | 124 | ||
93 | - @Override | 125 | + /** |
94 | - public void event(TopologyEvent event) { | 126 | + * Records an event. |
95 | - lastEventTimestampEpochMs = System.currentTimeMillis(); | 127 | + * |
96 | - // | 128 | + * @param event the event to record |
97 | - // NOTE: If we want to count each "reason" as a separate event, | 129 | + * @param updateEventRateMeter if true, update the Event Rate Meter |
98 | - // then we should use 'event.reason().size()' instead of '1' to | 130 | + */ |
99 | - // mark the meter below. | 131 | + private void recordEvent(Event event, boolean updateEventRateMeter) { |
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) { | 132 | synchronized (lastEvents) { |
133 | + 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 | + // | ||
114 | while (lastEvents.size() >= LAST_EVENTS_MAX_N) { | 141 | while (lastEvents.size() >= LAST_EVENTS_MAX_N) { |
115 | lastEvents.remove(); | 142 | lastEvents.remove(); |
116 | } | 143 | } |
... | @@ -119,11 +146,67 @@ public class TopologyMetrics implements TopologyMetricsService, | ... | @@ -119,11 +146,67 @@ public class TopologyMetrics implements TopologyMetricsService, |
119 | } | 146 | } |
120 | 147 | ||
121 | /** | 148 | /** |
149 | + * 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 | + /** | ||
122 | * Clears the internal state. | 205 | * Clears the internal state. |
123 | */ | 206 | */ |
124 | private void clear() { | 207 | private void clear() { |
125 | - lastEventTimestampEpochMs = 0; | ||
126 | synchronized (lastEvents) { | 208 | synchronized (lastEvents) { |
209 | + lastEventTimestampEpochMs = 0; | ||
127 | lastEvents.clear(); | 210 | lastEvents.clear(); |
128 | } | 211 | } |
129 | } | 212 | } | ... | ... |
... | @@ -4,7 +4,7 @@ import java.util.List; | ... | @@ -4,7 +4,7 @@ import java.util.List; |
4 | 4 | ||
5 | import com.codahale.metrics.Gauge; | 5 | import com.codahale.metrics.Gauge; |
6 | import com.codahale.metrics.Meter; | 6 | import com.codahale.metrics.Meter; |
7 | -import org.onlab.onos.net.topology.TopologyEvent; | 7 | +import org.onlab.onos.event.Event; |
8 | 8 | ||
9 | /** | 9 | /** |
10 | * Service interface exported by TopologyMetrics. | 10 | * Service interface exported by TopologyMetrics. |
... | @@ -15,7 +15,7 @@ public interface TopologyMetricsService { | ... | @@ -15,7 +15,7 @@ public interface TopologyMetricsService { |
15 | * | 15 | * |
16 | * @return the last saved topology events. | 16 | * @return the last saved topology events. |
17 | */ | 17 | */ |
18 | - public List<TopologyEvent> getEvents(); | 18 | + public List<Event> getEvents(); |
19 | 19 | ||
20 | /** | 20 | /** |
21 | * Gets the Metrics' Gauge for the last topology event timestamp | 21 | * Gets the Metrics' Gauge for the last topology event timestamp | ... | ... |
... | @@ -19,10 +19,8 @@ import org.onlab.onos.net.topology.TopologyEvent; | ... | @@ -19,10 +19,8 @@ import org.onlab.onos.net.topology.TopologyEvent; |
19 | description = "Lists the last topology events") | 19 | description = "Lists the last topology events") |
20 | public class TopologyEventsListCommand extends AbstractShellCommand { | 20 | public class TopologyEventsListCommand extends AbstractShellCommand { |
21 | 21 | ||
22 | - private static final String FORMAT_EVENT = | 22 | + private static final String FORMAT_EVENT = "Event=%s"; |
23 | - "Topology Event time=%d type=%s subject=%s"; | 23 | + private static final String FORMAT_REASON = " Reason=%s"; |
24 | - private static final String FORMAT_REASON = | ||
25 | - " Reason time=%d type=%s subject=%s"; | ||
26 | 24 | ||
27 | @Override | 25 | @Override |
28 | protected void execute() { | 26 | protected void execute() { |
... | @@ -31,12 +29,13 @@ public class TopologyEventsListCommand extends AbstractShellCommand { | ... | @@ -31,12 +29,13 @@ public class TopologyEventsListCommand extends AbstractShellCommand { |
31 | if (outputJson()) { | 29 | if (outputJson()) { |
32 | print("%s", json(service.getEvents())); | 30 | print("%s", json(service.getEvents())); |
33 | } else { | 31 | } else { |
34 | - for (TopologyEvent event : service.getEvents()) { | 32 | + for (Event event : service.getEvents()) { |
35 | - print(FORMAT_EVENT, event.time(), event.type(), | 33 | + print(FORMAT_EVENT, event); |
36 | - event.subject()); | 34 | + if (event instanceof TopologyEvent) { |
37 | - for (Event reason : event.reasons()) { | 35 | + TopologyEvent topologyEvent = (TopologyEvent) event; |
38 | - print(FORMAT_REASON, reason.time(), reason.type(), | 36 | + for (Event reason : topologyEvent.reasons()) { |
39 | - reason.subject()); | 37 | + print(FORMAT_REASON, reason); |
38 | + } | ||
40 | } | 39 | } |
41 | print(""); // Extra empty line for clarity | 40 | print(""); // Extra empty line for clarity |
42 | } | 41 | } |
... | @@ -46,14 +45,14 @@ public class TopologyEventsListCommand extends AbstractShellCommand { | ... | @@ -46,14 +45,14 @@ public class TopologyEventsListCommand extends AbstractShellCommand { |
46 | /** | 45 | /** |
47 | * Produces a JSON array of topology events. | 46 | * Produces a JSON array of topology events. |
48 | * | 47 | * |
49 | - * @param topologyEvents the topology events with the data | 48 | + * @param events the topology events with the data |
50 | * @return JSON array with the topology events | 49 | * @return JSON array with the topology events |
51 | */ | 50 | */ |
52 | - private JsonNode json(List<TopologyEvent> topologyEvents) { | 51 | + private JsonNode json(List<Event> events) { |
53 | ObjectMapper mapper = new ObjectMapper(); | 52 | ObjectMapper mapper = new ObjectMapper(); |
54 | ArrayNode result = mapper.createArrayNode(); | 53 | ArrayNode result = mapper.createArrayNode(); |
55 | 54 | ||
56 | - for (TopologyEvent event : topologyEvents) { | 55 | + for (Event event : events) { |
57 | result.add(json(mapper, event)); | 56 | result.add(json(mapper, event)); |
58 | } | 57 | } |
59 | return result; | 58 | return result; |
... | @@ -66,32 +65,23 @@ public class TopologyEventsListCommand extends AbstractShellCommand { | ... | @@ -66,32 +65,23 @@ public class TopologyEventsListCommand extends AbstractShellCommand { |
66 | * @param topologyEvent the topology event with the data | 65 | * @param topologyEvent the topology event with the data |
67 | * @return JSON object for the topology event | 66 | * @return JSON object for the topology event |
68 | */ | 67 | */ |
69 | - private ObjectNode json(ObjectMapper mapper, TopologyEvent topologyEvent) { | ||
70 | - ObjectNode result = mapper.createObjectNode(); | ||
71 | - ArrayNode reasons = mapper.createArrayNode(); | ||
72 | - | ||
73 | - for (Event reason : topologyEvent.reasons()) { | ||
74 | - reasons.add(json(mapper, reason)); | ||
75 | - } | ||
76 | - result.put("time", topologyEvent.time()) | ||
77 | - .put("type", topologyEvent.type().toString()) | ||
78 | - .put("subject", topologyEvent.subject().toString()) | ||
79 | - .put("reasons", reasons); | ||
80 | - return result; | ||
81 | - } | ||
82 | - | ||
83 | - /** | ||
84 | - * Produces JSON object for a generic event. | ||
85 | - * | ||
86 | - * @param event the generic event with the data | ||
87 | - * @return JSON object for the generic event | ||
88 | - */ | ||
89 | private ObjectNode json(ObjectMapper mapper, Event event) { | 68 | private ObjectNode json(ObjectMapper mapper, Event event) { |
90 | ObjectNode result = mapper.createObjectNode(); | 69 | ObjectNode result = mapper.createObjectNode(); |
91 | 70 | ||
92 | result.put("time", event.time()) | 71 | result.put("time", event.time()) |
93 | .put("type", event.type().toString()) | 72 | .put("type", event.type().toString()) |
94 | - .put("subject", event.subject().toString()); | 73 | + .put("event", event.toString()); |
74 | + | ||
75 | + // Add the reasons if a TopologyEvent | ||
76 | + if (event instanceof TopologyEvent) { | ||
77 | + TopologyEvent topologyEvent = (TopologyEvent) event; | ||
78 | + ArrayNode reasons = mapper.createArrayNode(); | ||
79 | + for (Event reason : topologyEvent.reasons()) { | ||
80 | + reasons.add(json(mapper, reason)); | ||
81 | + } | ||
82 | + result.put("reasons", reasons); | ||
83 | + } | ||
84 | + | ||
95 | return result; | 85 | return result; |
96 | } | 86 | } |
97 | } | 87 | } | ... | ... |
-
Please register or login to post a comment