Repository: eagle Updated Branches: refs/heads/master 906692058 -> 93f83f4a9
[EAGLE-949] Support job suggestion JPM: * Success job display job suggestions * Failure Job display task attempt & detail APP: * UI support dialog window Author: zombieJ <[email protected]> Closes #872 from zombieJ/EAGLE-949. Project: http://git-wip-us.apache.org/repos/asf/eagle/repo Commit: http://git-wip-us.apache.org/repos/asf/eagle/commit/93f83f4a Tree: http://git-wip-us.apache.org/repos/asf/eagle/tree/93f83f4a Diff: http://git-wip-us.apache.org/repos/asf/eagle/diff/93f83f4a Branch: refs/heads/master Commit: 93f83f4a975dd3303f776c4fc9b3da8a53384aa3 Parents: 9066920 Author: zombieJ <[email protected]> Authored: Wed Mar 15 00:52:54 2017 +0800 Committer: Hao Chen <[email protected]> Committed: Wed Mar 15 00:52:54 2017 +0800 ---------------------------------------------------------------------- .../main/webapp/app/apps/jpm/ctrl/detailCtrl.js | 73 ++++++++++++++++---- .../app/apps/jpm/partials/job/detail.html | 46 +++++++++++- .../src/main/webapp/app/dev/public/css/main.css | 4 ++ .../webapp/app/dev/public/js/services/uiSrv.js | 33 +++++++++ eagle-server/src/main/webapp/app/package.json | 2 +- 5 files changed, 141 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/eagle/blob/93f83f4a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/ctrl/detailCtrl.js ---------------------------------------------------------------------- diff --git a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/ctrl/detailCtrl.js b/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/ctrl/detailCtrl.js index 905f270..b56335b 100644 --- a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/ctrl/detailCtrl.js +++ b/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/ctrl/detailCtrl.js @@ -21,7 +21,7 @@ * `register` without params will load the module which using require */ register(function (jpmApp) { - jpmApp.controller("detailCtrl", function ($q, $wrapState, $element, $scope, PageConfig, Time, Entity, JPM) { + jpmApp.controller("detailCtrl", function ($q, $wrapState, $element, $rootScope, $scope, $sce, PageConfig, Time, Entity, JPM, UI) { var TASK_BUCKET_TIMES = [0, 30, 60, 120, 300, 600, 1800, 3600, 7200, 18000]; var i; var startTime, endTime; @@ -125,21 +125,68 @@ // =============================== task attempt =============================== - if ($scope.job.currentState === 'FAILED') { - $scope.taskAttemptList = JPM.list('TaskAttemptErrorCategoryService', { - site: $scope.job.tags.site, - jobId: $scope.job.tags.jobId - }, + (function () { + if ($scope.job.currentState === 'FAILED') { + // Attempt List + $scope.taskAttemptList = JPM.list('TaskAttemptErrorCategoryService', { + site: $scope.job.tags.site, + jobId: $scope.job.tags.jobId + }, + Time($scope.startTimestamp).subtract(1, 'day'), + Time($scope.endTimestamp).add(1, 'day')); + $scope.taskAttemptCategories = {}; + $scope.taskAttemptList._promise.then(function () { + $.each($scope.taskAttemptList, function (i, attempt) { + $scope.taskAttemptCategories[attempt.tags.errorCategory] = + ($scope.taskAttemptCategories[attempt.tags.errorCategory] || 0) + 1; + }); + }); + + // Error Mapping + $scope.errorMapping = {}; + var errorMappingList = JPM.list('JobErrorMappingService', { + site: $scope.job.tags.site, + jobId: $scope.job.tags.jobId + }, + Time($scope.startTimestamp).subtract(1, 'day'), + Time($scope.endTimestamp).add(1, 'day')); + errorMappingList._promise.then(function () { + $.each(errorMappingList, function (i, entity) { + var errorTooltip = $sce.trustAsHtml('<div class="text-break">' + entity.error + '</div>'); + + $.each(entity.taskAttempts, function (j, attempt) { + $scope.errorMapping[attempt] = errorTooltip; + }); + }); + }); + } + })(); + + $scope.loadAttemptDetail = function (taskAttemptId) { + var scope = $rootScope.$new(true); + scope.content = 'Loading...'; + + var attemptList = JPM.list('TaskAttemptExecutionService', { + site: $scope.job.tags.site, + taskAttemptId: taskAttemptId + }, Time($scope.startTimestamp).subtract(1, 'day'), Time($scope.endTimestamp).add(1, 'day')); - $scope.taskAttemptCategories = {}; - $scope.taskAttemptList._promise.then(function () { - $.each($scope.taskAttemptList, function (i, attempt) { - $scope.taskAttemptCategories[attempt.tags.errorCategory] = - ($scope.taskAttemptCategories[attempt.tags.errorCategory] || 0) + 1; - }); + attemptList._promise.then(function () { + scope.content = common.getValueByPath(attemptList, [0, 'error'], '(No Data)'); + scope.$apply(); }); - } + + UI.dialog(taskAttemptId, '<pre>{{content}}</pre>', scope); + }; + + // ============================== job suggestion ============================== + $scope.jobSuggestionList = JPM.list('JobOptimizerSuggestionService', { + site: $scope.job.tags.site, + jobId: $scope.job.tags.jobId + }, + Time($scope.startTimestamp).subtract(1, 'day'), + Time($scope.endTimestamp).add(1, 'day')); // ================================ dashboards ================================ // Dashboard 1: Allocated MB http://git-wip-us.apache.org/repos/asf/eagle/blob/93f83f4a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/job/detail.html ---------------------------------------------------------------------- diff --git a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/job/detail.html b/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/job/detail.html index 359b043..eeb5976 100644 --- a/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/job/detail.html +++ b/eagle-jpm/eagle-jpm-web/src/main/webapp/app/apps/jpm/partials/job/detail.html @@ -193,7 +193,7 @@ </div> <div class="box-body"> <div sort-table="taskAttemptList" is-sorting="isSorting" class="table-responsive" max-size="7" ng-show="taskAttemptList._done"> - <table class="table table-bordered"> + <table class="table table-bordered table-hover"> <thead> <tr> <th sortpath="startTime">Start Time</th> @@ -205,13 +205,53 @@ </tr> </thead> <tbody> - <tr ng-repeat="item in jobList"> + <tr class="row-clickable" ng-click="loadAttemptDetail(item.tags.taskAttemptId)"> <td>{{Time.format(item.startTime)}}</td> <td>{{Time.format(item.endTime)}}</td> <td>{{item.tags.hostname || "-"}}</td> <td>{{item.tags.taskType || "-"}}</td> <td>{{item.tags.taskAttemptId || "-"}}</td> - <td>{{item.tags.errorCategory || "-"}}</td> + <td class="text-no-break"> + {{item.tags.errorCategory || "-"}} + <span + ng-if="errorMapping[item.tags.taskAttemptId]" + class="fa fa-info-circle" tooltip-placement="left" + uib-tooltip-html="errorMapping[item.tags.taskAttemptId]" + > + </span> + </td> + </tr> + </tbody> + </table> + </div> + </div> +</div> + +<!-- Job Suggestion --> +<div class="box box-primary collapsed-box" ng-if="jobSuggestionList.length"> + <div class="box-header with-border"> + <h3 class="box-title"> + Job Suggestion ({{jobSuggestionList.length}}) + </h3> + <div class="box-tools pull-right"> + <button type="button" class="btn btn-box-tool" data-widget="collapse"> + <i class="fa fa-plus"></i> + </button> + </div> + </div> + <div class="box-body"> + <div sort-table="jobSuggestionList" class="table-responsive" max-size="7"> + <table class="table table-bordered"> + <thead> + <tr> + <th sortpath="tags.ruleType">Rule Type</th> + <th>Optimizer Suggestion</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{item.tags.ruleType}}</td> + <td><pre class="inline">{{item.optimizerSuggestion}}</pre></td> </tr> </tbody> </table> http://git-wip-us.apache.org/repos/asf/eagle/blob/93f83f4a/eagle-server/src/main/webapp/app/dev/public/css/main.css ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/webapp/app/dev/public/css/main.css b/eagle-server/src/main/webapp/app/dev/public/css/main.css index 30e10d7..a50ffac 100644 --- a/eagle-server/src/main/webapp/app/dev/public/css/main.css +++ b/eagle-server/src/main/webapp/app/dev/public/css/main.css @@ -163,6 +163,10 @@ table.table .btn-group .btn.opt { width: 22px; } +table.table .row-clickable { + cursor: pointer; +} + table.table.table-sm th, table.table.table-sm td { padding: 3px 5px; http://git-wip-us.apache.org/repos/asf/eagle/blob/93f83f4a/eagle-server/src/main/webapp/app/dev/public/js/services/uiSrv.js ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/webapp/app/dev/public/js/services/uiSrv.js b/eagle-server/src/main/webapp/app/dev/public/js/services/uiSrv.js index 6ce77b8..81ee9d8 100644 --- a/eagle-server/src/main/webapp/app/dev/public/js/services/uiSrv.js +++ b/eagle-server/src/main/webapp/app/dev/public/js/services/uiSrv.js @@ -252,6 +252,21 @@ return wrapPromise(_deferred.promise); }; + UI.dialog = function (title, html, $scope) { + var $mdl; + + $mdl = $(common.template(TMPL_MODAL, { + title: title, + html: html + })).appendTo('body'); + $compile($mdl)($scope); + $mdl.modal(); + + $mdl.on("hidden.bs.modal", function() { + $mdl.remove(); + }); + }; + return UI; }); @@ -313,4 +328,22 @@ '</div>' + '</div>' + '</div>'; + + var TMPL_MODAL = + '<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">' + + '<div class="modal-dialog">' + + '<div class="modal-content">' + + '<div class="modal-header">' + + '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' + + '<h4 class="modal-title">${title}</h4>' + + '</div>' + + '<div class="modal-body">' + + '${html}' + + '</div>' + + '<div class="modal-footer">' + + '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>' + + '</div>' + + '</div>' + + '</div>' + + '</div>'; }()); http://git-wip-us.apache.org/repos/asf/eagle/blob/93f83f4a/eagle-server/src/main/webapp/app/package.json ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/webapp/app/package.json b/eagle-server/src/main/webapp/app/package.json index 2c5d272..11d72e3 100644 --- a/eagle-server/src/main/webapp/app/package.json +++ b/eagle-server/src/main/webapp/app/package.json @@ -19,7 +19,7 @@ "angular-cookies": "1.5.0", "angular-resource": "1.5.0", "angular-route": "1.5.0", - "angular-ui-bootstrap": "1.1.2", + "angular-ui-bootstrap": "1.3.3", "angular-ui-router": "0.3.1", "bootstrap": "3.3.6", "d3": "3.5.16",
