##// 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 return json.JSONEncoder.default(self, obj)
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 servers=None):
108 servers=None):
109 responses = []
109 responses = []
110 if not servers:
110 if not servers:
@@ -32,7 +32,7 b' from appenlight.models import Base, Datastores'
32 from appenlight.lib.utils.date_utils import convert_date
32 from appenlight.lib.utils.date_utils import convert_date
33 from appenlight.lib.utils import convert_es_type
33 from appenlight.lib.utils import convert_es_type
34 from appenlight.models.slow_call import SlowCall
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 from appenlight.lib.enums import ReportType, Language
36 from appenlight.lib.enums import ReportType, Language
37 from pyramid.threadlocal import get_current_registry, get_current_request
37 from pyramid.threadlocal import get_current_registry, get_current_request
38 from sqlalchemy.dialects.postgresql import JSON
38 from sqlalchemy.dialects.postgresql import JSON
@@ -410,7 +410,7 b' class Report(Base, BaseModel):'
410 Sends notification to websocket channel
410 Sends notification to websocket channel
411 """
411 """
412 settings = get_current_registry().settings
412 settings = get_current_registry().settings
413 log.info('notify cometd')
413 log.info('notify channelstream')
414 if self.report_type != ReportType.error:
414 if self.report_type != ReportType.error:
415 return
415 return
416 payload = {
416 payload = {
@@ -418,7 +418,7 b' class Report(Base, BaseModel):'
418 "user": '__system__',
418 "user": '__system__',
419 "channel": 'app_%s' % self.resource_id,
419 "channel": 'app_%s' % self.resource_id,
420 'message': {
420 'message': {
421 'type': 'report',
421 'topic': 'front_dashboard.new_topic',
422 'report': {
422 'report': {
423 'group': {
423 'group': {
424 'priority': report_group.priority,
424 'priority': report_group.priority,
@@ -441,8 +441,7 b' class Report(Base, BaseModel):'
441 }
441 }
442
442
443 }
443 }
444
444 channelstream_request(settings['cometd.secret'], '/message', [payload],
445 cometd_request(settings['cometd.secret'], '/message', [payload],
446 servers=[settings['cometd_servers']])
445 servers=[settings['cometd_servers']])
447
446
448 def es_doc(self):
447 def es_doc(self):
@@ -2671,7 +2671,12 b" angular.module('appenlight.base', ["
2671
2671
2672 angular.module('appenlight.filters', []);
2672 angular.module('appenlight.filters', []);
2673 angular.module('appenlight.templates', []);
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 angular.module('appenlight.directives', [
2680 angular.module('appenlight.directives', [
2676 'appenlight.directives.appVersion',
2681 'appenlight.directives.appVersion',
2677 'appenlight.directives.c3chart',
2682 'appenlight.directives.c3chart',
@@ -2714,6 +2719,7 b" var app = angular.module('appenlight', ["
2714 'appenlight.services',
2719 'appenlight.services',
2715 'appenlight.directives',
2720 'appenlight.directives',
2716 'appenlight.controllers',
2721 'appenlight.controllers',
2722 'appenlight.components',
2717 'appenlight.plugins'
2723 'appenlight.plugins'
2718 ]);
2724 ]);
2719
2725
@@ -2731,7 +2737,6 b' function kickstartAE(initialUserData) {'
2731 return response;
2737 return response;
2732 },
2738 },
2733 'responseError': function (rejection) {
2739 'responseError': function (rejection) {
2734
2735 if (rejection.status > 299 && rejection.status !== 422) {
2740 if (rejection.status > 299 && rejection.status !== 422) {
2736 stateHolder.flashMessages.extend([{
2741 stateHolder.flashMessages.extend([{
2737 msg: 'Response status code: ' + rejection.status + ', "' + rejection.statusText + '", url: ' + rejection.config.url,
2742 msg: 'Response status code: ' + rejection.status + ', "' + rejection.statusText + '", url: ' + rejection.config.url,
@@ -7017,6 +7022,64 b' function kickstartAE(initialUserData) {'
7017 // # services, and proprietary license terms, please see
7022 // # services, and proprietary license terms, please see
7018 // # https://rhodecode.com/licenses/
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 var aeconfig = angular.module('appenlight.config', []);
7083 var aeconfig = angular.module('appenlight.config', []);
7021 aeconfig.factory('AeConfig', function () {
7084 aeconfig.factory('AeConfig', function () {
7022 var obj = {};
7085 var obj = {};
@@ -8478,55 +8541,31 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
8478 'series': true
8541 'series': true
8479 };
8542 };
8480 vm.stream = {paused: false, filtered: false, messages: [], reports: []};
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 vm.determineStartState = function () {
8571 vm.determineStartState = function () {
@@ -8582,12 +8621,12 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
8582 vm.fetchMetrics();
8621 vm.fetchMetrics();
8583 vm.fetchRequestsBreakdown();
8622 vm.fetchRequestsBreakdown();
8584 vm.fetchSlowCalls();
8623 vm.fetchSlowCalls();
8585 }
8624 };
8586
8625
8587 vm.changedTimeSpan = function(){
8626 vm.changedTimeSpan = function(){
8588 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
8627 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
8589 vm.refreshData();
8628 vm.refreshData();
8590 }
8629 };
8591
8630
8592 var intervalId = $interval(function () {
8631 var intervalId = $interval(function () {
8593 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
8632 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
@@ -8599,14 +8638,6 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
8599 }
8638 }
8600 }, 60000);
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 vm.fetchApdexStats = function () {
8641 vm.fetchApdexStats = function () {
8611 vm.loading.apdex = true;
8642 vm.loading.apdex = true;
8612 vm.apdexStats = applicationsPropertyResource.query({
8643 vm.apdexStats = applicationsPropertyResource.query({
@@ -12706,7 +12737,8 b" angular.module('appenlight.services.resources').factory('resourcesPropertyResour"
12706 // # services, and proprietary license terms, please see
12737 // # services, and proprietary license terms, please see
12707 // # https://rhodecode.com/licenses/
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 var AeUser = {"user_name": null, "id": null};
12743 var AeUser = {"user_name": null, "id": null};
12712 AeUser.update = function (jsonData) {
12744 AeUser.update = function (jsonData) {
@@ -1,5 +1,6 b''
1 <!-- Fixed navbar -->
1 <!-- Fixed navbar -->
2 <div id="top-navbar" class="navbar navbar-default navbar-fixed-top" role="navigation" data-ng-controller="HeaderCtrl as header">
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 <div class="pattern">
4 <div class="pattern">
4 <div class="container">
5 <div class="container">
5 <div class="navbar-header pull-left">
6 <div class="navbar-header pull-left">
@@ -37,7 +37,7 b' from ziggurat_foundations.models.services.external_identity import \\'
37
37
38 from appenlight.lib import generate_random_string
38 from appenlight.lib import generate_random_string
39 from appenlight.lib.social import handle_social_data
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 permission_tuple_to_dict
41 permission_tuple_to_dict
42 from appenlight.models import DBSession
42 from appenlight.models import DBSession
43 from appenlight.models.alert_channels.email import EmailAlertChannel
43 from appenlight.models.alert_channels.email import EmailAlertChannel
@@ -259,7 +259,7 b' def users_websocket(request):'
259 "channels": channels
259 "channels": channels
260 }
260 }
261 settings = request.registry.settings
261 settings = request.registry.settings
262 response = cometd_request(
262 response = channelstream_request(
263 settings['cometd.secret'], '/connect', payload,
263 settings['cometd.secret'], '/connect', payload,
264 servers=[request.registry.settings['cometd_servers']],
264 servers=[request.registry.settings['cometd_servers']],
265 throw_exceptions=True)
265 throw_exceptions=True)
@@ -36,7 +36,12 b" angular.module('appenlight.base', ["
36
36
37 angular.module('appenlight.filters', []);
37 angular.module('appenlight.filters', []);
38 angular.module('appenlight.templates', []);
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 angular.module('appenlight.directives', [
45 angular.module('appenlight.directives', [
41 'appenlight.directives.appVersion',
46 'appenlight.directives.appVersion',
42 'appenlight.directives.c3chart',
47 'appenlight.directives.c3chart',
@@ -79,6 +84,7 b" var app = angular.module('appenlight', ["
79 'appenlight.services',
84 'appenlight.services',
80 'appenlight.directives',
85 'appenlight.directives',
81 'appenlight.controllers',
86 'appenlight.controllers',
87 'appenlight.components',
82 'appenlight.plugins'
88 'appenlight.plugins'
83 ]);
89 ]);
84
90
@@ -96,7 +102,6 b' function kickstartAE(initialUserData) {'
96 return response;
102 return response;
97 },
103 },
98 'responseError': function (rejection) {
104 'responseError': function (rejection) {
99 console.log(rejection);
100 if (rejection.status > 299 && rejection.status !== 422) {
105 if (rejection.status > 299 && rejection.status !== 422) {
101 stateHolder.flashMessages.extend([{
106 stateHolder.flashMessages.extend([{
102 msg: 'Response status code: ' + rejection.status + ', "' + rejection.statusText + '", url: ' + rejection.config.url,
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 'series': true
375 'series': true
376 };
376 };
377 vm.stream = {paused: false, filtered: false, messages: [], reports: []};
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 vm.determineStartState = function () {
405 vm.determineStartState = function () {
@@ -479,12 +455,12 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
479 vm.fetchMetrics();
455 vm.fetchMetrics();
480 vm.fetchRequestsBreakdown();
456 vm.fetchRequestsBreakdown();
481 vm.fetchSlowCalls();
457 vm.fetchSlowCalls();
482 }
458 };
483
459
484 vm.changedTimeSpan = function(){
460 vm.changedTimeSpan = function(){
485 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
461 vm.startDateFilter = timeSpanToStartDate(vm.timeSpan.key);
486 vm.refreshData();
462 vm.refreshData();
487 }
463 };
488
464
489 var intervalId = $interval(function () {
465 var intervalId = $interval(function () {
490 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
466 if (_.contains(['30m', "1h"], vm.timeSpan.key)) {
@@ -496,14 +472,6 b' function IndexDashboardController($scope, $location, $cookies, $interval, stateH'
496 }
472 }
497 }, 60000);
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 vm.fetchApdexStats = function () {
475 vm.fetchApdexStats = function () {
508 vm.loading.apdex = true;
476 vm.loading.apdex = true;
509 vm.apdexStats = applicationsPropertyResource.query({
477 vm.apdexStats = applicationsPropertyResource.query({
@@ -17,7 +17,8 b''
17 // # services, and proprietary license terms, please see
17 // # services, and proprietary license terms, please see
18 // # https://rhodecode.com/licenses/
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 var AeUser = {"user_name": null, "id": null};
23 var AeUser = {"user_name": null, "id": null};
23 AeUser.update = function (jsonData) {
24 AeUser.update = function (jsonData) {
General Comments 0
You need to be logged in to leave comments. Login now