blob: ee02cae4bbfb9d2d65463a81e163784467f5f4b8 [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 Vachuska95aadff2015-03-26 11:45:41 -070034 function createGraph(h) {
35 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 Vachuska95aadff2015-03-26 11:45:41 -070053 svg = d3.select("#intent-perf-chart").append("p")
54 .append("svg").attr("id", "intent-perf-svg")
55 .append("g").attr("id", "intent-perf-svg-g");
Brian O'Connora468e902015-03-18 16:43:49 -070056
Thomas Vachuska95aadff2015-03-26 11:45:41 -070057 svg.append("defs").append("clipPath").attr("id", "intent-perf-clip")
58 .append("rect");
Brian O'Connora468e902015-03-18 16:43:49 -070059
Thomas Vachuska95aadff2015-03-26 11:45:41 -070060 axis = svg.append("g")
Brian O'Connora468e902015-03-18 16:43:49 -070061 .attr("class", "x axis")
Thomas Vachuska95aadff2015-03-26 11:45:41 -070062 .attr("id", "intent-perf-x");
63
64 svg.append("g").attr("class", "y axis")
65 .attr("id", "intent-perf-yl");
Brian O'Connora468e902015-03-18 16:43:49 -070066
67 svg.append("g")
68 .attr("class", "y axis")
Thomas Vachuska95aadff2015-03-26 11:45:41 -070069 .attr("id", "intent-perf-yr");
Brian O'Connora468e902015-03-18 16:43:49 -070070
Thomas Vachuska95aadff2015-03-26 11:45:41 -070071 resize(dim);
72
73 headers.forEach(function (h, li) {
Thomas Vachuska90c7be22015-03-27 14:12:46 -070074 // Prime the data to match the headers and zero it out.
Thomas Vachuska95aadff2015-03-26 11:45:41 -070075 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()) :
Thomas Vachuska90c7be22015-03-27 14:12:46 -070097 ts.theme() === 'light' ? '#333' : '#eee';
Brian O'Connora468e902015-03-18 16:43:49 -070098 }
99
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700100 function tick() {
101 if (stopped) {
102 return;
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);
Thomas Vachuska90c7be22015-03-27 14:12:46 -0700116 paths[li].transition()
117 .attr("transform", "translate(" + x(now - (n - 1) * duration) + ")");
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700118
119 // pop the old data point off the front
120 d.shift();
121 });
122
123 // slide the x-axis left
124 axis.call(x.axis);
125 }).transition().each("start", tick);
126 }
127
128 function start() {
129 stopped = false;
130 headers.forEach(function (h, li) {
131 theSample[li] = 0;
Brian O'Connora468e902015-03-18 16:43:49 -0700132 });
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700133 tick();
134 }
Brian O'Connora468e902015-03-18 16:43:49 -0700135
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700136 function stop() {
137 stopped = true;
138 }
Brian O'Connora468e902015-03-18 16:43:49 -0700139
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700140 function resize(dim) {
141 margin = {top: 20, right: 90, bottom: 20, left: 70};
142 width = dim.width - margin.right - margin.left;
143 height = 480 - margin.top - margin.bottom;
Brian O'Connora468e902015-03-18 16:43:49 -0700144
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700145 x = d3.time.scale()
146 .domain([now - (n - 2) * duration, now - duration])
147 .range([0, width]);
Brian O'Connora468e902015-03-18 16:43:49 -0700148
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700149 y = d3.scale.linear()
150 .domain([0, 200000])
151 .range([height, 0]);
152
153 d3.select("#intent-perf-svg")
154 .attr("width", width + margin.left + margin.right)
155 .attr("height", height + margin.top + margin.bottom);
156 d3.select("#intent-perf-svg-g")
157 .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
158
159 d3.select("#intent-pef-clip rect").attr("width", width).attr("height", height);
160
161 d3.select("#intent-perf-x")
Brian O'Connora468e902015-03-18 16:43:49 -0700162 .attr("transform", "translate(0," + height + ")")
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700163 .call(x.axis = d3.svg.axis().scale(x).orient("bottom"));
Brian O'Connora468e902015-03-18 16:43:49 -0700164
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700165 d3.select("#intent-perf-yl")
166 .call(d3.svg.axis().scale(y).orient("left"))
167 d3.select("#intent-perf-yr")
168 .attr("transform", "translate(" + width + " ,0)")
169 .call(d3.svg.axis().scale(y).orient("right"))
Brian O'Connora468e902015-03-18 16:43:49 -0700170 }
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700171
172 return {
173 start: start,
174 stop: stop,
175 resize: resize
176 };
Brian O'Connora468e902015-03-18 16:43:49 -0700177 }
178
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700179
180 function wsOpen(host, url) {
181 $log.debug('IntentPerf: web socket open - cluster node:', host, 'URL:', url);
182 // Request batch of initial data from the new server
183 wss.sendEvent('intentPerfStart');
184 }
185
186 function createAndInitGraph(d) {
187 if (!graph) {
188 d.headers.push("total");
189 graph = createGraph(d.headers);
190 }
191 graph.start();
192 }
193
194 function graphResized(dim) {
195 $log.info("Resized: " + dim.width + "x" + dim.height);
196 graph.resize(dim);
197 }
198
199 function recordSample(sample) {
200 var total = 0;
201 sample.data.forEach(function (d, i) {
202 theSample[i] = d;
203 total = total + d;
204 });
205 theSample[sample.data.length] = total;
206 }
207
208 function createHandlerMap() {
209 handlerMap = {
210 intentPerfHeaders: createAndInitGraph,
211 intentPerfSample: recordSample
212 };
213 }
214
Brian O'Connora468e902015-03-18 16:43:49 -0700215 // define the controller
216
217 angular.module('ovIntentPerf', ['onosUtil'])
218 .controller('OvIntentPerfCtrl',
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700219 ['$scope', '$log', 'ToolbarService', 'WebSocketService',
220 'ThemeService', 'FlashService', 'SvgUtilService', 'FnService',
221 'MastService',
Brian O'Connora468e902015-03-18 16:43:49 -0700222
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700223 function ($scope, _$log_, _tbs_, _wss_, _ts_, _flash_, _sus_, _fs_, _mast_) {
224 var self = this;
Brian O'Connora468e902015-03-18 16:43:49 -0700225
226 $log = _$log_;
227 tbs = _tbs_;
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700228 wss = _wss_;
229 ts = _ts_;
Brian O'Connora468e902015-03-18 16:43:49 -0700230 flash = _flash_;
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700231 sus = _sus_;
232 fs = _fs_;
233 mast = _mast_;
Brian O'Connora468e902015-03-18 16:43:49 -0700234
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700235 createHandlerMap();
Brian O'Connora468e902015-03-18 16:43:49 -0700236
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700237 self.notifyResize = function () {
238 graphResized(fs.windowSize(mast.mastHeight()));
239 };
240
241 function start() {
242 openListener = wss.addOpenListener(wsOpen);
243 wss.bindHandlers(handlerMap);
244 wss.sendEvent('intentPerfStart');
245 $log.debug('intentPerf comms started');
246 }
247
248 function stop() {
249 graph.stop();
250 wss.sendEvent('intentPerfStop');
251 wss.unbindHandlers(handlerMap);
252 wss.removeOpenListener(openListener);
253 openListener = null;
254 graph = null;
255 $log.debug('intentPerf comms stopped');
256 }
257
258 // Cleanup on destroyed scope..
Brian O'Connora468e902015-03-18 16:43:49 -0700259 $scope.$on('$destroy', function () {
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700260 $log.log('OvIntentPerfCtrl is saying Buh-Bye!');
261 stop();
Brian O'Connora468e902015-03-18 16:43:49 -0700262 });
263
Thomas Vachuska90c7be22015-03-27 14:12:46 -0700264 $log.log('OvIntentPerfCtrl has been created');
265
Thomas Vachuska95aadff2015-03-26 11:45:41 -0700266 start();
267 }]);
Brian O'Connora468e902015-03-18 16:43:49 -0700268}());