updates to job results performance

This commit is contained in:
John Mitchell 2017-01-20 17:41:09 -05:00
parent 037d8a1ee4
commit 55034f1a78
7 changed files with 125 additions and 53 deletions

View File

@ -2234,3 +2234,8 @@ a:hover {
padding-left: 2px;
width: 14px;
}
button[disabled],
html input[disabled] {
cursor: not-allowed;
}

View File

@ -35,11 +35,14 @@
<div class="JobResultsStdOut-numberColumnPreload"></div>
<div id='lineAnchor' class="JobResultsStdOut-lineAnchor"></div>
<div class="JobResultsStdOut-aLineOfStdOut"
ng-show="tooManyEvents">
ng-show="tooManyEvents || tooManyPastEvents">
<div class="JobResultsStdOut-lineNumberColumn">
<span class="JobResultsStdOut-lineExpander"> </span>
</div>
<div class="JobResultsStdOut-stdoutColumn JobResultsStdOut-stdoutColumn--tooMany">The standard output is too large to display. Please specify additional filters to narrow the standard out.</div>
<div class="JobResultsStdOut-stdoutColumn JobResultsStdOut-stdoutColumn--tooMany"
ng-show="tooManyEvents">The standard output is too large to display. Please specify additional filters to narrow the standard out.</div>
<div class="JobResultsStdOut-stdoutColumn JobResultsStdOut-stdoutColumn--tooMany"
ng-show="tooManyPastEvents">Too much previous output to display. Showing running standard output.</div>
</div>
<div id="followAnchor"
class="JobResultsStdOut-followAnchor">

View File

@ -1,5 +1,5 @@
export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', 'eventQueue', '$compile', '$log', 'Dataset', '$q', 'Rest', '$state', 'QuerySet', '$rootScope', 'moment', 'i18n',
function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, eventQueue, $compile, $log, Dataset, $q, Rest, $state, QuerySet, $rootScope, moment, i18n) {
export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', 'eventQueue', '$compile', '$log', 'Dataset', '$q', 'Rest', '$state', 'QuerySet', '$rootScope', 'moment', '$stateParams', 'i18n',
function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, eventQueue, $compile, $log, Dataset, $q, Rest, $state, QuerySet, $rootScope, moment, $stateParams, i18n) {
var toDestroy = [];
var cancelRequests = false;
@ -9,6 +9,25 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy
// this allows you to manage the timing of rest-call based events as
// filters are updated. see processPage for more info
var currentContext = 1;
$scope.firstCounterFromSocket = -1;
// if the user enters the page mid-run, reset the search to include a param
// to only grab events less than the first counter from the websocket events
toDestroy.push($scope.$watch('firstCounterFromSocket', function(counter) {
if (counter > -1) {
// make it so that the search include a counter less than the
// first counter from the socket
let params = _.cloneDeep($stateParams.job_event_search);
params.counter__lte = "" + counter;
Dataset = QuerySet.search(jobData.related.job_events,
params);
Dataset.then(function(actualDataset) {
$scope.job_event_dataset = actualDataset.data;
});
}
}));
// used for tag search
$scope.job_event_dataset = Dataset.data;
@ -424,57 +443,87 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy
// grab non-header recap lines
toDestroy.push($scope.$watch('job_event_dataset', function(val) {
eventQueue.initialize();
if (val) {
eventQueue.initialize();
Object.keys($scope.events)
.forEach(v => {
// dont destroy scope events for skeleton lines
let name = $scope.events[v].event.name;
Object.keys($scope.events)
.forEach(v => {
// dont destroy scope events for skeleton lines
let name = $scope.events[v].event.name;
if (!(name === "playbook_on_play_start" ||
name === "playbook_on_task_start" ||
name === "playbook_on_stats")) {
$scope.events[v].$destroy();
$scope.events[v] = null;
delete $scope.events[v];
if (!(name === "playbook_on_play_start" ||
name === "playbook_on_task_start" ||
name === "playbook_on_stats")) {
$scope.events[v].$destroy();
$scope.events[v] = null;
delete $scope.events[v];
}
});
// pause websocket events from coming in to the pane
$scope.gotPreviouslyRanEvents = $q.defer();
currentContext += 1;
let context = currentContext;
$( ".JobResultsStdOut-aLineOfStdOut.not_skeleton" ).remove();
$scope.hasSkeleton.promise.then(() => {
if (val.count > parseInt(val.maxEvents)) {
$(".header_task").hide();
$(".header_play").hide();
$scope.standardOutTooltip = '<div class="JobResults-downloadTooLarge"><div>' +
i18n._('The output is too large to display. Please download.') +
'</div>' +
'<div class="JobResults-downloadTooLarge--icon">' +
'<span class="fa-stack fa-lg">' +
'<i class="fa fa-circle fa-stack-1x"></i>' +
'<i class="fa fa-stack-1x icon-job-stdout-download-tooltip"></i>' +
'</span>' +
'</div>' +
'</div>';
if ($scope.job_status === "successful" ||
$scope.job_status === "failed" ||
$scope.job_status === "error" ||
$scope.job_status === "canceled") {
$scope.tooManyEvents = true;
$scope.tooManyPastEvents = false;
} else {
$scope.tooManyPastEvents = true;
$scope.tooManyEvents = false;
$scope.gotPreviouslyRanEvents.resolve("");
}
} else {
$(".header_task").show();
$(".header_play").show();
$scope.tooManyEvents = false;
$scope.tooManyPastEvents = false;
processPage(val, context);
}
});
// pause websocket events from coming in to the pane
$scope.gotPreviouslyRanEvents = $q.defer();
currentContext += 1;
let context = currentContext;
$( ".JobResultsStdOut-aLineOfStdOut.not_skeleton" ).remove();
$scope.hasSkeleton.promise.then(() => {
if (val.count > parseInt(val.maxEvents)) {
$(".header_task").hide();
$(".header_play").hide();
$scope.tooManyEvents = true;
$scope.standardOutTooltip = '<div class="JobResults-downloadTooLarge"><div>' +
i18n._('The output is too large to display. Please download.') +
'</div>' +
'<div class="JobResults-downloadTooLarge--icon">' +
'<span class="fa-stack fa-lg">' +
'<i class="fa fa-circle fa-stack-1x"></i>' +
'<i class="fa fa-stack-1x icon-job-stdout-download-tooltip"></i>' +
'</span>' +
'</div>' +
'</div>';
} else {
$(".header_task").show();
$(".header_play").show();
$scope.tooManyEvents = false;
processPage(val, context);
}
});
}
}));
// Processing of job_events messages from the websocket
toDestroy.push($scope.$on(`ws-job_events-${$scope.job.id}`, function(e, data) {
// use the lowest counter coming over the socket to retrigger pull data
// to only be for stuff lower than that id
//
// only do this for entering the jobs page mid-run (thus the
// data.counter is 1 conditional
if (data.counter === 1) {
$scope.firstCounterFromSocket = -2;
}
if ($scope.firstCounterFromSocket !== -2 &&
$scope.firstCounterFromSocket === -1 ||
data.counter < $scope.firstCounterFromSocket) {
$scope.firstCounterFromSocket = data.counter;
}
$q.all([$scope.gotPreviouslyRanEvents.promise,
$scope.hasSkeleton.promise]).then(() => {
// put the line in the

View File

@ -506,7 +506,9 @@
list="list"
collection="job_events"
dataset="job_event_dataset"
search-tags="searchTags">
search-tags="searchTags"
disable-search="job_status == 'running' ||
job_status=='pending'">
</smart-search>
<job-results-standard-out></job-results-standard-out>
</div>

View File

@ -6,6 +6,12 @@
import {templateUrl} from '../shared/template-url/template-url.factory';
const defaultParams = {
page_size: "200",
order_by: 'start_line',
not__event__in: 'playbook_on_start,playbook_on_play_start,playbook_on_task_start,playbook_on_stats'
}
export default {
name: 'jobDetail',
url: '/jobs/{id: int}',
@ -24,11 +30,7 @@ export default {
},
params: {
job_event_search: {
value: {
page_size: 100,
order_by: 'id',
not__event__in: 'playbook_on_start,playbook_on_play_start,playbook_on_task_start,playbook_on_stats'
},
value: defaultParams,
dynamic: true,
squash: ''
}
@ -56,7 +58,7 @@ export default {
// flashing as rest data comes in. If the job is finished and
// there's a playbook_on_stats event, go ahead and resolve the count
// so you don't get that flashing!
count: ['jobData', 'jobResultsService', 'Rest', '$q', function(jobData, jobResultsService, Rest, $q) {
count: ['jobData', 'jobResultsService', 'Rest', '$q', '$stateParams', '$state', function(jobData, jobResultsService, Rest, $q, $stateParams, $state) {
var defer = $q.defer();
if (jobData.finished) {
// if the job is finished, grab the playbook_on_stats
@ -92,6 +94,15 @@ export default {
}, countFinished: false});
});
} else {
// make sure to not include any extra
// search params for a running job (because we can't filter
// incoming job events)
if (!_.isEqual($stateParams.job_event_search, defaultParams)) {
let params = _.cloneDeep($stateParams);
params.job_event_search = defaultParams;
$state.go('.', params, { reload: true });
}
// job isn't finished so just send an empty count and read
// from events
defer.resolve({val: {

View File

@ -15,6 +15,7 @@ export default ['templateUrl',
dataset: '=',
collection: '=',
searchTags: '=',
disableSearch: '='
},
controller: 'SmartSearchController',
templateUrl: templateUrl('shared/smart-search/smart-search')

View File

@ -4,7 +4,8 @@
<div class="SmartSearch-searchTermContainer">
<!-- string search input -->
<form name="smartSearch" class="SmartSearch-form" aw-enter-key="add(searchTerm)" novalidate>
<input class="SmartSearch-input" ng-model="searchTerm" placeholder="Search">
<input class="SmartSearch-input" ng-model="searchTerm" placeholder="{{disableSearch ? 'Cannot search running job' : 'Search'}}"
ng-disabled="disableSearch">
</form>
<div type="submit" class="SmartSearch-searchButton" ng-disabled="!searchTerm" ng-click="add(searchTerm)">
<i class="fa fa-search"></i>