diff options
Diffstat (limited to 'framework/src/onos/apps/test/intent-perf/src/main/resources/app/view/intentPerf/intentPerf.js')
-rw-r--r-- | framework/src/onos/apps/test/intent-perf/src/main/resources/app/view/intentPerf/intentPerf.js | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/framework/src/onos/apps/test/intent-perf/src/main/resources/app/view/intentPerf/intentPerf.js b/framework/src/onos/apps/test/intent-perf/src/main/resources/app/view/intentPerf/intentPerf.js new file mode 100644 index 00000000..94304c73 --- /dev/null +++ b/framework/src/onos/apps/test/intent-perf/src/main/resources/app/view/intentPerf/intentPerf.js @@ -0,0 +1,307 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + ONOS GUI -- Intent Performance View Module + */ +(function () { + 'use strict'; + + // injected refs + var $log, tbs, ts, wss, sus, flash, fs, mast; + + // internal state + var handlerMap, + openListener, + theSample = [], + graph; + + // ========================== + + function createGraph(h, samples) { + var stopped = false, + n = 243, + duration = 750, + now = new Date(Date.now() - duration), + headers = h, + data = []; + + var dim = fs.windowSize(mast.mastHeight()); + var margin, width, height, x, y; + var svg, axis; + + var lines = [], + paths = []; + + var transition = d3.select({}).transition() + .duration(duration) + .ease("linear"); + + svg = d3.select("#intent-perf-chart").append("p").append("svg") + .attr("id", "intent-perf-svg") + .append("g") + .attr("id", "intent-perf-svg-g"); + + svg.append("defs").append("clipPath") + .attr("id", "intent-perf-clip") + .append("rect"); + + axis = svg.append("g") + .attr("class", "x axis") + .attr("id", "intent-perf-x"); + + svg.append("g").attr("class", "y axis") + .attr("id", "intent-perf-yl"); + + svg.append("g") + .attr("class", "y axis") + .attr("id", "intent-perf-yr"); + + resize(dim); + + headers.forEach(function (h, li) { + // Prime the data to match the headers and zero it out. + data[li] = d3.range(n).map(function() { return 0 }); + + if (li < headers.length - 1) { + samples.forEach(function (s, i) { + var di = dataIndex(s.time); + if (di >= 0) { + data[li][di] = s.data[li]; + } + }); + + data[li].forEach(function (d, i) { + if (!d && i > 0) { + data[li][i] = data[li][i - 1]; + } + }); + } else { + data[li].forEach(function (t, i) { + for (var si = 0; si < headers.length - 1; si++) { + data[li][i] = data[si][i]; + } + }); + } + + // Create the lines + lines[li] = d3.svg.line() + .interpolate("basis") + .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) + .y(function(d, i) { return y(d); }); + + // Create the SVG paths + paths[li] = svg.append("g") + .attr("clip-path", "url(#intent-perf-clip)") + .append("path") + .datum(function () { return data[li]; }) + .attr("id", "line" + li); + + if (li < headers.length - 1) { + paths[li].attr("class", "line").style("stroke", lineColor(li)); + } else { + paths[li].attr("class", "lineTotal"); + } + }); + + function dataIndex(time) { + var delta = now.getTime() - time; + var di = Math.round(n - 2 - (delta / duration)); + // $log.info('now=' + now.getTime() + '; then=' + time + '; delta=' + delta + '; di=' + di + ';'); + return di >= n || di < 0 ? -1 : di; + } + + function lineColor(li) { + return sus.cat7().getColor(li, false, ts.theme()); + } + + function tick() { + if (stopped) { + return; + } + + transition = transition.each(function() { + // update the domains + now = new Date(); + x.domain([now - (n - 2) * duration, now - duration]); + + data.forEach(function (d, li) { + // push the new most recent sample onto the back + d.push(theSample[li]); + + // redraw the line and slide it left + paths[li].attr("d", lines[li]).attr("transform", null); + paths[li].transition() + .attr("transform", "translate(" + x(now - (n - 1) * duration) + ")"); + + // pop the old data point off the front + d.shift(); + }); + + // slide the x-axis left + axis.call(x.axis); + }).transition().each("start", tick); + } + + function start() { + stopped = false; + headers.forEach(function (h, li) { + theSample[li] = data[li][n-1]; + }); + tick(); + } + + function stop() { + headers.forEach(function (h, li) { + theSample[li] = 0; + }); + // Schedule delayed stop to allow 0s to render. + setTimeout(function () { stopped = true; }, 1000); + } + + function resize(dim) { + margin = {top: 20, right: 90, bottom: 20, left: 70}; + width = dim.width - margin.right - margin.left; + height = 480 - margin.top - margin.bottom; + + x = d3.time.scale() + .domain([now - (n - 2) * duration, now - duration]) + .range([0, width]); + + y = d3.scale.linear() + .domain([0, 200000]) + .range([height, 0]); + + d3.select("#intent-perf-svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom); + d3.select("#intent-perf-svg-g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + d3.select("#intent-perf-clip rect") + .attr("width", width) + .attr("height", height); + + d3.select("#intent-perf-x") + .attr("transform", "translate(0," + height + ")") + .call(x.axis = d3.svg.axis().scale(x).orient("bottom")); + + d3.select("#intent-perf-yl") + .call(d3.svg.axis().scale(y).orient("left")) + d3.select("#intent-perf-yr") + .attr("transform", "translate(" + width + " ,0)") + .call(d3.svg.axis().scale(y).orient("right")) + } + + return { + start: start, + stop: stop, + resize: resize + }; + } + + + function wsOpen(host, url) { + $log.debug('IntentPerf: web socket open - cluster node:', host, 'URL:', url); + // Request batch of initial data from the new server + wss.sendEvent('intentPerfStart'); + } + + function createAndInitGraph(d) { + if (!graph) { + d.headers.push("total"); + graph = createGraph(d.headers, d.samples); + } + graph.start(); + } + + function graphResized(dim) { + $log.info("Resized: " + dim.width + "x" + dim.height); + if (graph) { + graph.resize(dim); + } + } + + function recordSample(sample) { + var total = 0; + sample.data.forEach(function (d, i) { + theSample[i] = d; + total = total + d; + }); + theSample[sample.data.length] = total; + } + + function createHandlerMap() { + handlerMap = { + intentPerfInit: createAndInitGraph, + intentPerfSample: recordSample + }; + } + + // define the controller + + angular.module('ovIntentPerf', ['onosUtil']) + .controller('OvIntentPerfCtrl', + ['$scope', '$log', 'ToolbarService', 'WebSocketService', + 'ThemeService', 'FlashService', 'SvgUtilService', 'FnService', + 'MastService', + + function ($scope, _$log_, _tbs_, _wss_, _ts_, _flash_, _sus_, _fs_, _mast_) { + var self = this; + + $log = _$log_; + tbs = _tbs_; + wss = _wss_; + ts = _ts_; + flash = _flash_; + sus = _sus_; + fs = _fs_; + mast = _mast_; + + createHandlerMap(); + + self.notifyResize = function () { + graphResized(fs.windowSize(mast.mastHeight())); + }; + + function start() { + openListener = wss.addOpenListener(wsOpen); + wss.bindHandlers(handlerMap); + wss.sendEvent('intentPerfStart'); + $log.debug('intentPerf comms started'); + } + + function stop() { + graph.stop(); + wss.sendEvent('intentPerfStop'); + wss.unbindHandlers(handlerMap); + wss.removeOpenListener(openListener); + openListener = null; + graph = null; + $log.debug('intentPerf comms stopped'); + } + + // Cleanup on destroyed scope.. + $scope.$on('$destroy', function () { + $log.log('OvIntentPerfCtrl is saying Buh-Bye!'); + stop(); + }); + + $log.log('OvIntentPerfCtrl has been created'); + + start(); + }]); +}()); |