Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 104 additions & 7 deletions ui/eventing-ui/ui-current/eventing.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
self.disableEditButton = false;
self.appListStaleCount = 0;
self.statusPollMillis = 2000;
self.deployedStats = null;

// Broadcast on channel 'isEventingRunning'
$rootScope.$broadcast('isEventingRunning', self.isEventingRunning);
Expand All @@ -41,6 +42,11 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
var updAppList = new Set(); // appname not in UI
var rspAppStat = new Map(); // composite_status by appname (in UI and not in UI)
var uiIsStale = false; // if we need to reload somehting new App or state change
var statsConfig = {
haveDeployedOrDeploying: false,
metaDataBucket: "",
lastSampleTime: new Date().valueOf()
};

for (var rspApp of response.apps ? response.apps : []) {

Expand All @@ -67,13 +73,44 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
}
}
}
statsConfig.reqstats = "";
for (var app of Object.keys(self.appList)) {
if (!rspAppList.has(app)) {
// An App from the UI's current list doesn't exisit in the recurring status
uiIsStale = true;
} else {
self.appList[app].uiState = determineUIStatus(self.appList[app].status);
self.appList[app].warnings = getWarnings(self.appList[app]);
if (!self.appList[app].cluster_stats) {
self.appList[app].cluster_stats = {};
}

if (self.appList[app].status === 'deployed' || self.appList[app].status === 'deploying') {
statsConfig.haveDeployedOrDeploying = true;
statsConfig.metaDataBucket = self.appList[app].depcfg.metadata_bucket;

if (statsConfig.reqstats !== "") {
statsConfig.reqstats = statsConfig.reqstats + ',';
}

statsConfig.reqstats = statsConfig.reqstats +
'"eventing/' + app + '/processed_count",' +
'"eventing/' + app + '/failed_count",' +
'"eventing/' + app + '/dcp_backlog",' +
'"eventing/' + app + '/timeout_count"';

// make sure we loaded the needed stats
if (self.deployedStats && self.deployedStats !== null) {
// attach statistics to our UI information for the deployed hander else just '-'
self.appList[app].cluster_stats.show = 1;
formatDeployedStats(app, 'success', 'processed_count');
formatDeployedStats(app, 'failure', 'failed_count');
formatDeployedStats(app, 'backlog', 'dcp_backlog');
formatDeployedStats(app, 'timeout', 'timeout_count');
}
} else {
self.appList[app].cluster_stats = {};
}
}
}
if (!uiIsStale) {
Expand Down Expand Up @@ -110,6 +147,9 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
fetchCpuCount();
}

// Only does the fetch if we have one or more items deploying or deployed in the UI
fetchDeployedStats(statsConfig);

}).catch(function(errResponse) {
self.errorCode = errResponse && errResponse.status || 500;
// Do not log the occasional HTTP abort when we leave the Eventing view
Expand All @@ -119,6 +159,54 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
});
}

function formatDeployedStats(app, tag, a) {
var ret = '-';
var ary_a = self.deployedStats.stats['eventing/' + app + '/' + a];
if (ary_a && ary_a.aggregate && ary_a.aggregate.length > 0) {
var val_a = ary_a.aggregate[ary_a.aggregate.length - 1];
if (!isNaN(val_a)) {
ret = val_a;
if (ret > 9999999) {
ret = d3.format(".4s")(val_a);
}
}
}
if (typeof ret === 'undefined') {
ret = '-';
}
self.appList[app].cluster_stats[tag] = ret;
self.appList[app].cluster_stats[tag + '_gt_zero'] = false;
if (!isNaN(ret) && ret > 0) {
self.appList[app].cluster_stats[tag + '_gt_zero'] = true;
}
return ret;
}

function fetchDeployedStats(statsConfig) {

if (self.deployedStats && self.deployedStats['timestamps']) {
var tstamps = self.deployedStats['timestamps'];
statsConfig.lastSampleTime = tstamps[tstamps.length - 1];
}

self.deployedStats = null;
if (statsConfig.haveDeployedOrDeploying == false || statsConfig.metaDataBucket === "") {
return;
}
ApplicationService.server.getDeployedStats(statsConfig)
.then(function(response) {
if (response && response.data && response.data[0]) {
self.deployedStats = response.data[0];
return;
}
})
.catch(function(errResponse) {
console.error('Unable to get deployed stats count', errResponse);
return;
});
}


function fetchWorkerCount() {
ApplicationService.server.getWorkerCount()
.then(function(response) {
Expand Down Expand Up @@ -404,6 +492,7 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
app.settings.cleanup_timers = appClone.settings.cleanup_timers;
app.settings.deployment_status = appClone.settings.deployment_status;
app.settings.processing_status = appClone.settings.processing_status;
app.settings.cluster_stats = appClone.settings.cluster_stats;

self.disableEditButton = false;

Expand Down Expand Up @@ -463,9 +552,9 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
return $q.reject(ApplicationService.status.getErrorMsg(responseCode, response.data));
}

console.log(response.data);
app.settings.deployment_status = false;
app.settings.processing_status = false;
app.settings.cluster_stats = null;
ApplicationService.server.showSuccessAlert(`${app.appname} will be undeployed`);

// since the UI is changing state via undeploy update the count
Expand Down Expand Up @@ -581,10 +670,11 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
Object.assign(creationScope.appModel.depcfg, ApplicationService.convertBindingToConfig(creationScope.bindings));
creationScope.appModel.fillWithMissingDefaults();

// When we import the application, we want it to be in
// disabled and undeployed state.
// When we import the application, we want it to be in disabled and
// undeployed state with feed bondary "everything" ("from_prior" is not legal)
creationScope.appModel.settings.processing_status = false;
creationScope.appModel.settings.deployment_status = false;
creationScope.appModel.settings.dcp_stream_boundary = "everything";

// Deadline timeout must be greater and execution timeout.
if (creationScope.appModel.settings.hasOwnProperty('execution_timeout')) {
Expand Down Expand Up @@ -1471,6 +1561,13 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
console.error('Unable to get logFileLocation', errResponse.data);
});
},
getDeployedStats: function(statsConfig) {
// just one sample sometimes gets nothing, so grab the last five seconds
return $http.post('/_uistats',
'[{"bucket":"' + statsConfig.metaDataBucket + '","step":1,"stats":[' + statsConfig.reqstats + '],"startTS":-5000,"aggregate":true}]'
);

},
getWorkerCount: function() {
return $http.get('/_p/event/getWorkerCount');
},
Expand Down Expand Up @@ -1689,9 +1786,9 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
bindingError,
hostnameValid,
hostnameError,
bindingsValidList = []
hostnameValidList = []
form = formCtrl.createAppForm;
bindingsValidList = [],
hostnameValidList = [],
form = formCtrl.createAppForm;

for (var binding of bindings) {
if (binding.value.length) {
Expand Down Expand Up @@ -1805,4 +1902,4 @@ angular.module('eventing', ['mnPluggableUiRegistry', 'ui.router', 'mnPoolDefault
});
}
]);
angular.module('mnAdmin').requires.push('eventing');
angular.module('mnAdmin').requires.push('eventing');
115 changes: 84 additions & 31 deletions ui/eventing-ui/ui-current/fragments/summary.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,37 +61,90 @@
<div class="cbui-tablerow-expanded"
ng-if="app.actionsVisible">
<p class="width-6">{{app.settings.description}}</p>
<div class="width-12 text-right">
<button
class="outline"
ng-click="$event.stopPropagation();summaryCtrl.deleteApp(app.appname)"
ng-disabled="app.settings.processing_status || app.settings.deployment_status || app.uiState === 'healthy'">
Delete
</button>
<button
class="outline"
ng-click="$event.stopPropagation();summaryCtrl.exportApp(app.appname)">
Export
</button>
<button
class="outline"
ng-disabled="app.status === 'deploying' || app.status === 'undeploying' || app.status === 'pausing'"
ng-click="$event.stopPropagation();summaryCtrl.toggleDeployment(app)">
{{app.getDeploymentStatus(true)}}
</button>
<button
class="outline"
ng-disabled="app.status === 'deploying' || app.status === 'undeploying' || app.status === 'undeployed' || app.status === 'pausing'"
ng-click="$event.stopPropagation();summaryCtrl.toggleProcessing(app)">
{{app.getProcessingStatus(true)}}
</button>
<button
ng-click="$event.stopPropagation();"
ui-sref="app.admin.eventing.handler({appName:app.appname})"
ng-disabled="summaryCtrl.disableEditButton">
Edit JavaScript
</button>
</div>
<div class="width-12">
<table style="border-collapse:collapse;padding:0px;margin:0px" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="text-smaller" align="left" style="padding:0px;color:#555;">
<div ng-show="app.status !== 'undeployed'" ng-if="app.cluster_stats.show">
<table style="border-collapse:collapse;padding:0px;margin:0px;width:260px" border="0" cellpadding="0" cellspacing="0">
<tr>
<td colspan="5" style="border-collapse:collapse;padding:0px;margin:0px;width:260px;text-decoration: underline">
Deployment Statistics
</td>
</tr>
<tr>
<td style="border-collapse:collapse;padding:0px;margin:0px;width:60px">
success:
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px;width:60px" align="right">
{{app.cluster_stats.success}}
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px;width:20px" align="right">
&nbsp; &nbsp;
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px;width:60px">
backlog:
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px;width:60px" align="right">
{{app.cluster_stats.backlog}}
</td>
</tr>
<tr>
<td style="border-collapse:collapse;padding:0px;margin:0px">
timeout:
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px" align="right">
<div style=" display: inline-block;" ng-if="app.cluster_stats.timeout_gt_zero == false"> {{app.cluster_stats.timeout}} </div>
<div style="color: #CC0000; display: inline-block;" ng-if="app.cluster_stats.timeout_gt_zero == true "> {{app.cluster_stats.timeout}} </div>
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px" align="right">
&nbsp; &nbsp;
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px">
failure:
</td>
<td style="border-collapse:collapse;padding:0px;margin:0px" align="right">
<div style=" display: inline-block;" ng-if="app.cluster_stats.failure_gt_zero == false"> {{app.cluster_stats.failure}} </div>
<div style="color: #CC0000; display: inline-block;" ng-if="app.cluster_stats.failure_gt_zero == true "> {{app.cluster_stats.failure}} </div>
</td>
</tr>
</table>
</div>
</td>
<td align="right" style="padding:0px;">
<button
class="outline"
ng-click="$event.stopPropagation();summaryCtrl.deleteApp(app.appname)"
ng-disabled="app.settings.processing_status || app.settings.deployment_status || app.uiState === 'healthy'">
Delete
</button>
<button
class="outline"
ng-click="$event.stopPropagation();summaryCtrl.exportApp(app.appname)">
Export
</button>
<button
class="outline"
ng-disabled="app.status === 'deploying' || app.status === 'undeploying' || app.status === 'pausing'"
ng-click="$event.stopPropagation();summaryCtrl.toggleDeployment(app)">
{{app.getDeploymentStatus(true)}}
</button>
<button
class="outline"
ng-disabled="app.status === 'deploying' || app.status === 'undeploying' || app.status === 'undeployed' || app.status === 'pausing'"
ng-click="$event.stopPropagation();summaryCtrl.toggleProcessing(app)">
{{app.getProcessingStatus(true)}}
</button>
<button
ui-sref="app.admin.eventing.handler({appName:app.appname})"
ng-disabled="summaryCtrl.disableEditButton"
ng-click="$event.stopPropagation();">
{{app.status === 'deployed' || app.status === 'deploying' ? 'View JavaScript' : 'Edit JavaScript'}}
</button>
</td>
</tr>
</table>
</div>
</div>
</section>
</div>
Expand Down