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
501 additions
and
116 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; | ||
56 | } | 48 | } |
49 | + | ||
50 | +.axis text { | ||
51 | + stroke-width: 0.3; | ||
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> | ... | ... |
... | @@ -21,122 +21,248 @@ | ... | @@ -21,122 +21,248 @@ |
21 | 'use strict'; | 21 | 'use strict'; |
22 | 22 | ||
23 | // injected refs | 23 | // injected refs |
24 | - var $log, tbs, flash; | 24 | + var $log, tbs, ts, wss, sus, flash, fs, mast; |
25 | 25 | ||
26 | - function start() { | 26 | + // internal state |
27 | - //var format = d3.time.format("%m/%d/%y"); | 27 | + var handlerMap, |
28 | - var format = d3.time.format("%H:%M:%S"); | 28 | + openListener, |
29 | - var samples = []; | 29 | + theSample = [], |
30 | + graph; | ||
30 | 31 | ||
31 | - var margin = {top: 20, right: 30, bottom: 30, left: 40}, | 32 | + // ========================== |
32 | - width = 960 - margin.left - margin.right, | ||
33 | - height = 500 - margin.top - margin.bottom; | ||
34 | 33 | ||
35 | - var x = d3.time.scale() | 34 | + function createGraph(h) { |
36 | - .range([0, width]); | 35 | + var stopped = false, |
36 | + n = 243, | ||
37 | + duration = 750, | ||
38 | + now = new Date(Date.now() - duration), | ||
39 | + headers = h, | ||
40 | + data = []; | ||
37 | 41 | ||
38 | - var y = d3.scale.linear() | 42 | + var dim = fs.windowSize(mast.mastHeight()); |
39 | - .range([height, 0]); | 43 | + var margin, width, height, x, y; |
44 | + var svg, axis; | ||
40 | 45 | ||
41 | - var z = d3.scale.category20c(); | 46 | + var lines = [], |
47 | + paths = []; | ||
42 | 48 | ||
43 | - var xAxis = d3.svg.axis() | 49 | + var transition = d3.select({}).transition() |
44 | - .scale(x) | 50 | + .duration(duration) |
45 | - .orient("bottom") | 51 | + .ease("linear"); |
46 | - .ticks(d3.time.seconds); | ||
47 | 52 | ||
48 | - var yAxis = d3.svg.axis() | 53 | + svg = d3.select("#intent-perf-chart").append("p") |
49 | - .scale(y) | 54 | + .append("svg").attr("id", "intent-perf-svg") |
50 | - .orient("left"); | 55 | + .append("g").attr("id", "intent-perf-svg-g"); |
51 | 56 | ||
52 | - var stack = d3.layout.stack() | 57 | + svg.append("defs").append("clipPath").attr("id", "intent-perf-clip") |
53 | - .offset("zero") | 58 | + .append("rect"); |
54 | - .values(function(d) { return d.values; }) | ||
55 | - .x(function(d) { return d.date; }) | ||
56 | - .y(function(d) { return d.value; }); | ||
57 | 59 | ||
58 | - var nest = d3.nest() | 60 | + axis = svg.append("g") |
59 | - .key(function(d) { return d.key; }); | ||
60 | - | ||
61 | - var area = d3.svg.area() | ||
62 | - .interpolate("cardinal") | ||
63 | - .x(function(d) { return x(d.date); }) | ||
64 | - .y0(function(d) { return y(d.y0); }) | ||
65 | - .y1(function(d) { return y(d.y0 + d.y); }); | ||
66 | - | ||
67 | - var svg = d3.select("body").append("svg") | ||
68 | - .attr("width", width + margin.left + margin.right) | ||
69 | - .attr("height", height + margin.top + margin.bottom) | ||
70 | - .append("g") | ||
71 | - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | ||
72 | - | ||
73 | - svg.append("g") | ||
74 | .attr("class", "x axis") | 61 | .attr("class", "x axis") |
75 | - .attr("transform", "translate(0," + height + ")") | 62 | + .attr("id", "intent-perf-x"); |
76 | - .call(xAxis); | 63 | + |
64 | + svg.append("g").attr("class", "y axis") | ||
65 | + .attr("id", "intent-perf-yl"); | ||
77 | 66 | ||
78 | svg.append("g") | 67 | svg.append("g") |
79 | .attr("class", "y axis") | 68 | .attr("class", "y axis") |
80 | - .call(yAxis); | 69 | + .attr("id", "intent-perf-yr"); |
81 | 70 | ||
82 | - function fetchData() { | 71 | + resize(dim); |
83 | - d3.csv("app/view/intentPerf/data.csv", function (data) { | 72 | + |
84 | - samples = data; | 73 | + headers.forEach(function (h, li) { |
85 | - updateGraph(); | 74 | + // Prime the data to match the headeres and zero it out. |
86 | - }); | 75 | + data[li] = d3.range(n).map(function() { return 0 }); |
76 | + theSample[li] = 0; | ||
77 | + | ||
78 | + // Create the lines | ||
79 | + lines[li] = d3.svg.line() | ||
80 | + .interpolate("basis") | ||
81 | + .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) | ||
82 | + .y(function(d, i) { return y(d); }); | ||
83 | + | ||
84 | + // Create the SVG paths | ||
85 | + paths[li] = svg.append("g") | ||
86 | + .attr("clip-path", "url(#intent-perf-clip)") | ||
87 | + .append("path") | ||
88 | + .datum(function () { return data[li]; }) | ||
89 | + .attr("id", "line" + li) | ||
90 | + .style("stroke", lineColor(li)) | ||
91 | + .attr("class", "line"); | ||
92 | + }); | ||
93 | + | ||
94 | + function lineColor(li) { | ||
95 | + return li < headers.length - 1 ? | ||
96 | + sus.cat7().getColor(li, false, ts.theme()) : | ||
97 | + ts.theme() == 'light' ? '#333' : '#eee'; | ||
87 | } | 98 | } |
88 | 99 | ||
89 | - function updateGraph() { | 100 | + function tick() { |
90 | - samples.forEach(function(d) { | 101 | + if (stopped) { |
91 | - d.date = format.parse(d.date); | 102 | + return; |
92 | - d.value = +d.value; | 103 | + } |
104 | + | ||
105 | + transition = transition.each(function() { | ||
106 | + // update the domains | ||
107 | + now = new Date(); | ||
108 | + x.domain([now - (n - 2) * duration, now - duration]); | ||
109 | + | ||
110 | + data.forEach(function (d, li) { | ||
111 | + // push the new most recent sample onto the back | ||
112 | + d.push(theSample[li]); | ||
113 | + | ||
114 | + // redraw the line and slide it left | ||
115 | + paths[li].attr("d", lines[li]).attr("transform", null); | ||
116 | + paths[li].transition().attr("transform", "translate(" + x(now - (n - 1) * duration) + ")"); | ||
117 | + | ||
118 | + // pop the old data point off the front | ||
119 | + d.shift(); | ||
120 | + }); | ||
121 | + | ||
122 | + // slide the x-axis left | ||
123 | + axis.call(x.axis); | ||
124 | + }).transition().each("start", tick); | ||
125 | + } | ||
126 | + | ||
127 | + function start() { | ||
128 | + stopped = false; | ||
129 | + headers.forEach(function (h, li) { | ||
130 | + theSample[li] = 0; | ||
93 | }); | 131 | }); |
132 | + tick(); | ||
133 | + } | ||
134 | + | ||
135 | + function stop() { | ||
136 | + stopped = true; | ||
137 | + } | ||
94 | 138 | ||
95 | - var layers = stack(nest.entries(samples)); | 139 | + function resize(dim) { |
140 | + margin = {top: 20, right: 90, bottom: 20, left: 70}; | ||
141 | + width = dim.width - margin.right - margin.left; | ||
142 | + height = 480 - margin.top - margin.bottom; | ||
96 | 143 | ||
97 | - x.domain(d3.extent(samples, function(d) { return d.date; })); | 144 | + x = d3.time.scale() |
98 | - y.domain([0, d3.max(samples, function(d) { return d.y0 + d.y; })]); | 145 | + .domain([now - (n - 2) * duration, now - duration]) |
146 | + .range([0, width]); | ||
99 | 147 | ||
100 | - svg.selectAll(".layer") | 148 | + y = d3.scale.linear() |
101 | - .data(layers) | 149 | + .domain([0, 200000]) |
102 | - .enter().append("path") | 150 | + .range([height, 0]); |
103 | - .attr("class", "layer") | ||
104 | - .attr("d", function(d) { return area(d.values); }) | ||
105 | - .style("fill", function(d, i) { return z(i); }); | ||
106 | 151 | ||
107 | - svg.select(".x") | 152 | + d3.select("#intent-perf-svg") |
153 | + .attr("width", width + margin.left + margin.right) | ||
154 | + .attr("height", height + margin.top + margin.bottom); | ||
155 | + d3.select("#intent-perf-svg-g") | ||
156 | + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | ||
157 | + | ||
158 | + d3.select("#intent-pef-clip rect").attr("width", width).attr("height", height); | ||
159 | + | ||
160 | + d3.select("#intent-perf-x") | ||
108 | .attr("transform", "translate(0," + height + ")") | 161 | .attr("transform", "translate(0," + height + ")") |
109 | - .call(xAxis); | 162 | + .call(x.axis = d3.svg.axis().scale(x).orient("bottom")); |
163 | + | ||
164 | + d3.select("#intent-perf-yl") | ||
165 | + .call(d3.svg.axis().scale(y).orient("left")) | ||
166 | + d3.select("#intent-perf-yr") | ||
167 | + .attr("transform", "translate(" + width + " ,0)") | ||
168 | + .call(d3.svg.axis().scale(y).orient("right")) | ||
169 | + } | ||
170 | + | ||
171 | + return { | ||
172 | + start: start, | ||
173 | + stop: stop, | ||
174 | + resize: resize | ||
175 | + }; | ||
176 | + } | ||
177 | + | ||
110 | 178 | ||
111 | - svg.select(".y") | 179 | + function wsOpen(host, url) { |
112 | - .call(yAxis); | 180 | + $log.debug('IntentPerf: web socket open - cluster node:', host, 'URL:', url); |
181 | + // Request batch of initial data from the new server | ||
182 | + wss.sendEvent('intentPerfStart'); | ||
183 | + } | ||
113 | 184 | ||
114 | - console.log('tick'); | 185 | + function createAndInitGraph(d) { |
186 | + if (!graph) { | ||
187 | + d.headers.push("total"); | ||
188 | + graph = createGraph(d.headers); | ||
115 | } | 189 | } |
190 | + graph.start(); | ||
116 | } | 191 | } |
117 | 192 | ||
118 | - start(); | 193 | + function graphResized(dim) { |
194 | + $log.info("Resized: " + dim.width + "x" + dim.height); | ||
195 | + graph.resize(dim); | ||
196 | + } | ||
197 | + | ||
198 | + function recordSample(sample) { | ||
199 | + var total = 0; | ||
200 | + sample.data.forEach(function (d, i) { | ||
201 | + theSample[i] = d; | ||
202 | + total = total + d; | ||
203 | + }); | ||
204 | + theSample[sample.data.length] = total; | ||
205 | + } | ||
206 | + | ||
207 | + function createHandlerMap() { | ||
208 | + handlerMap = { | ||
209 | + intentPerfHeaders: createAndInitGraph, | ||
210 | + intentPerfSample: recordSample | ||
211 | + }; | ||
212 | + } | ||
213 | + | ||
214 | + //setInterval(function () { theSample = samples[++cs]; }, 5000); | ||
215 | + //createGraph(); | ||
119 | 216 | ||
120 | // define the controller | 217 | // define the controller |
121 | 218 | ||
122 | angular.module('ovIntentPerf', ['onosUtil']) | 219 | angular.module('ovIntentPerf', ['onosUtil']) |
123 | .controller('OvIntentPerfCtrl', | 220 | .controller('OvIntentPerfCtrl', |
124 | - ['$scope', '$log', 'ToolbarService', 'FlashService', | 221 | + ['$scope', '$log', 'ToolbarService', 'WebSocketService', |
222 | + 'ThemeService', 'FlashService', 'SvgUtilService', 'FnService', | ||
223 | + 'MastService', | ||
125 | 224 | ||
126 | - function ($scope, _$log_, _tbs_, _flash_) { | 225 | + function ($scope, _$log_, _tbs_, _wss_, _ts_, _flash_, _sus_, _fs_, _mast_) { |
127 | - var self = this | 226 | + var self = this; |
128 | 227 | ||
129 | $log = _$log_; | 228 | $log = _$log_; |
130 | tbs = _tbs_; | 229 | tbs = _tbs_; |
230 | + wss = _wss_; | ||
231 | + ts = _ts_; | ||
131 | flash = _flash_; | 232 | flash = _flash_; |
233 | + sus = _sus_; | ||
234 | + fs = _fs_; | ||
235 | + mast = _mast_; | ||
132 | 236 | ||
133 | - self.message = 'Hey there dudes!'; | 237 | + createHandlerMap(); |
134 | - start(); | ||
135 | 238 | ||
136 | - // Clean up on destroyed scope | 239 | + self.notifyResize = function () { |
240 | + graphResized(fs.windowSize(mast.mastHeight())); | ||
241 | + }; | ||
242 | + | ||
243 | + function start() { | ||
244 | + openListener = wss.addOpenListener(wsOpen); | ||
245 | + wss.bindHandlers(handlerMap); | ||
246 | + wss.sendEvent('intentPerfStart'); | ||
247 | + $log.debug('intentPerf comms started'); | ||
248 | + } | ||
249 | + | ||
250 | + function stop() { | ||
251 | + graph.stop(); | ||
252 | + wss.sendEvent('intentPerfStop'); | ||
253 | + wss.unbindHandlers(handlerMap); | ||
254 | + wss.removeOpenListener(openListener); | ||
255 | + openListener = null; | ||
256 | + graph = null; | ||
257 | + $log.debug('intentPerf comms stopped'); | ||
258 | + } | ||
259 | + | ||
260 | + // Cleanup on destroyed scope.. | ||
137 | $scope.$on('$destroy', function () { | 261 | $scope.$on('$destroy', function () { |
262 | + $log.log('OvIntentPerfCtrl is saying Buh-Bye!'); | ||
263 | + stop(); | ||
138 | }); | 264 | }); |
139 | 265 | ||
140 | - $log.log('OvIntentPerfCtrl has been created'); | 266 | + start(); |
141 | - }]); | 267 | + }]); |
142 | }()); | 268 | }()); | ... | ... |
... | @@ -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