Showing
12 changed files
with
479 additions
and
65 deletions
apps/metrics/intent/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
5 | + <modelVersion>4.0.0</modelVersion> | ||
6 | + | ||
7 | + <parent> | ||
8 | + <groupId>org.onlab.onos</groupId> | ||
9 | + <artifactId>onos-app-metrics</artifactId> | ||
10 | + <version>1.0.0-SNAPSHOT</version> | ||
11 | + <relativePath>../pom.xml</relativePath> | ||
12 | + </parent> | ||
13 | + | ||
14 | + <artifactId>onos-app-metrics-intent</artifactId> | ||
15 | + <packaging>bundle</packaging> | ||
16 | + | ||
17 | + <description>ONOS intent metrics application</description> | ||
18 | + | ||
19 | + <dependencies> | ||
20 | + <dependency> | ||
21 | + <groupId>org.onlab.onos</groupId> | ||
22 | + <artifactId>onos-cli</artifactId> | ||
23 | + <version>${project.version}</version> | ||
24 | + </dependency> | ||
25 | + | ||
26 | + <dependency> | ||
27 | + <groupId>org.apache.karaf.shell</groupId> | ||
28 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
29 | + </dependency> | ||
30 | + </dependencies> | ||
31 | + | ||
32 | +</project> |
This diff is collapsed. Click to expand it.
apps/metrics/intent/src/main/java/org/onlab/onos/metrics/intent/IntentMetricsService.java
0 → 100644
1 | +package org.onlab.onos.metrics.intent; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +import com.codahale.metrics.Gauge; | ||
6 | +import com.codahale.metrics.Meter; | ||
7 | +import org.onlab.onos.net.intent.IntentEvent; | ||
8 | + | ||
9 | +/** | ||
10 | + * Service interface exported by IntentMetrics. | ||
11 | + */ | ||
12 | +public interface IntentMetricsService { | ||
13 | + /** | ||
14 | + * Gets the last saved intent events. | ||
15 | + * | ||
16 | + * @return the last saved intent events. | ||
17 | + */ | ||
18 | + public List<IntentEvent> getEvents(); | ||
19 | + | ||
20 | + /** | ||
21 | + * Gets the Metrics' Gauge for the intent SUBMITTED event timestamp | ||
22 | + * (ms from the epoch). | ||
23 | + * | ||
24 | + * @return the Metrics' Gauge for the intent SUBMITTED event timestamp | ||
25 | + * (ms from the epoch) | ||
26 | + */ | ||
27 | + public Gauge<Long> intentSubmittedTimestampEpochMsGauge(); | ||
28 | + | ||
29 | + /** | ||
30 | + * Gets the Metrics' Gauge for the intent INSTALLED event timestamp | ||
31 | + * (ms from the epoch). | ||
32 | + * | ||
33 | + * @return the Metrics' Gauge for the intent INSTALLED event timestamp | ||
34 | + * (ms from the epoch) | ||
35 | + */ | ||
36 | + public Gauge<Long> intentInstalledTimestampEpochMsGauge(); | ||
37 | + | ||
38 | + /** | ||
39 | + * Gets the Metrics' Gauge for the intent WITHDRAW_REQUESTED event | ||
40 | + * timestamp (ms from the epoch). | ||
41 | + * | ||
42 | + * TODO: This intent event is not implemented yet. | ||
43 | + * | ||
44 | + * @return the Metrics' Gauge for the intent WITHDRAW_REQUESTED event | ||
45 | + * timestamp (ms from the epoch) | ||
46 | + */ | ||
47 | + public Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge(); | ||
48 | + | ||
49 | + /** | ||
50 | + * Gets the Metrics' Gauge for the intent WITHDRAWN event timestamp | ||
51 | + * (ms from the epoch). | ||
52 | + * | ||
53 | + * @return the Metrics' Gauge for the intent WITHDRAWN event timestamp | ||
54 | + * (ms from the epoch) | ||
55 | + */ | ||
56 | + public Gauge<Long> intentWithdrawnTimestampEpochMsGauge(); | ||
57 | + | ||
58 | + /** | ||
59 | + * Gets the Metrics' Meter for the submitted intents event rate. | ||
60 | + * | ||
61 | + * @return the Metrics' Meter for the submitted intents event rate | ||
62 | + */ | ||
63 | + public Meter intentSubmittedRateMeter(); | ||
64 | + | ||
65 | + /** | ||
66 | + * Gets the Metrics' Meter for the installed intents event rate. | ||
67 | + * | ||
68 | + * @return the Metrics' Meter for the installed intent event rate | ||
69 | + */ | ||
70 | + public Meter intentInstalledRateMeter(); | ||
71 | + | ||
72 | + /** | ||
73 | + * Gets the Metrics' Meter for the withdraw requested intents event rate. | ||
74 | + * | ||
75 | + * @return the Metrics' Meter for the withdraw requested intents event rate | ||
76 | + */ | ||
77 | + public Meter intentWithdrawRequestedRateMeter(); | ||
78 | + | ||
79 | + /** | ||
80 | + * Gets the Metrics' Meter for the withdraw completed intents event rate. | ||
81 | + * | ||
82 | + * @return the Metrics' Meter for the withdraw completed intents event rate | ||
83 | + */ | ||
84 | + public Meter intentWithdrawnRateMeter(); | ||
85 | +} |
apps/metrics/intent/src/main/java/org/onlab/onos/metrics/intent/cli/IntentEventsListCommand.java
0 → 100644
1 | +package org.onlab.onos.metrics.intent.cli; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +import com.fasterxml.jackson.databind.JsonNode; | ||
6 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
7 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
8 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
9 | +import org.apache.karaf.shell.commands.Command; | ||
10 | +import org.onlab.onos.cli.AbstractShellCommand; | ||
11 | +import org.onlab.onos.metrics.intent.IntentMetricsService; | ||
12 | +import org.onlab.onos.net.intent.IntentEvent; | ||
13 | + | ||
14 | +/** | ||
15 | + * Command to show the list of last intent events. | ||
16 | + */ | ||
17 | +@Command(scope = "onos", name = "intents-events", | ||
18 | + description = "Lists the last intent events") | ||
19 | +public class IntentEventsListCommand extends AbstractShellCommand { | ||
20 | + | ||
21 | + private static final String FORMAT_EVENT = "Event=%s"; | ||
22 | + | ||
23 | + @Override | ||
24 | + protected void execute() { | ||
25 | + IntentMetricsService service = get(IntentMetricsService.class); | ||
26 | + | ||
27 | + if (outputJson()) { | ||
28 | + print("%s", json(service.getEvents())); | ||
29 | + } else { | ||
30 | + for (IntentEvent event : service.getEvents()) { | ||
31 | + print(FORMAT_EVENT, event); | ||
32 | + print(""); // Extra empty line for clarity | ||
33 | + } | ||
34 | + } | ||
35 | + } | ||
36 | + | ||
37 | + /** | ||
38 | + * Produces a JSON array of intent events. | ||
39 | + * | ||
40 | + * @param intentEvents the intent events with the data | ||
41 | + * @return JSON array with the intent events | ||
42 | + */ | ||
43 | + private JsonNode json(List<IntentEvent> intentEvents) { | ||
44 | + ObjectMapper mapper = new ObjectMapper(); | ||
45 | + ArrayNode result = mapper.createArrayNode(); | ||
46 | + | ||
47 | + for (IntentEvent event : intentEvents) { | ||
48 | + result.add(json(mapper, event)); | ||
49 | + } | ||
50 | + return result; | ||
51 | + } | ||
52 | + | ||
53 | + /** | ||
54 | + * Produces JSON object for a intent event. | ||
55 | + * | ||
56 | + * @param mapper the JSON object mapper to use | ||
57 | + * @param intentEvent the intent event with the data | ||
58 | + * @return JSON object for the intent event | ||
59 | + */ | ||
60 | + private ObjectNode json(ObjectMapper mapper, IntentEvent intentEvent) { | ||
61 | + ObjectNode result = mapper.createObjectNode(); | ||
62 | + | ||
63 | + result.put("time", intentEvent.time()) | ||
64 | + .put("type", intentEvent.type().toString()) | ||
65 | + .put("event", intentEvent.toString()); | ||
66 | + return result; | ||
67 | + } | ||
68 | +} |
apps/metrics/intent/src/main/java/org/onlab/onos/metrics/intent/cli/IntentEventsMetricsCommand.java
0 → 100644
1 | +package org.onlab.onos.metrics.intent.cli; | ||
2 | + | ||
3 | +import java.io.IOException; | ||
4 | +import java.util.concurrent.TimeUnit; | ||
5 | + | ||
6 | +import com.codahale.metrics.Gauge; | ||
7 | +import com.codahale.metrics.Meter; | ||
8 | +import com.codahale.metrics.json.MetricsModule; | ||
9 | +import com.fasterxml.jackson.core.JsonProcessingException; | ||
10 | +import com.fasterxml.jackson.databind.JsonNode; | ||
11 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
12 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
13 | +import org.apache.karaf.shell.commands.Command; | ||
14 | +import org.onlab.onos.cli.AbstractShellCommand; | ||
15 | +import org.onlab.onos.metrics.intent.IntentMetricsService; | ||
16 | + | ||
17 | +/** | ||
18 | + * Command to show the intent events metrics. | ||
19 | + */ | ||
20 | +@Command(scope = "onos", name = "intents-events-metrics", | ||
21 | + description = "Lists intent events metrics") | ||
22 | +public class IntentEventsMetricsCommand extends AbstractShellCommand { | ||
23 | + | ||
24 | + private static final String FORMAT_GAUGE = | ||
25 | + "Intent %s Event Timestamp (ms from epoch)=%d"; | ||
26 | + private static final String FORMAT_METER = | ||
27 | + "Intent %s Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f"; | ||
28 | + | ||
29 | + @Override | ||
30 | + protected void execute() { | ||
31 | + IntentMetricsService service = get(IntentMetricsService.class); | ||
32 | + Gauge<Long> gauge; | ||
33 | + Meter meter; | ||
34 | + | ||
35 | + if (outputJson()) { | ||
36 | + ObjectMapper mapper = new ObjectMapper() | ||
37 | + .registerModule(new MetricsModule(TimeUnit.SECONDS, | ||
38 | + TimeUnit.MILLISECONDS, | ||
39 | + false)); | ||
40 | + ObjectNode result = mapper.createObjectNode(); | ||
41 | + // | ||
42 | + gauge = service.intentSubmittedTimestampEpochMsGauge(); | ||
43 | + result.put("intentSubmittedTimestamp", json(mapper, gauge)); | ||
44 | + gauge = service.intentInstalledTimestampEpochMsGauge(); | ||
45 | + result.put("intentInstalledTimestamp", json(mapper, gauge)); | ||
46 | + gauge = service.intentWithdrawRequestedTimestampEpochMsGauge(); | ||
47 | + result.put("intentWithdrawRequestedTimestamp", | ||
48 | + json(mapper, gauge)); | ||
49 | + gauge = service.intentWithdrawnTimestampEpochMsGauge(); | ||
50 | + result.put("intentWithdrawnTimestamp", json(mapper, gauge)); | ||
51 | + // | ||
52 | + meter = service.intentSubmittedRateMeter(); | ||
53 | + result.put("intentSubmittedRate", json(mapper, meter)); | ||
54 | + meter = service.intentInstalledRateMeter(); | ||
55 | + result.put("intentInstalledRate", json(mapper, meter)); | ||
56 | + meter = service.intentWithdrawRequestedRateMeter(); | ||
57 | + result.put("intentWithdrawRequestedRate", json(mapper, meter)); | ||
58 | + meter = service.intentWithdrawnRateMeter(); | ||
59 | + result.put("intentWithdrawnRate", json(mapper, meter)); | ||
60 | + // | ||
61 | + print("%s", result); | ||
62 | + } else { | ||
63 | + gauge = service.intentSubmittedTimestampEpochMsGauge(); | ||
64 | + printGauge("Submitted", gauge); | ||
65 | + gauge = service.intentInstalledTimestampEpochMsGauge(); | ||
66 | + printGauge("Installed", gauge); | ||
67 | + gauge = service.intentWithdrawRequestedTimestampEpochMsGauge(); | ||
68 | + printGauge("Withdraw Requested", gauge); | ||
69 | + gauge = service.intentWithdrawnTimestampEpochMsGauge(); | ||
70 | + printGauge("Withdrawn", gauge); | ||
71 | + // | ||
72 | + meter = service.intentSubmittedRateMeter(); | ||
73 | + printMeter("Submitted", meter); | ||
74 | + meter = service.intentInstalledRateMeter(); | ||
75 | + printMeter("Installed", meter); | ||
76 | + meter = service.intentWithdrawRequestedRateMeter(); | ||
77 | + printMeter("Withdraw Requested", meter); | ||
78 | + meter = service.intentWithdrawnRateMeter(); | ||
79 | + printMeter("Withdrawn", meter); | ||
80 | + } | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * Produces JSON node for an Object. | ||
85 | + * | ||
86 | + * @param mapper the JSON object mapper to use | ||
87 | + * @param object the Object with the data | ||
88 | + * @return JSON node for the Object | ||
89 | + */ | ||
90 | + private JsonNode json(ObjectMapper mapper, Object object) { | ||
91 | + // | ||
92 | + // NOTE: The API for custom serializers is incomplete, | ||
93 | + // hence we have to parse the JSON string to create JsonNode. | ||
94 | + // | ||
95 | + try { | ||
96 | + final String objectJson = mapper.writeValueAsString(object); | ||
97 | + JsonNode objectNode = mapper.readTree(objectJson); | ||
98 | + return objectNode; | ||
99 | + } catch (JsonProcessingException e) { | ||
100 | + log.error("Error writing value as JSON string", e); | ||
101 | + } catch (IOException e) { | ||
102 | + log.error("Error writing value as JSON string", e); | ||
103 | + } | ||
104 | + return null; | ||
105 | + } | ||
106 | + | ||
107 | + /** | ||
108 | + * Prints a Gauge. | ||
109 | + * | ||
110 | + * @param operationStr the string with the intent operation to print | ||
111 | + * @param gauge the Gauge to print | ||
112 | + */ | ||
113 | + private void printGauge(String operationStr, Gauge<Long> gauge) { | ||
114 | + print(FORMAT_GAUGE, operationStr, gauge.getValue()); | ||
115 | + } | ||
116 | + | ||
117 | + /** | ||
118 | + * Prints a Meter. | ||
119 | + * | ||
120 | + * @param operationStr the string with the intent operation to print | ||
121 | + * @param meter the Meter to print | ||
122 | + */ | ||
123 | + private void printMeter(String operationStr, Meter meter) { | ||
124 | + TimeUnit rateUnit = TimeUnit.SECONDS; | ||
125 | + double rateFactor = rateUnit.toSeconds(1); | ||
126 | + print(FORMAT_METER, operationStr, meter.getCount(), | ||
127 | + meter.getMeanRate() * rateFactor, | ||
128 | + meter.getOneMinuteRate() * rateFactor, | ||
129 | + meter.getFiveMinuteRate() * rateFactor, | ||
130 | + meter.getFifteenMinuteRate() * rateFactor); | ||
131 | + } | ||
132 | +} |
1 | +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> | ||
2 | + | ||
3 | + <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> | ||
4 | + <command> | ||
5 | + <action class="org.onlab.onos.metrics.intent.cli.IntentEventsListCommand"/> | ||
6 | + </command> | ||
7 | + <command> | ||
8 | + <action class="org.onlab.onos.metrics.intent.cli.IntentEventsMetricsCommand"/> | ||
9 | + </command> | ||
10 | + </command-bundle> | ||
11 | + | ||
12 | +</blueprint> |
... | @@ -17,6 +17,7 @@ | ... | @@ -17,6 +17,7 @@ |
17 | <description>ONOS metrics applications</description> | 17 | <description>ONOS metrics applications</description> |
18 | 18 | ||
19 | <modules> | 19 | <modules> |
20 | + <module>intent</module> | ||
20 | <module>topology</module> | 21 | <module>topology</module> |
21 | </modules> | 22 | </modules> |
22 | 23 | ... | ... |
... | @@ -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 | } | ... | ... |
... | @@ -199,9 +199,16 @@ | ... | @@ -199,9 +199,16 @@ |
199 | 199 | ||
200 | <feature name="onos-app-metrics" version="1.0.0" | 200 | <feature name="onos-app-metrics" version="1.0.0" |
201 | description="ONOS metrics applications"> | 201 | description="ONOS metrics applications"> |
202 | + <feature>onos-app-metrics-intent</feature> | ||
202 | <feature>onos-app-metrics-topology</feature> | 203 | <feature>onos-app-metrics-topology</feature> |
203 | </feature> | 204 | </feature> |
204 | 205 | ||
206 | + <feature name="onos-app-metrics-intent" version="1.0.0" | ||
207 | + description="ONOS intent metrics application"> | ||
208 | + <feature>onos-api</feature> | ||
209 | + <bundle>mvn:org.onlab.onos/onos-app-metrics-intent/1.0.0-SNAPSHOT</bundle> | ||
210 | + </feature> | ||
211 | + | ||
205 | <feature name="onos-app-metrics-topology" version="1.0.0" | 212 | <feature name="onos-app-metrics-topology" version="1.0.0" |
206 | description="ONOS topology metrics application"> | 213 | description="ONOS topology metrics application"> |
207 | <feature>onos-api</feature> | 214 | <feature>onos-api</feature> | ... | ... |
-
Please register or login to post a comment