##// END OF EJS Templates
frontend: do not close non-existing websocket connection - don't do anything if window is not focused
ergo -
Show More
@@ -1,694 +1,700 b''
1 1 // # Copyright (C) 2010-2016 RhodeCode GmbH
2 2 // #
3 3 // # This program is free software: you can redistribute it and/or modify
4 4 // # it under the terms of the GNU Affero General Public License, version 3
5 5 // # (only), as published by the Free Software Foundation.
6 6 // #
7 7 // # This program is distributed in the hope that it will be useful,
8 8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 // # GNU General Public License for more details.
11 11 // #
12 12 // # You should have received a copy of the GNU Affero General Public License
13 13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 // #
15 15 // # This program is dual-licensed. If you wish to learn more about the
16 16 // # App Enlight Enterprise Edition, including its added features, Support
17 17 // # services, and proprietary license terms, please see
18 18 // # https://rhodecode.com/licenses/
19 19
20 20 angular.module('appenlight.controllers')
21 21 .controller('IndexDashboardController', IndexDashboardController);
22 22
23 23 IndexDashboardController.$inject = ['$scope', '$location','$cookies', '$interval', 'stateHolder', 'userSelfPropertyResource', 'applicationsPropertyResource', 'AeConfig', 'AeUser'];
24 24
25 25 function IndexDashboardController($scope, $location, $cookies, $interval, stateHolder, userSelfPropertyResource, applicationsPropertyResource, AeConfig, AeUser) {
26 26 var vm = this;
27 27 stateHolder.section = 'dashboard';
28 28 vm.timeOptions = {};
29 29 var allowed = ['1h', '4h', '12h', '24h', '1w', '2w', '1M'];
30 30 _.each(allowed, function (key) {
31 31 if (allowed.indexOf(key) !== -1) {
32 32 vm.timeOptions[key] = AeConfig.timeOptions[key];
33 33 }
34 34 });
35 35 vm.urls = AeConfig.urls;
36 36 vm.applications = AeUser.applications_map;
37 37 vm.show_dashboard = false;
38 38 vm.resource = null;
39 39 vm.graphType = {selected: null};
40 40 vm.timeSpan = vm.timeOptions['1h'];
41 41 vm.trendingReports = [];
42 42 vm.exceptions = 0;
43 43 vm.satisfyingRequests = 0;
44 44 vm.toleratedRequests = 0;
45 45 vm.frustratingRequests = 0;
46 46 vm.uptimeStats = 0;
47 47 vm.apdexStats = [];
48 48 vm.seriesRequestsData = [];
49 49 vm.seriesMetricsData = [];
50 50 vm.seriesSlowData = [];
51 51 vm.slowCalls = [];
52 52 vm.slowURIS = [];
53 53
54 54 vm.reportChartConfig = {
55 55 data: {
56 56 json: [],
57 57 xFormat: '%Y-%m-%dT%H:%M:%S'
58 58 },
59 59 color: {
60 60 pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b']
61 61 },
62 62 axis: {
63 63 x: {
64 64 type: 'timeseries',
65 65 tick: {
66 66 culling: {
67 67 max: 6 // the number of tick texts will be adjusted to less than this value
68 68 },
69 69 format: '%Y-%m-%d %H:%M'
70 70 }
71 71 },
72 72 y: {
73 73 tick: {
74 74 count: 5,
75 75 format: d3.format('.2s')
76 76 }
77 77 }
78 78 },
79 79 subchart: {
80 80 show: true,
81 81 size: {
82 82 height: 20
83 83 }
84 84 },
85 85 size: {
86 86 height: 250
87 87 },
88 88 zoom: {
89 89 rescale: true
90 90 },
91 91 grid: {
92 92 x: {
93 93 show: true
94 94 },
95 95 y: {
96 96 show: true
97 97 }
98 98 },
99 99 tooltip: {
100 100 format: {
101 101 title: function (d) {
102 102 return '' + d;
103 103 },
104 104 value: function (v) {
105 105 return v
106 106 }
107 107 }
108 108 }
109 109 };
110 110 vm.reportChartData = {};
111 111
112 112 vm.reportSlowChartConfig = {
113 113 data: {
114 114 json: [],
115 115 xFormat: '%Y-%m-%dT%H:%M:%S'
116 116 },
117 117 color: {
118 118 pattern: ['#6baed6', '#e6550d', '#74c476', '#fdd0a2', '#8c564b']
119 119 },
120 120 axis: {
121 121 x: {
122 122 type: 'timeseries',
123 123 tick: {
124 124 culling: {
125 125 max: 6 // the number of tick texts will be adjusted to less than this value
126 126 },
127 127 format: '%Y-%m-%d %H:%M'
128 128 }
129 129 },
130 130 y: {
131 131 tick: {
132 132 count: 5,
133 133 format: d3.format('.2s')
134 134 }
135 135 }
136 136 },
137 137 subchart: {
138 138 show: true,
139 139 size: {
140 140 height: 20
141 141 }
142 142 },
143 143 size: {
144 144 height: 250
145 145 },
146 146 zoom: {
147 147 rescale: true
148 148 },
149 149 grid: {
150 150 x: {
151 151 show: true
152 152 },
153 153 y: {
154 154 show: true
155 155 }
156 156 },
157 157 tooltip: {
158 158 format: {
159 159 title: function (d) {
160 160 return '' + d;
161 161 },
162 162 value: function (v) {
163 163 return v
164 164 }
165 165 }
166 166 }
167 167 };
168 168 vm.reportSlowChartData = {};
169 169
170 170 vm.metricsChartConfig = {
171 171 data: {
172 172 json: [],
173 173 xFormat: '%Y-%m-%dT%H:%M:%S',
174 174 keys: {
175 175 x: 'x',
176 176 value: ["main", "sql", "nosql", "tmpl", "remote", "custom"]
177 177 },
178 178 names: {
179 179 main: 'View/Application logic',
180 180 sql: 'Relational database queries',
181 181 nosql: 'NoSql datastore calls',
182 182 tmpl: 'Template rendering',
183 183 custom: 'Custom timed calls',
184 184 remote: 'Requests to remote resources'
185 185 },
186 186 type: 'area',
187 187 groups: [["main", "sql", "nosql", "remote", "custom", "tmpl"]],
188 188 order: null
189 189 },
190 190 color: {
191 191 pattern: ['#6baed6', '#c7e9c0', '#fd8d3c', '#d6616b', '#ffcc00', '#c6dbef']
192 192 },
193 193 axis: {
194 194 x: {
195 195 type: 'timeseries',
196 196 tick: {
197 197 culling: {
198 198 max: 6 // the number of tick texts will be adjusted to less than this value
199 199 },
200 200 format: '%Y-%m-%d %H:%M'
201 201 }
202 202 },
203 203 y: {
204 204 tick: {
205 205 count: 5,
206 206 format: d3.format('.2f')
207 207 }
208 208 }
209 209 },
210 210 point: {
211 211 show: false
212 212 },
213 213 subchart: {
214 214 show: true,
215 215 size: {
216 216 height: 20
217 217 }
218 218 },
219 219 size: {
220 220 height: 350
221 221 },
222 222 zoom: {
223 223 rescale: true
224 224 },
225 225 grid: {
226 226 x: {
227 227 show: true
228 228 },
229 229 y: {
230 230 show: true
231 231 }
232 232 },
233 233 tooltip: {
234 234 format: {
235 235 title: function (d) {
236 236 return '' + d;
237 237 },
238 238 value: function (v) {
239 239 return v
240 240 }
241 241 }
242 242 }
243 243 };
244 244 vm.metricsChartData = {};
245 245
246 246 vm.responseChartConfig = {
247 247 data: {
248 248 json: [],
249 249 xFormat: '%Y-%m-%dT%H:%M:%S'
250 250 },
251 251 color: {
252 252 pattern: ['#d6616b', '#6baed6', '#fd8d3c']
253 253 },
254 254 axis: {
255 255 x: {
256 256 type: 'timeseries',
257 257 tick: {
258 258 culling: {
259 259 max: 6 // the number of tick texts will be adjusted to less than this value
260 260 },
261 261 format: '%Y-%m-%d %H:%M'
262 262 }
263 263 },
264 264 y: {
265 265 tick: {
266 266 count: 5,
267 267 format: d3.format('.2f')
268 268 }
269 269 }
270 270 },
271 271 point: {
272 272 show: false
273 273 },
274 274 subchart: {
275 275 show: true,
276 276 size: {
277 277 height: 20
278 278 }
279 279 },
280 280 size: {
281 281 height: 350
282 282 },
283 283 zoom: {
284 284 rescale: true
285 285 },
286 286 grid: {
287 287 x: {
288 288 show: true
289 289 },
290 290 y: {
291 291 show: true
292 292 }
293 293 },
294 294 tooltip: {
295 295 format: {
296 296 title: function (d) {
297 297 return '' + d;
298 298 },
299 299 value: function (v) {
300 300 return v
301 301 }
302 302 }
303 303 }
304 304 };
305 305 vm.responseChartData = {};
306 306
307 307 vm.requestsChartConfig = {
308 308 data: {
309 309 json: [],
310 310 xFormat: '%Y-%m-%dT%H:%M:%S'
311 311 },
312 312 color: {
313 313 pattern: ['#d6616b', '#6baed6', '#fd8d3c']
314 314 },
315 315 axis: {
316 316 x: {
317 317 type: 'timeseries',
318 318 tick: {
319 319 culling: {
320 320 max: 6 // the number of tick texts will be adjusted to less than this value
321 321 },
322 322 format: '%Y-%m-%d %H:%M'
323 323 }
324 324 },
325 325 y: {
326 326 tick: {
327 327 count: 5,
328 328 format: d3.format('.2f')
329 329 }
330 330 }
331 331 },
332 332 point: {
333 333 show: false
334 334 },
335 335 subchart: {
336 336 show: true,
337 337 size: {
338 338 height: 20
339 339 }
340 340 },
341 341 size: {
342 342 height: 350
343 343 },
344 344 zoom: {
345 345 rescale: true
346 346 },
347 347 grid: {
348 348 x: {
349 349 show: true
350 350 },
351 351 y: {
352 352 show: true
353 353 }
354 354 },
355 355 tooltip: {
356 356 format: {
357 357 title: function (d) {
358 358 return '' + d;
359 359 },
360 360 value: function (v) {
361 361 return v
362 362 }
363 363 }
364 364 }
365 365 };
366 366 vm.requestsChartData = {};
367 367
368 368 vm.loading = {
369 369 'apdex': true,
370 370 'reports': true,
371 371 'graphs': true,
372 372 'slowCalls': true,
373 373 'slowURIS': true,
374 374 'requestsBreakdown': true,
375 375 'series': true
376 376 };
377 377 vm.stream = {paused: false, filtered: false, messages: [], reports: []};
378 378 vm.websocket = null;
379 379 userSelfPropertyResource.get({key: 'websocket'}, function (data) {
380 380 console.log(data);
381 381 console.log(AeConfig.ws_url + '/ws?conn_id=' + data.conn_id);
382 382 vm.websocket = new ReconnectingWebSocket(AeConfig.ws_url + '/ws?conn_id=' + data.conn_id);
383 383 vm.websocket.onopen = function (event) {
384 384 console.log('open');
385 385 };
386 386 vm.websocket.onmessage = function (event) {
387 387 var data = JSON.parse(event.data);
388 388 console.log('message');
389 389 $scope.$apply(function (scope) {
390 390 _.each(data, function (message) {
391 391 if (message.type === 'message'){
392 392 ws_report = message.message.report;
393 393 if (ws_report.http_status != 500) {
394 394 return
395 395 }
396 396 if (vm.stream.paused == true) {
397 397 return
398 398 }
399 399 if (vm.stream.filtered && ws_report.resource_id != vm.resource) {
400 400 return
401 401 }
402 402 var should_insert = true;
403 403 _.each(vm.stream.reports, function (report) {
404 404 if (report.report_id == ws_report.report_id) {
405 405 report.occurences = ws_report.occurences;
406 406 should_insert = false;
407 407 }
408 408 });
409 409 if (should_insert) {
410 410 if (vm.stream.reports.length > 7) {
411 411 vm.stream.reports.pop();
412 412 }
413 413 vm.stream.reports.unshift(ws_report);
414 414 }
415 415 }
416 416 });
417 417 });
418 418 };
419 419 vm.websocket.onclose = function (event) {
420 420 console.log('closed');
421 421 };
422 422
423 423 vm.websocket.onerror = function (event) {
424 424 console.log('error');
425 425 };
426 426
427 427 });
428 428
429 429 vm.determineStartState = function () {
430 430 if (AeUser.applications.length) {
431 431 vm.resource = Number($location.search().resource);
432 432
433 433 if (!vm.resource){
434 434 var cookieResource = $cookies.getObject('resource');
435 435 console.log('cookieResource', cookieResource);
436 436
437 437 if (cookieResource) {
438 438 vm.resource = cookieResource;
439 439 }
440 440 else{
441 441 vm.resource = AeUser.applications[0].resource_id;
442 442 }
443 443 }
444 444 }
445 445
446 446 var timespan = $location.search().timespan;
447 447
448 448 if(_.has(vm.timeOptions, timespan)){
449 449 vm.timeSpan = vm.timeOptions[timespan];
450 450 }
451 451 else{
452 452 vm.timeSpan = vm.timeOptions['1h'];
453 453 }
454 454
455 455 var graphType = $location.search().graphtype;
456 456 if(!graphType){
457 457 vm.graphType = {selected: 'metrics_graphs'};
458 458 }
459 459 else{
460 460 vm.graphType = {selected: graphType};
461 461 }
462 462 vm.updateSearchParams();
463 463 };
464 464
465 465 vm.updateSearchParams = function () {
466 466 $location.search('resource', vm.resource);
467 467 $location.search('timespan', vm.timeSpan.key);
468 468 $location.search('graphtype', vm.graphType.selected);
469 469 stateHolder.resource = vm.resource;
470 470 if (vm.resource){
471 471 $cookies.putObject('resource', vm.resource,
472 472 {expires:new Date(3000, 1, 1)});
473 473 }
474 474 };
475 475
476 476 vm.refreshData = function () {
477 477 vm.fetchApdexStats();
478 478 vm.fetchTrendingReports();
479 479 vm.fetchMetrics();
480 480 vm.fetchRequestsBreakdown();
481 481 vm.fetchSlowCalls();
482 482 }
483 483
484 484 vm.changedTimeSpan = function(){
485 485 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
486 486 vm.refreshData();
487 487 }
488 488
489 489 var intervalId = $interval(function () {
490 490 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
491 // don't do anything if window is unfocused
492 if(document.hidden === true){
493 return ;
494 }
491 495 vm.refreshData();
492 496 }
493 497 }, 60000);
494 498
495 499 $scope.$on('$destroy',function(){
496 500 $interval.cancel(intervalId);
497 vm.websocket.close();
501 if (vm.websocket && vm.websocket.readyState == 1){
502 vm.websocket.close();
503 }
498 504 });
499 505
500 506
501 507 vm.fetchApdexStats = function () {
502 508 vm.loading.apdex = true;
503 509 vm.apdexStats = applicationsPropertyResource.query({
504 510 'key': 'apdex_stats',
505 511 'resourceId': vm.resource,
506 512 "start_date": timeSpanToStartDate(vm.timeSpan.key)
507 513 },
508 514 function (data) {
509 515 vm.loading.apdex = false;
510 516
511 517 vm.exceptions = _.reduce(data, function (memo, row) {
512 518 return memo + row.errors;
513 519 }, 0);
514 520 vm.satisfyingRequests = _.reduce(data, function (memo, row) {
515 521 return memo + row.satisfying_requests;
516 522 }, 0);
517 523 vm.toleratedRequests = _.reduce(data, function (memo, row) {
518 524 return memo + row.tolerated_requests;
519 525 }, 0);
520 526 vm.frustratingRequests = _.reduce(data, function (memo, row) {
521 527 return memo + row.frustrating_requests;
522 528 }, 0);
523 529 if (data.length) {
524 530 vm.uptimeStats = data[0].uptime;
525 531 }
526 532
527 533 },
528 534 function () {
529 535 vm.loading.apdex = false;
530 536 }
531 537 );
532 538 }
533 539
534 540 vm.fetchMetrics = function () {
535 541 vm.loading.series = true;
536 542 applicationsPropertyResource.query({
537 543 'resourceId': vm.resource,
538 544 'key': vm.graphType.selected,
539 545 "start_date": timeSpanToStartDate(vm.timeSpan.key)
540 546 }, function (data) {
541 547 if (vm.graphType.selected == 'metrics_graphs') {
542 548 vm.metricsChartData = {
543 549 json: data,
544 550 xFormat: '%Y-%m-%dT%H:%M:%S',
545 551 keys: {
546 552 x: 'x',
547 553 value: ["main", "sql", "nosql", "tmpl", "remote", "custom"]
548 554 },
549 555 names: {
550 556 main: 'View/Application logic',
551 557 sql: 'Relational database queries',
552 558 nosql: 'NoSql datastore calls',
553 559 tmpl: 'Template rendering',
554 560 custom: 'Custom timed calls',
555 561 remote: 'Requests to remote resources'
556 562 },
557 563 type: 'area',
558 564 groups: [["main", "sql", "nosql", "remote", "custom", "tmpl"]],
559 565 order: null
560 566 };
561 567 }
562 568 else if (vm.graphType.selected == 'report_graphs') {
563 569 vm.reportChartData = {
564 570 json: data,
565 571 xFormat: '%Y-%m-%dT%H:%M:%S',
566 572 keys: {
567 573 x: 'x',
568 574 value: ["not_found", "report"]
569 575 },
570 576 names: {
571 577 report: 'Errors',
572 578 not_found: '404\'s requests'
573 579 },
574 580 type: 'bar'
575 581 };
576 582 }
577 583 else if (vm.graphType.selected == 'slow_report_graphs') {
578 584 vm.reportSlowChartData = {
579 585 json: data,
580 586 xFormat: '%Y-%m-%dT%H:%M:%S',
581 587 keys: {
582 588 x: 'x',
583 589 value: ["slow_report"]
584 590 },
585 591 names: {
586 592 slow_report: 'Slow reports'
587 593 },
588 594 type: 'bar'
589 595 };
590 596 }
591 597 else if (vm.graphType.selected == 'response_graphs') {
592 598 vm.responseChartData = {
593 599 json: data,
594 600 xFormat: '%Y-%m-%dT%H:%M:%S',
595 601 keys: {
596 602 x: 'x',
597 603 value: ["today", "days_ago_2", "days_ago_7"]
598 604 },
599 605 names: {
600 606 today: 'Today',
601 607 "days_ago_2": '2 days ago',
602 608 "days_ago_7": '7 days ago'
603 609 }
604 610 };
605 611 }
606 612 else if (vm.graphType.selected == 'requests_graphs') {
607 613 vm.requestsChartData = {
608 614 json: data,
609 615 xFormat: '%Y-%m-%dT%H:%M:%S',
610 616 keys: {
611 617 x: 'x',
612 618 value: ["requests"]
613 619 },
614 620 names: {
615 621 requests: 'Requests/s'
616 622 }
617 623 };
618 624 }
619 625 vm.loading.series = false;
620 626 }, function(){
621 627 vm.loading.series = false;
622 628 });
623 629 }
624 630
625 631 vm.fetchSlowCalls = function () {
626 632 vm.loading.slowCalls = true;
627 633 applicationsPropertyResource.query({
628 634 'resourceId': vm.resource,
629 635 "start_date": timeSpanToStartDate(vm.timeSpan.key),
630 636 'key': 'slow_calls'
631 637 }, function (data) {
632 638 vm.slowCalls = data;
633 639 vm.loading.slowCalls = false;
634 640 }, function () {
635 641 vm.loading.slowCalls = false;
636 642 });
637 643 }
638 644
639 645 vm.fetchRequestsBreakdown = function () {
640 646 vm.loading.requestsBreakdown = true;
641 647 applicationsPropertyResource.query({
642 648 'resourceId': vm.resource,
643 649 "start_date": timeSpanToStartDate(vm.timeSpan.key),
644 650 'key': 'requests_breakdown'
645 651 }, function (data) {
646 652 vm.requestsBreakdown = data;
647 653 vm.loading.requestsBreakdown = false;
648 654 }, function () {
649 655 vm.loading.requestsBreakdown = false;
650 656 });
651 657 }
652 658
653 659 vm.fetchTrendingReports = function () {
654 660
655 661 if (vm.graphType.selected == 'slow_report_graphs') {
656 662 var report_type = 'slow';
657 663 }
658 664 else {
659 665 var report_type = 'error';
660 666 }
661 667
662 668 vm.loading.reports = true;
663 669 vm.trendingReports = applicationsPropertyResource.query({
664 670 'key': 'trending_reports',
665 671 'resourceId': vm.resource,
666 672 "start_date": timeSpanToStartDate(vm.timeSpan.key),
667 673 "report_type": report_type
668 674 },
669 675 function () {
670 676 vm.loading.reports = false;
671 677 },
672 678 function () {
673 679 vm.loading.reports = false;
674 680 }
675 681 )
676 682 ;
677 683 }
678 684
679 685 if (AeUser.applications.length){
680 686 vm.show_dashboard = true;
681 687 vm.determineStartState();
682 688 vm.refreshData();
683 689 }
684 690
685 691 $scope.$on('$locationChangeSuccess', function () {
686 692 console.log('$locationChangeSuccess IndexDashboardController');
687 693 if (vm.loading.series === false) {
688 694 vm.determineStartState();
689 695 vm.refreshData();
690 696 }
691 697 });
692 698
693 699
694 700 }
General Comments 0
You need to be logged in to leave comments. Login now