Added GUI to intent perf app to monitor performance stats in real-time.
Fixed app ids for metrics app. Change-Id: Icea99991ad71c80c53a832c236dcc05fefbb9b02
Showing
10 changed files
with
299 additions
and
40 deletions
| ... | @@ -65,7 +65,7 @@ public class IntentPerfCollector { | ... | @@ -65,7 +65,7 @@ public class IntentPerfCollector { |
| 65 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 65 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 66 | protected ClusterService clusterService; | 66 | protected ClusterService clusterService; |
| 67 | 67 | ||
| 68 | - @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY) | 68 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 69 | protected IntentPerfUi ui; | 69 | protected IntentPerfUi ui; |
| 70 | 70 | ||
| 71 | // Auxiliary structures used to accrue data for normalized time interval | 71 | // Auxiliary structures used to accrue data for normalized time interval |
| ... | @@ -99,6 +99,7 @@ public class IntentPerfCollector { | ... | @@ -99,6 +99,7 @@ public class IntentPerfCollector { |
| 99 | nodeToIndex.put(nodes[i].id(), i); | 99 | nodeToIndex.put(nodes[i].id(), i); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | + ui.setHeaders(getSampleHeaders()); | ||
| 102 | clearSamples(); | 103 | clearSamples(); |
| 103 | log.info("Started"); | 104 | log.info("Started"); |
| 104 | } | 105 | } | ... | ... |
| ... | @@ -99,7 +99,7 @@ public class IntentPerfInstaller { | ... | @@ -99,7 +99,7 @@ public class IntentPerfInstaller { |
| 99 | private static final int DEFAULT_NUM_NEIGHBORS = 0; | 99 | private static final int DEFAULT_NUM_NEIGHBORS = 0; |
| 100 | 100 | ||
| 101 | private static final int START_DELAY = 5_000; // ms | 101 | private static final int START_DELAY = 5_000; // ms |
| 102 | - private static final int REPORT_PERIOD = 5_000; //ms | 102 | + private static final int REPORT_PERIOD = 1_000; //ms |
| 103 | 103 | ||
| 104 | private static final String START = "start"; | 104 | private static final String START = "start"; |
| 105 | private static final String STOP = "stop"; | 105 | private static final String STOP = "stop"; | ... | ... |
| ... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.intentperf; | 16 | package org.onosproject.intentperf; |
| 17 | 17 | ||
| 18 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | import com.google.common.collect.ImmutableList; | 20 | import com.google.common.collect.ImmutableList; |
| 20 | import com.google.common.collect.ImmutableSet; | 21 | import com.google.common.collect.ImmutableSet; |
| ... | @@ -23,6 +24,7 @@ import org.apache.felix.scr.annotations.Component; | ... | @@ -23,6 +24,7 @@ import org.apache.felix.scr.annotations.Component; |
| 23 | import org.apache.felix.scr.annotations.Deactivate; | 24 | import org.apache.felix.scr.annotations.Deactivate; |
| 24 | import org.apache.felix.scr.annotations.Reference; | 25 | import org.apache.felix.scr.annotations.Reference; |
| 25 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 26 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 27 | +import org.apache.felix.scr.annotations.Service; | ||
| 26 | import org.onlab.osgi.ServiceDirectory; | 28 | import org.onlab.osgi.ServiceDirectory; |
| 27 | import org.onosproject.intentperf.IntentPerfCollector.Sample; | 29 | import org.onosproject.intentperf.IntentPerfCollector.Sample; |
| 28 | import org.onosproject.ui.UiConnection; | 30 | import org.onosproject.ui.UiConnection; |
| ... | @@ -34,14 +36,17 @@ import org.onosproject.ui.UiView; | ... | @@ -34,14 +36,17 @@ import org.onosproject.ui.UiView; |
| 34 | import java.util.Collection; | 36 | import java.util.Collection; |
| 35 | import java.util.HashSet; | 37 | import java.util.HashSet; |
| 36 | import java.util.List; | 38 | import java.util.List; |
| 39 | +import java.util.Random; | ||
| 37 | import java.util.Set; | 40 | import java.util.Set; |
| 41 | +import java.util.TimerTask; | ||
| 38 | 42 | ||
| 39 | import static java.util.Collections.synchronizedSet; | 43 | import static java.util.Collections.synchronizedSet; |
| 40 | 44 | ||
| 41 | /** | 45 | /** |
| 42 | * Mechanism to stream data to the GUI. | 46 | * Mechanism to stream data to the GUI. |
| 43 | */ | 47 | */ |
| 44 | -@Component(immediate = true, enabled = false) | 48 | +@Component(immediate = true, enabled = true) |
| 49 | +@Service(value = IntentPerfUi.class) | ||
| 45 | public class IntentPerfUi { | 50 | public class IntentPerfUi { |
| 46 | 51 | ||
| 47 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 52 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| ... | @@ -53,9 +58,25 @@ public class IntentPerfUi { | ... | @@ -53,9 +58,25 @@ public class IntentPerfUi { |
| 53 | private UiExtension uiExtension = new UiExtension(views, this::newHandlers, | 58 | private UiExtension uiExtension = new UiExtension(views, this::newHandlers, |
| 54 | getClass().getClassLoader()); | 59 | getClass().getClassLoader()); |
| 55 | 60 | ||
| 61 | + private List<String> headers = ImmutableList.of("One", "Two", "Three", "Four", "Five"); | ||
| 62 | + | ||
| 63 | + private Random random = new Random(); | ||
| 64 | + private TimerTask task; | ||
| 65 | + | ||
| 56 | @Activate | 66 | @Activate |
| 57 | protected void activate() { | 67 | protected void activate() { |
| 58 | uiExtensionService.register(uiExtension); | 68 | uiExtensionService.register(uiExtension); |
| 69 | +// task = new TimerTask() { | ||
| 70 | +// @Override | ||
| 71 | +// public void run() { | ||
| 72 | +// Sample sample = new Sample(System.currentTimeMillis(), headers.size()); | ||
| 73 | +// for (int i = 0; i < headers.size(); i++) { | ||
| 74 | +// sample.data[i] = 25_000 + random.nextInt(20_000) - 5_000; | ||
| 75 | +// } | ||
| 76 | +// reportSample(sample); | ||
| 77 | +// } | ||
| 78 | +// }; | ||
| 79 | +// SharedExecutors.getTimer().scheduleAtFixedRate(task, 1000, 1000); | ||
| 59 | } | 80 | } |
| 60 | 81 | ||
| 61 | @Deactivate | 82 | @Deactivate |
| ... | @@ -74,6 +95,15 @@ public class IntentPerfUi { | ... | @@ -74,6 +95,15 @@ public class IntentPerfUi { |
| 74 | } | 95 | } |
| 75 | } | 96 | } |
| 76 | 97 | ||
| 98 | + /** | ||
| 99 | + * Sets the headers for the subsequently reported samples. | ||
| 100 | + * | ||
| 101 | + * @param headers list of headers for future samples | ||
| 102 | + */ | ||
| 103 | + public void setHeaders(List<String> headers) { | ||
| 104 | + this.headers = headers; | ||
| 105 | + } | ||
| 106 | + | ||
| 77 | // Creates and returns session specific message handler. | 107 | // Creates and returns session specific message handler. |
| 78 | private Collection<UiMessageHandler> newHandlers() { | 108 | private Collection<UiMessageHandler> newHandlers() { |
| 79 | return ImmutableList.of(new StreamingControl()); | 109 | return ImmutableList.of(new StreamingControl()); |
| ... | @@ -90,7 +120,22 @@ public class IntentPerfUi { | ... | @@ -90,7 +120,22 @@ public class IntentPerfUi { |
| 90 | 120 | ||
| 91 | @Override | 121 | @Override |
| 92 | public void process(ObjectNode message) { | 122 | public void process(ObjectNode message) { |
| 93 | - streamingEnabled = message.path("event").asText("unknown").equals("initPerfStart"); | 123 | + streamingEnabled = message.path("event").asText("unknown").equals("intentPerfStart"); |
| 124 | + if (streamingEnabled) { | ||
| 125 | + sendHeaders(); | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + private void sendHeaders() { | ||
| 130 | + ArrayNode an = mapper.createArrayNode(); | ||
| 131 | + for (String header : headers) { | ||
| 132 | + an.add(header); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + ObjectNode sn = mapper.createObjectNode(); | ||
| 136 | + sn.set("headers", an); | ||
| 137 | + | ||
| 138 | + connection().sendMessage("intentPerfHeaders", 0, sn); | ||
| 94 | } | 139 | } |
| 95 | 140 | ||
| 96 | @Override | 141 | @Override |
| ... | @@ -106,10 +151,18 @@ public class IntentPerfUi { | ... | @@ -106,10 +151,18 @@ public class IntentPerfUi { |
| 106 | } | 151 | } |
| 107 | 152 | ||
| 108 | private void send(Sample sample) { | 153 | private void send(Sample sample) { |
| 109 | - // FIXME: finish this | 154 | + if (streamingEnabled) { |
| 110 | - ObjectNode sn = mapper.createObjectNode() | 155 | + ArrayNode an = mapper.createArrayNode(); |
| 111 | - .put("time", sample.time); | 156 | + for (double d : sample.data) { |
| 112 | - connection().sendMessage("intentPerf", 0, sn); | 157 | + an.add(d); |
| 158 | + } | ||
| 159 | + | ||
| 160 | + ObjectNode sn = mapper.createObjectNode(); | ||
| 161 | + sn.put("time", sample.time); | ||
| 162 | + sn.set("data", an); | ||
| 163 | + | ||
| 164 | + connection().sendMessage("intentPerfSample", 0, sn); | ||
| 165 | + } | ||
| 113 | } | 166 | } |
| 114 | } | 167 | } |
| 115 | 168 | ... | ... |
| ... | @@ -18,39 +18,35 @@ | ... | @@ -18,39 +18,35 @@ |
| 18 | ONOS GUI -- Intent Perf View -- CSS file | 18 | ONOS GUI -- Intent Perf View -- CSS file |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | -.light #ov-intentPerf { | 21 | +svg { |
| 22 | - color: navy; | 22 | + font: 12px sans-serif; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | -.dark #ov-intentPerf { | 25 | +.line { |
| 26 | - color: #1e5e6f; | 26 | + fill: none; |
| 27 | -} | 27 | + stroke: #000; |
| 28 | - | 28 | + stroke-width: 2px; |
| 29 | -.dark a { | ||
| 30 | - color: #88c; | ||
| 31 | -} | ||
| 32 | - | ||
| 33 | -#ov-intentPerf .msg { | ||
| 34 | - color: darkorange; | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | -.light #ov-intentPerf .msg { | ||
| 38 | - color: darkorange; | ||
| 39 | -} | ||
| 40 | - | ||
| 41 | -.dark #ov-intentPerf .msg { | ||
| 42 | - color: #904e00; | ||
| 43 | } | 29 | } |
| 44 | 30 | ||
| 45 | - | ||
| 46 | - | ||
| 47 | .axis path, | 31 | .axis path, |
| 48 | .axis line { | 32 | .axis line { |
| 49 | fill: none; | 33 | fill: none; |
| 50 | - stroke: #000; | 34 | + stroke-width: 2px; |
| 51 | shape-rendering: crispEdges; | 35 | shape-rendering: crispEdges; |
| 52 | } | 36 | } |
| 53 | 37 | ||
| 54 | -.browser text { | 38 | +.light .axis path, |
| 55 | - text-anchor: end; | 39 | +.light .axis line, |
| 40 | +.light .axis text { | ||
| 41 | + stroke: #999; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +.dark .axis path, | ||
| 45 | +.dark .axis line, | ||
| 46 | +.dark .axis text { | ||
| 47 | + stroke: #eee; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +.axis text { | ||
| 51 | + stroke-width: 0.3; | ||
| 56 | } | 52 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -15,10 +15,12 @@ | ... | @@ -15,10 +15,12 @@ |
| 15 | --> | 15 | --> |
| 16 | 16 | ||
| 17 | <!-- Intent Performance partial HTML --> | 17 | <!-- Intent Performance partial HTML --> |
| 18 | -<div id="ov-sample"> | 18 | +<div id="ov-intentPerf"> |
| 19 | <h2> Intent Performance View </h2> | 19 | <h2> Intent Performance View </h2> |
| 20 | 20 | ||
| 21 | - <span class="msg">{{ ctrl.message }}</span> | 21 | + <div id="intent-perf-chart" |
| 22 | - | 22 | + resize |
| 23 | - <div id="intent-perf-chart"></div> | 23 | + ng-style="resizeWithOffset(56, 12)" |
| 24 | + notifier="ctrl.notifyResize()"> | ||
| 25 | + </div> | ||
| 24 | </div> | 26 | </div> | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -18,8 +18,6 @@ | ... | @@ -18,8 +18,6 @@ |
| 18 | <head> | 18 | <head> |
| 19 | <title>Dev View</title> | 19 | <title>Dev View</title> |
| 20 | <script src="tp/d3.min.js"></script> | 20 | <script src="tp/d3.min.js"></script> |
| 21 | - <script src="tp/jquery-2.1.1.min.js"></script> | ||
| 22 | - | ||
| 23 | <link rel="stylesheet" href="app/view/intentPerf/intentPerf.css"> | 21 | <link rel="stylesheet" href="app/view/intentPerf/intentPerf.css"> |
| 24 | </head> | 22 | </head> |
| 25 | <body> | 23 | <body> | ... | ... |
| 1 | +<!DOCTYPE html> | ||
| 2 | +<meta charset="utf-8"> | ||
| 3 | +<style> | ||
| 4 | + | ||
| 5 | + svg { | ||
| 6 | + font: 10px sans-serif; | ||
| 7 | + } | ||
| 8 | + | ||
| 9 | + .line { | ||
| 10 | + fill: none; | ||
| 11 | + stroke: darkgreen; | ||
| 12 | + stroke-width: 2px; | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + .axis path, | ||
| 16 | + .axis line { | ||
| 17 | + fill: none; | ||
| 18 | + stroke: #999; | ||
| 19 | + stroke-width: 2px; | ||
| 20 | + shape-rendering: crispEdges; | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | +</style> | ||
| 24 | +<body> | ||
| 25 | +<script src="http://d3js.org/d3.v3.min.js"></script> | ||
| 26 | +<script> | ||
| 27 | + (function () { | ||
| 28 | + var cs = 0, | ||
| 29 | + samples = [ | ||
| 30 | + 89.53, | ||
| 31 | + 37515.81, | ||
| 32 | + 104609.6, | ||
| 33 | + 113105.11, | ||
| 34 | + 103194.74, | ||
| 35 | + 122151.63, | ||
| 36 | + 128623.9, | ||
| 37 | + 137325.33, | ||
| 38 | + 154897.31, | ||
| 39 | + 161235.07, | ||
| 40 | + 162025.4, | ||
| 41 | + 164902.64, | ||
| 42 | + 158196.26, | ||
| 43 | + 161072.44, | ||
| 44 | + 160792.54, | ||
| 45 | + 164692.44, | ||
| 46 | + 161979.74, | ||
| 47 | + 162137.4, | ||
| 48 | + 159325.19, | ||
| 49 | + 170465.44, | ||
| 50 | + 168186.46, | ||
| 51 | + 171152.34, | ||
| 52 | + 168221.02, | ||
| 53 | + 167440.73, | ||
| 54 | + 165003.39, | ||
| 55 | + 166855.18, | ||
| 56 | + 157268.79, | ||
| 57 | + 164087.54, | ||
| 58 | + 162265.21, | ||
| 59 | + 165990.16, | ||
| 60 | + 176364.01, | ||
| 61 | + 172064.07, | ||
| 62 | + 184872.24, | ||
| 63 | + 183249.8, | ||
| 64 | + 182282.47, | ||
| 65 | + 171475.11, | ||
| 66 | + 158880.58, | ||
| 67 | + 166016.69, | ||
| 68 | + 168233.16, | ||
| 69 | + 177759.92, | ||
| 70 | + 179742.87, | ||
| 71 | + 170819.44, | ||
| 72 | + 167577.73, | ||
| 73 | + 169479.9, | ||
| 74 | + 175544.89, | ||
| 75 | + 183792.01, | ||
| 76 | + 184689.52, | ||
| 77 | + 178503.87, | ||
| 78 | + 173219.27, | ||
| 79 | + 179085.49, | ||
| 80 | + 179700.54, | ||
| 81 | + 174281.17, | ||
| 82 | + 181353.08, | ||
| 83 | + 180173.14, | ||
| 84 | + 184093.16, | ||
| 85 | + 186011.5, | ||
| 86 | + 176952.79, | ||
| 87 | + 175319.2, | ||
| 88 | + 169001.05, | ||
| 89 | + 174545.12, | ||
| 90 | + 169156.29, | ||
| 91 | + 171804.3, | ||
| 92 | + 159155.54, | ||
| 93 | + 154709.96, | ||
| 94 | + 157263.97 | ||
| 95 | + ], | ||
| 96 | + theSample, | ||
| 97 | + headers = [ "Whole", "Half", "Third" ]; | ||
| 98 | + | ||
| 99 | + var n = 243, | ||
| 100 | + duration = 750, | ||
| 101 | + now = new Date(Date.now() - duration), | ||
| 102 | + data = []; | ||
| 103 | + | ||
| 104 | + headers.forEach(function (d, li) { | ||
| 105 | + data[li] = d3.range(n).map(function () { return 0; }); | ||
| 106 | + }); | ||
| 107 | + | ||
| 108 | + var margin = {top: 20, right: 100, bottom: 20, left: 100}, | ||
| 109 | + width = 960 - margin.right, | ||
| 110 | + height = 512 - margin.top - margin.bottom; | ||
| 111 | + | ||
| 112 | + var x = d3.time.scale() | ||
| 113 | + .domain([now - (n - 2) * duration, now - duration]) | ||
| 114 | + .range([0, width]); | ||
| 115 | + | ||
| 116 | + var y = d3.scale.linear() | ||
| 117 | + .domain([0, 200000]) | ||
| 118 | + .range([height, 0]); | ||
| 119 | + | ||
| 120 | + var svg = d3.select("body").append("p").append("svg") | ||
| 121 | + .attr("width", width + margin.left + margin.right) | ||
| 122 | + .attr("height", height + margin.top + margin.bottom) | ||
| 123 | + .append("g") | ||
| 124 | + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | ||
| 125 | + | ||
| 126 | + svg.append("defs").append("clipPath") | ||
| 127 | + .attr("id", "clip") | ||
| 128 | + .append("rect") | ||
| 129 | + .attr("width", width) | ||
| 130 | + .attr("height", height); | ||
| 131 | + | ||
| 132 | + var axis = svg.append("g") | ||
| 133 | + .attr("class", "x axis") | ||
| 134 | + .attr("transform", "translate(0," + height + ")") | ||
| 135 | + .call(x.axis = d3.svg.axis().scale(x).orient("bottom")); | ||
| 136 | + | ||
| 137 | + svg.append("g") | ||
| 138 | + .attr("class", "y axis") | ||
| 139 | + .call(d3.svg.axis().scale(y).orient("left")); | ||
| 140 | + | ||
| 141 | + svg.append("g") | ||
| 142 | + .attr("class", "y axis") | ||
| 143 | + .attr("transform", "translate(" + width + " ,0)") | ||
| 144 | + .call(d3.svg.axis().scale(y).orient("right")); | ||
| 145 | + | ||
| 146 | + var lines = [], paths = []; | ||
| 147 | + data.forEach(function (p, li) { | ||
| 148 | + lines[li]= d3.svg.line() | ||
| 149 | + .interpolate("basis") | ||
| 150 | + .x(function (d, i) { | ||
| 151 | + return x(now - (n - 1 - i) * duration); | ||
| 152 | + }) | ||
| 153 | + .y(function (d, i) { | ||
| 154 | + return y(d); | ||
| 155 | + }); | ||
| 156 | + | ||
| 157 | + paths[li] = svg.append("g") | ||
| 158 | + .attr("clip-path", "url(#clip)") | ||
| 159 | + .append("path") | ||
| 160 | + .datum(function () { return data[li]; }) | ||
| 161 | + .attr("id", "line" + li) | ||
| 162 | + .attr("class", "line"); | ||
| 163 | + }); | ||
| 164 | + | ||
| 165 | + var transition = d3.select({}).transition() | ||
| 166 | + .duration(750) | ||
| 167 | + .ease("linear"); | ||
| 168 | + | ||
| 169 | + function tick() { | ||
| 170 | + transition = transition.each(function () { | ||
| 171 | + // update the domains | ||
| 172 | + now = new Date(); | ||
| 173 | + x.domain([now - (n - 2) * duration, now - duration]); | ||
| 174 | + | ||
| 175 | + data.forEach(function (d, li) { | ||
| 176 | + // push the new most recent sample onto the back | ||
| 177 | + d.push(theSample[li]); | ||
| 178 | + | ||
| 179 | + // redraw the line and slide it left | ||
| 180 | + paths[li].attr("d", lines[li]).attr("transform", null); | ||
| 181 | + paths[li].transition().attr("transform", "translate(" + x(now - (n - 1) * duration) + ")"); | ||
| 182 | + | ||
| 183 | + // pop the old data point off the front | ||
| 184 | + d.shift(); | ||
| 185 | + }); | ||
| 186 | + | ||
| 187 | + // slide the x-axis left | ||
| 188 | + axis.call(x.axis); | ||
| 189 | + | ||
| 190 | + }).transition().each("start", tick); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + function setSample() { | ||
| 194 | + var v = samples[cs++]; | ||
| 195 | + theSample = [ v, v/2, v/3 ]; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + setSample(); | ||
| 199 | + setInterval(setSample, 1000); | ||
| 200 | + tick(); | ||
| 201 | + | ||
| 202 | + })() | ||
| 203 | +</script> | ||
| 204 | +</body> | ||
| 205 | +</html> |
| ... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
| 21 | /* ------ for summary-list tables ------ */ | 21 | /* ------ for summary-list tables ------ */ |
| 22 | 22 | ||
| 23 | table.summary-list { | 23 | table.summary-list { |
| 24 | - margin: 0 50px 50px 50px; | 24 | + margin: 0 20px 16px 12px; |
| 25 | font-size: 10pt; | 25 | font-size: 10pt; |
| 26 | border-spacing: 0; | 26 | border-spacing: 0; |
| 27 | } | 27 | } | ... | ... |
-
Please register or login to post a comment