##// END OF EJS Templates
channelstream: separate element and basic pubsub
ergo -
Show More
@@ -0,0 +1,57 b''
1 // # Copyright (C) 2010-2016 RhodeCode GmbH
2 // #
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
6 // #
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # AppEnlight Enterprise Edition, including its added features, Support
17 // # services, and proprietary license terms, please see
18 // # https://rhodecode.com/licenses/
19
20 angular.module('appenlight.components.channelstream', [])
21 .component('channelstream', {
22 controller: ChannelstreamController,
23 bindings: {
24 config: '='
25 }
26 });
27
28 ChannelstreamController.$inject = ['$rootScope','userSelfPropertyResource'];
29
30 function ChannelstreamController($rootScope, userSelfPropertyResource){
31 userSelfPropertyResource.get({key: 'websocket'}, function (data) {
32 stateHolder.websocket = new ReconnectingWebSocket(this.config.ws_url + '/ws?conn_id=' + data.conn_id);
33 stateHolder.websocket.onopen = function (event) {
34 console.log('open');
35 };
36 stateHolder.websocket.onmessage = function (event) {
37 var data = JSON.parse(event.data);
38 _.each(data, function (message) {
39 console.log('channelstream-message', message);
40 if(typeof message.message.topic !== 'undefined'){
41 $rootScope.$broadcast(
42 'channelstream-message.'+message.message.topic, message);
43 }
44 else{
45 $rootScope.$broadcast('channelstream-message', message);
46 }
47 });
48 };
49 stateHolder.websocket.onclose = function (event) {
50 console.log('closed');
51 };
52
53 stateHolder.websocket.onerror = function (event) {
54 console.log('error');
55 };
56 });
57 }
@@ -104,7 +104,7 b' class DateTimeEncoder(json.JSONEncoder):'
104 104 return json.JSONEncoder.default(self, obj)
105 105
106 106
107 def cometd_request(secret, endpoint, payload, throw_exceptions=False,
107 def channelstream_request(secret, endpoint, payload, throw_exceptions=False,
108 108 servers=None):
109 109 responses = []
110 110 if not servers:
@@ -32,7 +32,7 b' from appenlight.models import Base, Datastores'
32 32 from appenlight.lib.utils.date_utils import convert_date
33 33 from appenlight.lib.utils import convert_es_type
34 34 from appenlight.models.slow_call import SlowCall
35 from appenlight.lib.utils import cometd_request
35 from appenlight.lib.utils import channelstream_request
36 36 from appenlight.lib.enums import ReportType, Language
37 37 from pyramid.threadlocal import get_current_registry, get_current_request
38 38 from sqlalchemy.dialects.postgresql import JSON
@@ -410,7 +410,7 b' class Report(Base, BaseModel):'
410 410 Sends notification to websocket channel
411 411 """
412 412 settings = get_current_registry().settings
413 log.info('notify cometd')
413 log.info('notify channelstream')
414 414 if self.report_type != ReportType.error:
415 415 return
416 416 payload = {
@@ -418,7 +418,7 b' class Report(Base, BaseModel):'
418 418 "user": '__system__',
419 419 "channel": 'app_%s' % self.resource_id,
420 420 'message': {
421 'type': 'report',
421 'topic': 'front_dashboard.new_topic',
422 422 'report': {
423 423 'group': {
424 424 'priority': report_group.priority,
@@ -441,8 +441,7 b' class Report(Base, BaseModel):'
441 441 }
442 442
443 443 }
444
445 cometd_request(settings['cometd.secret'], '/message', [payload],
444 channelstream_request(settings['cometd.secret'], '/message', [payload],
446 445 servers=[settings['cometd_servers']])
447 446
448 447 def es_doc(self):
@@ -2671,7 +2671,12 b" angular.module('appenlight.base', ["
2671 2671
2672 2672 angular.module('appenlight.filters', []);
2673 2673 angular.module('appenlight.templates', []);
2674 angular.module('appenlight.controllers', ['appenlight.base']);
2674 angular.module('appenlight.controllers', [
2675 'appenlight.base'
2676 ]);
2677 angular.module('appenlight.components', [
2678 'appenlight.components.channelstream'
2679 ]);
2675 2680 angular.module('appenlight.directives', [
2676 2681 'appenlight.directives.appVersion',
2677 2682 'appenlight.directives.c3chart',
@@ -2714,6 +2719,7 b" var app = angular.module('appenlight', ["
2714 2719 'appenlight.services',
2715 2720 'appenlight.directives',
2716 2721 'appenlight.controllers',
2722 'appenlight.components',
2717 2723 'appenlight.plugins'
2718 2724 ]);
2719 2725
@@ -2731,7 +2737,6 b' function kickstartAE(initialUserData) {'
2731 2737 return response;
2732 2738 },
2733 2739 'responseError': function (rejection) {
2734
2735 2740 if (rejection.status > 299 && rejection.status !== 422) {
2736 2741 stateHolder.flashMessages.extend([{
2737 2742 msg: 'Response status code: ' + rejection.status + ', "' + rejection.statusText + '", url: ' + rejection.config.url,
@@ -7017,6 +7022,64 b' function kickstartAE(initialUserData) {'
7017 7022 // # services, and proprietary license terms, please see
7018 7023 // # https://rhodecode.com/licenses/
7019 7024
7025 angular.module('appenlight.components.channelstream', [])
7026 .component('channelstream', {
7027 controller: ChannelstreamController,
7028 bindings: {
7029 config: '='
7030 }
7031 });
7032
7033 ChannelstreamController.$inject = ['$rootScope','userSelfPropertyResource'];
7034
7035 function ChannelstreamController($rootScope, userSelfPropertyResource){
7036 userSelfPropertyResource.get({key: 'websocket'}, function (data) {
7037 stateHolder.websocket = new ReconnectingWebSocket(this.config.ws_url + '/ws?conn_id=' + data.conn_id);
7038 stateHolder.websocket.onopen = function (event) {
7039
7040 };
7041 stateHolder.websocket.onmessage = function (event) {
7042 var data = JSON.parse(event.data);
7043 _.each(data, function (message) {
7044
7045 if(typeof message.message.topic !== 'undefined'){
7046 $rootScope.$broadcast(
7047 'channelstream-message.'+message.message.topic, message);
7048 }
7049 else{
7050 $rootScope.$broadcast('channelstream-message', message);
7051 }
7052 });
7053 };
7054 stateHolder.websocket.onclose = function (event) {
7055
7056 };
7057
7058 stateHolder.websocket.onerror = function (event) {
7059
7060 };
7061 });
7062 }
7063
7064 ;// # Copyright (C) 2010-2016 RhodeCode GmbH
7065 // #
7066 // # This program is free software: you can redistribute it and/or modify
7067 // # it under the terms of the GNU Affero General Public License, version 3
7068 // # (only), as published by the Free Software Foundation.
7069 // #
7070 // # This program is distributed in the hope that it will be useful,
7071 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
7072 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7073 // # GNU General Public License for more details.
7074 // #
7075 // # You should have received a copy of the GNU Affero General Public License
7076 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
7077 // #
7078 // # This program is dual-licensed. If you wish to learn more about the
7079 // # AppEnlight Enterprise Edition, including its added features, Support
7080 // # services, and proprietary license terms, please see
7081 // # https://rhodecode.com/licenses/
7082
7020 7083 var aeconfig = angular.module('appenlight.config', []);
7021 7084 aeconfig.factory('AeConfig', function () {
7022 7085 var obj = {};
@@ -8478,55 +8541,31 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
8478 8541 'series': true
8479 8542 };
8480 8543 vm.stream = {paused: false, filtered: false, messages: [], reports: []};
8481 vm.websocket = null;
8482 userSelfPropertyResource.get({key: 'websocket'}, function (data) {
8483
8484
8485 vm.websocket = new ReconnectingWebSocket(AeConfig.ws_url + '/ws?conn_id=' + data.conn_id);
8486 vm.websocket.onopen = function (event) {
8487
8488 };
8489 vm.websocket.onmessage = function (event) {
8490 var data = JSON.parse(event.data);
8491
8492 $scope.$apply(function (scope) {
8493 _.each(data, function (message) {
8494 if (message.type === 'message'){
8495 ws_report = message.message.report;
8496 if (ws_report.http_status != 500) {
8497 return
8498 }
8499 if (vm.stream.paused == true) {
8500 return
8501 }
8502 if (vm.stream.filtered && ws_report.resource_id != vm.resource) {
8503 return
8504 }
8505 var should_insert = true;
8506 _.each(vm.stream.reports, function (report) {
8507 if (report.report_id == ws_report.report_id) {
8508 report.occurences = ws_report.occurences;
8509 should_insert = false;
8510 }
8511 });
8512 if (should_insert) {
8513 if (vm.stream.reports.length > 7) {
8514 vm.stream.reports.pop();
8515 }
8516 vm.stream.reports.unshift(ws_report);
8517 }
8518 }
8519 });
8520 });
8521 };
8522 vm.websocket.onclose = function (event) {
8523
8524 };
8525
8526 vm.websocket.onerror = function (event) {
8527
8528 };
8529 8544
8545 $scope.$on('channelstream-message.front_dashboard.new_topic', function(event, message){
8546 var ws_report = message.message.report;
8547 if (ws_report.http_status != 500) {
8548 return
8549 }
8550 if (vm.stream.paused == true) {
8551 return
8552 }
8553 if (vm.stream.filtered && ws_report.resource_id != vm.resource) {
8554 return
8555 }
8556 var should_insert = true;
8557 _.each(vm.stream.reports, function (report) {
8558 if (report.report_id == ws_report.report_id) {
8559 report.occurences = ws_report.occurences;
8560 should_insert = false;
8561 }
8562 });
8563 if (should_insert) {
8564 if (vm.stream.reports.length > 7) {
8565 vm.stream.reports.pop();
8566 }
8567 vm.stream.reports.unshift(ws_report);
8568 }
8530 8569 });
8531 8570
8532 8571 vm.determineStartState = function () {
@@ -8582,12 +8621,12 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
8582 8621 vm.fetchMetrics();
8583 8622 vm.fetchRequestsBreakdown();
8584 8623 vm.fetchSlowCalls();
8585 }
8624 };
8586 8625
8587 8626 vm.changedTimeSpan = function(){
8588 8627 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
8589 8628 vm.refreshData();
8590 }
8629 };
8591 8630
8592 8631 var intervalId = $interval(function () {
8593 8632 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
@@ -8599,14 +8638,6 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
8599 8638 }
8600 8639 }, 60000);
8601 8640
8602 $scope.$on('$destroy',function(){
8603 $interval.cancel(intervalId);
8604 if (vm.websocket && vm.websocket.readyState == 1){
8605 vm.websocket.close();
8606 }
8607 });
8608
8609
8610 8641 vm.fetchApdexStats = function () {
8611 8642 vm.loading.apdex = true;
8612 8643 vm.apdexStats = applicationsPropertyResource.query({
@@ -12706,7 +12737,8 b" angular.module('appenlight.services.resources').factory('resourcesPropertyResour"
12706 12737 // # services, and proprietary license terms, please see
12707 12738 // # https://rhodecode.com/licenses/
12708 12739
12709 angular.module('appenlight.services.stateHolder', []).factory('stateHolder', ['$timeout', 'AeConfig', function ($timeout, AeConfig) {
12740 angular.module('appenlight.services.stateHolder', []).factory('stateHolder',
12741 ['$timeout', '$rootScope', 'AeConfig', function ($timeout, $rootScope, AeConfig) {
12710 12742
12711 12743 var AeUser = {"user_name": null, "id": null};
12712 12744 AeUser.update = function (jsonData) {
@@ -1,5 +1,6 b''
1 1 <!-- Fixed navbar -->
2 2 <div id="top-navbar" class="navbar navbar-default navbar-fixed-top" role="navigation" data-ng-controller="HeaderCtrl as header">
3 {% raw %}<channelstream config="AeConfig"></channelstream>{% endraw %}
3 4 <div class="pattern">
4 5 <div class="container">
5 6 <div class="navbar-header pull-left">
@@ -37,7 +37,7 b' from ziggurat_foundations.models.services.external_identity import \\'
37 37
38 38 from appenlight.lib import generate_random_string
39 39 from appenlight.lib.social import handle_social_data
40 from appenlight.lib.utils import cometd_request, add_cors_headers, \
40 from appenlight.lib.utils import channelstream_request, add_cors_headers, \
41 41 permission_tuple_to_dict
42 42 from appenlight.models import DBSession
43 43 from appenlight.models.alert_channels.email import EmailAlertChannel
@@ -259,7 +259,7 b' def users_websocket(request):'
259 259 "channels": channels
260 260 }
261 261 settings = request.registry.settings
262 response = cometd_request(
262 response = channelstream_request(
263 263 settings['cometd.secret'], '/connect', payload,
264 264 servers=[request.registry.settings['cometd_servers']],
265 265 throw_exceptions=True)
@@ -36,7 +36,12 b" angular.module('appenlight.base', ["
36 36
37 37 angular.module('appenlight.filters', []);
38 38 angular.module('appenlight.templates', []);
39 angular.module('appenlight.controllers', ['appenlight.base']);
39 angular.module('appenlight.controllers', [
40 'appenlight.base'
41 ]);
42 angular.module('appenlight.components', [
43 'appenlight.components.channelstream'
44 ]);
40 45 angular.module('appenlight.directives', [
41 46 'appenlight.directives.appVersion',
42 47 'appenlight.directives.c3chart',
@@ -79,6 +84,7 b" var app = angular.module('appenlight', ["
79 84 'appenlight.services',
80 85 'appenlight.directives',
81 86 'appenlight.controllers',
87 'appenlight.components',
82 88 'appenlight.plugins'
83 89 ]);
84 90
@@ -96,7 +102,6 b' function kickstartAE(initialUserData) {'
96 102 return response;
97 103 },
98 104 'responseError': function (rejection) {
99 console.log(rejection);
100 105 if (rejection.status > 299 && rejection.status !== 422) {
101 106 stateHolder.flashMessages.extend([{
102 107 msg: 'Response status code: ' + rejection.status + ', "' + rejection.statusText + '", url: ' + rejection.config.url,
@@ -375,55 +375,31 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
375 375 'series': true
376 376 };
377 377 vm.stream = {paused: false, filtered: false, messages: [], reports: []};
378 vm.websocket = null;
379 userSelfPropertyResource.get({key: 'websocket'}, function (data) {
380 console.log(data);
381 console.log(AeConfig.ws_url + '/ws?conn_id=' + data.conn_id);
382 vm.websocket = new ReconnectingWebSocket(AeConfig.ws_url + '/ws?conn_id=' + data.conn_id);
383 vm.websocket.onopen = function (event) {
384 console.log('open');
385 };
386 vm.websocket.onmessage = function (event) {
387 var data = JSON.parse(event.data);
388 console.log('message');
389 $scope.$apply(function (scope) {
390 _.each(data, function (message) {
391 if (message.type === 'message'){
392 ws_report = message.message.report;
393 if (ws_report.http_status != 500) {
394 return
395 }
396 if (vm.stream.paused == true) {
397 return
398 }
399 if (vm.stream.filtered && ws_report.resource_id != vm.resource) {
400 return
401 }
402 var should_insert = true;
403 _.each(vm.stream.reports, function (report) {
404 if (report.report_id == ws_report.report_id) {
405 report.occurences = ws_report.occurences;
406 should_insert = false;
407 }
408 });
409 if (should_insert) {
410 if (vm.stream.reports.length > 7) {
411 vm.stream.reports.pop();
412 }
413 vm.stream.reports.unshift(ws_report);
414 }
415 }
416 });
417 });
418 };
419 vm.websocket.onclose = function (event) {
420 console.log('closed');
421 };
422
423 vm.websocket.onerror = function (event) {
424 console.log('error');
425 };
426 378
379 $scope.$on('channelstream-message.front_dashboard.new_topic', function(event, message){
380 var ws_report = message.message.report;
381 if (ws_report.http_status != 500) {
382 return
383 }
384 if (vm.stream.paused == true) {
385 return
386 }
387 if (vm.stream.filtered && ws_report.resource_id != vm.resource) {
388 return
389 }
390 var should_insert = true;
391 _.each(vm.stream.reports, function (report) {
392 if (report.report_id == ws_report.report_id) {
393 report.occurences = ws_report.occurences;
394 should_insert = false;
395 }
396 });
397 if (should_insert) {
398 if (vm.stream.reports.length > 7) {
399 vm.stream.reports.pop();
400 }
401 vm.stream.reports.unshift(ws_report);
402 }
427 403 });
428 404
429 405 vm.determineStartState = function () {
@@ -479,12 +455,12 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
479 455 vm.fetchMetrics();
480 456 vm.fetchRequestsBreakdown();
481 457 vm.fetchSlowCalls();
482 }
458 };
483 459
484 460 vm.changedTimeSpan = function(){
485 461 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
486 462 vm.refreshData();
487 }
463 };
488 464
489 465 var intervalId = $interval(function () {
490 466 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
@@ -496,14 +472,6 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
496 472 }
497 473 }, 60000);
498 474
499 $scope.$on('$destroy',function(){
500 $interval.cancel(intervalId);
501 if (vm.websocket && vm.websocket.readyState == 1){
502 vm.websocket.close();
503 }
504 });
505
506
507 475 vm.fetchApdexStats = function () {
508 476 vm.loading.apdex = true;
509 477 vm.apdexStats = applicationsPropertyResource.query({
@@ -17,7 +17,8 b''
17 17 // # services, and proprietary license terms, please see
18 18 // # https://rhodecode.com/licenses/
19 19
20 angular.module('appenlight.services.stateHolder', []).factory('stateHolder', ['$timeout', 'AeConfig', function ($timeout, AeConfig) {
20 angular.module('appenlight.services.stateHolder', []).factory('stateHolder',
21 ['$timeout', 'AeConfig', function ($timeout, AeConfig) {
21 22
22 23 var AeUser = {"user_name": null, "id": null};
23 24 AeUser.update = function (jsonData) {
General Comments 0
You need to be logged in to leave comments. Login now