Added a new module: ONOS intent metrics application
It can be used as an Intent-related event and event metrics collector. It can be loaded by one of the following two (new) features: onos-app-metrics, onos-app-metrics-intent After loading the module, it subscribes for intent-related events and keeps the following state: (a) The last 100 events (b) The timestamp of the last event (ms after epoch) as observed by this module for each event type: SUBMITTED, INSTALLED, WITHDRAWN. The missing event type is the equivalent of "Withdraw Requested" (c) The rate of each intent event type: count, median rate, average rate over the last 1, 5 or 15 minutes The following CLI commands are added: * onos:intents-events Shows the last 100 intent events * onos:intents-events-metrics Shows the timestamp of the last event (ms after epoch) as observed by this module for each event type, and the rate of the topology events (for each event type): see (b) and (c) above Change-Id: I9f23e9086bbd433b8f24283539abdeb97e199e2e
Showing
9 changed files
with
341 additions
and
0 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 | ... | ... |
... | @@ -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