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