blob: 94304c73a786c1bcf1a60164aadce42accca5f27 [file] [log] [blame]
Brian O'Connora468e902015-03-18 16:43:49 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Intent Performance View Module
19 */
20(function () {
21 'use strict';
22
23 // injected refs
Thomas Vachuska95aadff2015-03-26 11:45:41 -070024 var $log, tbs, ts, wss, sus, flash, fs, mast;
Brian O'Connora468e902015-03-18 16:43:49 -070025
Thomas Vachuska95aadff2015-03-26 11:45:41 -070026 // internal state
27 var handlerMap,
28 openListener,
29 theSample = [],
30 graph;
Brian O'Connora468e902015-03-18 16:43:49 -070031
Thomas Vachuska95aadff2015-03-26 11:45:41 -070032 // ==========================
Brian O'Connora468e902015-03-18 16:43:49 -070033
Thomas Vachuskab967ebf2015-03-28 15:19:30 -070034 function createGraph(h, samples) {
Thomas Vachuska95aadff2015-03-26 11:45:41 -070035 var stopped = false,
36 n = 243,
37 duration = 750,
38 now = new Date(Date.now() - duration),
39 headers = h,
40 data = [];
Brian O'Connora468e902015-03-18 16:43:49 -070041
Thomas Vachuska95aadff2015-03-26 11:45:41 -070042 var dim = fs.windowSize(mast.mastHeight());
43 var margin, width, height, x, y;
44 var svg, axis;
Brian O'Connora468e902015-03-18 16:43:49 -070045
Thomas Vachuska95aadff2015-03-26 11:45:41 -070046 var lines = [],
47 paths = [];
Brian O'Connora468e902015-03-18 16:43:49 -070048
Thomas Vachuska95aadff2015-03-26 11:45:41 -070049 var transition = d3.select({}).transition()
50 .duration(duration)
51 .ease("linear");
Brian O'Connora468e902015-03-18 16:43:49 -070052
Thomas Vachuska72dd99d2015-03-27 18:41:18 -070053 svg = d3.select("#intent-perf-chart").append("p").append("svg")
54 .attr("id", "intent-perf-svg")
55 .append("g")
56 .attr("id", "intent-perf-svg-g");
Brian O'Connora468e902015-03-18 16:43:49 -070057
Thomas Vachuska72dd99d2015-03-27 18:41:18 -070058 svg.append("defs").append("clipPath")
59 .attr("id", "intent-perf-clip")
Thomas Vachuska95aadff2015-03-26 11:45:41 -070060 .append("rect");
Brian O'Connora468e902015-03-18 16:43:49 -070061
Thomas Vachuska95aadff2015-03-26 11:45:41 -070062 axis = svg.append("g")
Brian O'Connora468e902015-03-18 16:43:49 -070063 .attr("class", "x axis")
Thomas Vachuska95aadff2015-03-26 11:45:41 -070064 .attr("id", "intent-perf-x");
65
66 svg.append("g").attr("class", "y axis")
67 .attr("id", "intent-perf-yl");
Brian O'Connora468e902015-03-18 16:43:49 -070068
69 svg.append("g")
70 .attr("class", "y axis")
Thomas Vachuska95aadff2015-03-26 11:45:41 -070071 .attr("id", "intent-perf-yr");
Brian O'Connora468e902015-03-18 16:43:49 -070072
Thomas Vachuska95aadff2015-03-26 11:45:41 -070073 resize(dim);
74
75 headers.forEach(function (h, li) {
Thomas Vachuska90c7be22015-03-27 14:12:46 -070076 // Prime the data to match the headers and zero it out.
Thomas Vachuska95aadff2015-03-26 11:45:41 -070077 data[li] = d3.range(n).map(function() { return 0 });
Thomas Vachuskab967ebf2015-03-28 15:19:30 -070078
79 if (li < headers.length - 1) {
80 samples.forEach(function (s, i) {
81 var di = dataIndex(s.time);
82 if (di >= 0) {
83 data[li][di] = s.data[li];
84 }
85 });
86
87 data[li].forEach(function (d, i) {
88 if (!d && i > 0) {
89 data[li][i] = data[li][i - 1];
90 }
91 });
92 } else {
93 data[li].forEach(function (t, i) {
94 for (var si = 0; si < headers.length - 1; si++) {
95 data[li][i] = data[si][i];
96 }
97 });
98 }
Thomas Vachuska95aadff2015-03-26 11:45:41 -070099
100 // Create the lines
101 lines[li] = d3.svg.line()
102 .interpolate("basis")
103 .x(function(d, i) { return x(now - (n - 1 - i) * duration); })
104 .y(function(d, i) { return y(d); });
105
106 // Create the SVG paths
107 paths[li] = svg.append("g")
108 .attr("clip-path", "url(#intent-perf-clip)")
109 .append("path")
110 .datum(function () { return data[li]; })
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700111 .attr("id", "line" + li);
112
113 if (li < headers.length - 1) {
114 paths[li].attr("class", "line").style("stroke", lineColor(li));
115 } else {
116 paths[li].attr("class", "lineTotal");
117 }
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700118 });
119
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700120 function dataIndex(time) {
121 var delta = now.getTime() - time;
122 var di = Math.round(n - 2 - (delta / duration));
123 // $log.info('now=' + now.getTime() + '; then=' + time + '; delta=' + delta + '; di=' + di + ';');
124 return di >= n || di < 0 ? -1 : di;
125 }
126
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700127 function lineColor(li) {
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700128 return sus.cat7().getColor(li, false, ts.theme());
Brian O'Connora468e902015-03-18 16:43:49 -0700129 }
130
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700131 function tick() {
132 if (stopped) {
133 return;
134 }
135
136 transition = transition.each(function() {
137 // update the domains
138 now = new Date();
139 x.domain([now - (n - 2) * duration, now - duration]);
140
141 data.forEach(function (d, li) {
142 // push the new most recent sample onto the back
143 d.push(theSample[li]);
144
145 // redraw the line and slide it left
146 paths[li].attr("d", lines[li]).attr("transform", null);
Thomas Vachuska90c7be22015-03-27 14:12:46 -0700147 paths[li].transition()
148 .attr("transform", "translate(" + x(now - (n - 1) * duration) + ")");
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700149
150 // pop the old data point off the front
151 d.shift();
152 });
153
154 // slide the x-axis left
155 axis.call(x.axis);
156 }).transition().each("start", tick);
157 }
158
159 function start() {
160 stopped = false;
161 headers.forEach(function (h, li) {
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700162 theSample[li] = data[li][n-1];
Brian O'Connora468e902015-03-18 16:43:49 -0700163 });
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700164 tick();
165 }
Brian O'Connora468e902015-03-18 16:43:49 -0700166
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700167 function stop() {
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700168 headers.forEach(function (h, li) {
169 theSample[li] = 0;
170 });
171 // Schedule delayed stop to allow 0s to render.
172 setTimeout(function () { stopped = true; }, 1000);
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700173 }
Brian O'Connora468e902015-03-18 16:43:49 -0700174
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700175 function resize(dim) {
176 margin = {top: 20, right: 90, bottom: 20, left: 70};
177 width = dim.width - margin.right - margin.left;
178 height = 480 - margin.top - margin.bottom;
Brian O'Connora468e902015-03-18 16:43:49 -0700179
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700180 x = d3.time.scale()
181 .domain([now - (n - 2) * duration, now - duration])
182 .range([0, width]);
Brian O'Connora468e902015-03-18 16:43:49 -0700183
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700184 y = d3.scale.linear()
185 .domain([0, 200000])
186 .range([height, 0]);
187
188 d3.select("#intent-perf-svg")
189 .attr("width", width + margin.left + margin.right)
190 .attr("height", height + margin.top + margin.bottom);
191 d3.select("#intent-perf-svg-g")
192 .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
193
Thomas Vachuska72dd99d2015-03-27 18:41:18 -0700194 d3.select("#intent-perf-clip rect")
195 .attr("width", width)
196 .attr("height", height);
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700197
198 d3.select("#intent-perf-x")
Brian O'Connora468e902015-03-18 16:43:49 -0700199 .attr("transform", "translate(0," + height + ")")
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700200 .call(x.axis = d3.svg.axis().scale(x).orient("bottom"));
Brian O'Connora468e902015-03-18 16:43:49 -0700201
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700202 d3.select("#intent-perf-yl")
203 .call(d3.svg.axis().scale(y).orient("left"))
204 d3.select("#intent-perf-yr")
205 .attr("transform", "translate(" + width + " ,0)")
206 .call(d3.svg.axis().scale(y).orient("right"))
Brian O'Connora468e902015-03-18 16:43:49 -0700207 }
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700208
209 return {
210 start: start,
211 stop: stop,
212 resize: resize
213 };
Brian O'Connora468e902015-03-18 16:43:49 -0700214 }
215
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700216
217 function wsOpen(host, url) {
218 $log.debug('IntentPerf: web socket open - cluster node:', host, 'URL:', url);
219 // Request batch of initial data from the new server
220 wss.sendEvent('intentPerfStart');
221 }
222
223 function createAndInitGraph(d) {
224 if (!graph) {
225 d.headers.push("total");
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700226 graph = createGraph(d.headers, d.samples);
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700227 }
228 graph.start();
229 }
230
231 function graphResized(dim) {
232 $log.info("Resized: " + dim.width + "x" + dim.height);
Thomas Vachuska72dd99d2015-03-27 18:41:18 -0700233 if (graph) {
234 graph.resize(dim);
235 }
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700236 }
237
238 function recordSample(sample) {
239 var total = 0;
240 sample.data.forEach(function (d, i) {
241 theSample[i] = d;
242 total = total + d;
243 });
244 theSample[sample.data.length] = total;
245 }
246
247 function createHandlerMap() {
248 handlerMap = {
Thomas Vachuskab967ebf2015-03-28 15:19:30 -0700249 intentPerfInit: createAndInitGraph,
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700250 intentPerfSample: recordSample
251 };
252 }
253
Brian O'Connora468e902015-03-18 16:43:49 -0700254 // define the controller
255
256 angular.module('ovIntentPerf', ['onosUtil'])
257 .controller('OvIntentPerfCtrl',
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700258 ['$scope', '$log', 'ToolbarService', 'WebSocketService',
259 'ThemeService', 'FlashService', 'SvgUtilService', 'FnService',
260 'MastService',
Brian O'Connora468e902015-03-18 16:43:49 -0700261
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700262 function ($scope, _$log_, _tbs_, _wss_, _ts_, _flash_, _sus_, _fs_, _mast_) {
263 var self = this;
Brian O'Connora468e902015-03-18 16:43:49 -0700264
265 $log = _$log_;
266 tbs = _tbs_;
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700267 wss = _wss_;
268 ts = _ts_;
Brian O'Connora468e902015-03-18 16:43:49 -0700269 flash = _flash_;
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700270 sus = _sus_;
271 fs = _fs_;
272 mast = _mast_;
Brian O'Connora468e902015-03-18 16:43:49 -0700273
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700274 createHandlerMap();
Brian O'Connora468e902015-03-18 16:43:49 -0700275
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700276 self.notifyResize = function () {
277 graphResized(fs.windowSize(mast.mastHeight()));
278 };
279
280 function start() {
281 openListener = wss.addOpenListener(wsOpen);
282 wss.bindHandlers(handlerMap);
283 wss.sendEvent('intentPerfStart');
284 $log.debug('intentPerf comms started');
285 }
286
287 function stop() {
288 graph.stop();
289 wss.sendEvent('intentPerfStop');
290 wss.unbindHandlers(handlerMap);
291 wss.removeOpenListener(openListener);
292 openListener = null;
293 graph = null;
294 $log.debug('intentPerf comms stopped');
295 }
296
297 // Cleanup on destroyed scope..
Brian O'Connora468e902015-03-18 16:43:49 -0700298 $scope.$on('$destroy', function () {
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700299 $log.log('OvIntentPerfCtrl is saying Buh-Bye!');
300 stop();
Brian O'Connora468e902015-03-18 16:43:49 -0700301 });
302
Thomas Vachuska90c7be22015-03-27 14:12:46 -0700303 $log.log('OvIntentPerfCtrl has been created');
304
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700305 start();
306 }]);
Brian O'Connora468e902015-03-18 16:43:49 -0700307}());