[FLINK-3310] [runtime-web] Add back pressure statistics to web dashboard (frontend)
This closes #1578. Project: http://git-wip-us.apache.org/repos/asf/flink/repo Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/ba13caa1 Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/ba13caa1 Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/ba13caa1 Branch: refs/heads/master Commit: ba13caa1bc10cfd4c94cdc89f674b64751a83a17 Parents: b7e70da Author: Ufuk Celebi <u...@apache.org> Authored: Mon Feb 1 21:01:26 2016 +0100 Committer: Ufuk Celebi <u...@apache.org> Committed: Mon Feb 8 15:05:00 2016 +0100 ---------------------------------------------------------------------- .../app/partials/jobs/job.plan.jade | 3 + .../jobs/job.plan.node-list.backpressure.jade | 77 + .../app/scripts/common/directives.coffee | 15 + .../app/scripts/common/filters.coffee | 2 + .../web-dashboard/app/scripts/index.coffee | 7 + .../app/scripts/modules/jobs/jobs.ctrl.coffee | 20 + .../app/scripts/modules/jobs/jobs.svc.coffee | 18 + .../web-dashboard/web/css/vendor.css | 13843 +++++++------ .../web-dashboard/web/fonts/FontAwesome.otf | Bin 109688 -> 93888 bytes .../web/fonts/fontawesome-webfont.eot | Bin 70807 -> 60767 bytes .../web/fonts/fontawesome-webfont.svg | 134 +- .../web/fonts/fontawesome-webfont.ttf | Bin 142072 -> 122092 bytes .../web/fonts/fontawesome-webfont.woff | Bin 83588 -> 71508 bytes .../web/fonts/fontawesome-webfont.woff2 | Bin 66624 -> 56780 bytes flink-runtime-web/web-dashboard/web/js/index.js | 72 +- .../web-dashboard/web/js/vendor.js | 17901 +++++++---------- .../web/partials/jobs/job.plan.html | 1 + .../jobs/job.plan.node-list.backpressure.html | 80 + 18 files changed, 14323 insertions(+), 17850 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.jade ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.jade b/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.jade index 5dc2632..46eeec6 100644 --- a/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.jade +++ b/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.jade @@ -30,4 +30,7 @@ li(ui-sref-active='active') a(ui-sref=".checkpoints({nodeid: nodeid})") Checkpoints + li(ng-if="job.state == 'RUNNING'" ui-sref-active='active') + a(ui-sref=".backpressure({nodeid: nodeid})") Back Pressure + .panel-body.clean(ui-view="node-details") http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.node-list.backpressure.jade ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.node-list.backpressure.jade b/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.node-list.backpressure.jade new file mode 100644 index 0000000..bf7f077 --- /dev/null +++ b/flink-runtime-web/web-dashboard/app/partials/jobs/job.plan.node-list.backpressure.jade @@ -0,0 +1,77 @@ +// + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +table.table.table-body-hover.table-clickable.table-activable + thead + tr + th Name + th Status + + tbody(ng-repeat="v in job.vertices" ng-class="{ active: v.id == nodeid }" ng-click="v.id == nodeid || changeNode(v.id)") + tr(ng-if="v.type == 'regular'") + td {{ v.name | humanizeText }} + td + bs-label(status="{{v.status}}") {{v.status}} + tr(ng-if="nodeid && v.id == nodeid") + td(ng-if="v.status != 'RUNNING'" colspan=2) + p Operator is not running. Cannot sample back pressure. + td(ng-if="v.status == 'RUNNING'" colspan=2) + table.table.table-hover.table-clickable.table-activable.table-inner + thead + tr + th Measurement + th Back Pressure Status + tbody + tr + td + span(ng-if="backPressureOperatorStats[v.id]['end-timestamp']") {{ now - backPressureOperatorStats[v.id]['end-timestamp'] | humanizeDuration }} ago + span(ng-if="backPressureOperatorStats[v.id]['status'] == 'deprecated'") + bp-label(status="in-progress") Sampling in progress... + td + bp-label(ng-if="backPressureOperatorStats[v.id]['backpressure-level']" status="{{backPressureOperatorStats[v.id]['backpressure-level']}}") {{ backPressureOperatorStats[v.id]['backpressure-level'] | toUpperCase }} + + div(ng-if="!nodeUnfolded && backPressureOperatorStats[v.id]['subtasks'] && backPressureOperatorStats[v.id]['subtasks'].length > 0") + a.btn.btn-default(ng-click="toggleFold()") + | Show subtasks + = ' ' + i.fa.fa-chevron-down + + a.btn.btn-default.pull-right(ng-click="deactivateNode(); $event.stopPropagation()" title="Fold") + i.fa.fa-chevron-up + + div(ng-if="nodeUnfolded && backPressureOperatorStats[v.id]['subtasks'] && backPressureOperatorStats[v.id]['subtasks'].length > 0") + a.btn.btn-default(ng-click="toggleFold()") + | Hide subtasks + = ' ' + i.fa.fa-chevron-up + + a.btn.btn-default.pull-right(ng-click="deactivateNode(); $event.stopPropagation()" title="Fold") + i.fa.fa-chevron-up + + table.table.table-hover.table-clickable.table-activable.table-inner + thead + tr + th Subtask + th Ratio + th Status + tbody + tr(ng-repeat="subtask in backPressureOperatorStats[nodeid]['subtasks']") + td {{ subtask['subtask'] + 1 }} + td {{ subtask['ratio'] }} + td + bp-label(status="{{subtask['backpressure-level']}}") {{ subtask['backpressure-level'] | toUpperCase }} + http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/scripts/common/directives.coffee ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/scripts/common/directives.coffee b/flink-runtime-web/web-dashboard/app/scripts/common/directives.coffee index 98212ee..39fbd50 100644 --- a/flink-runtime-web/web-dashboard/app/scripts/common/directives.coffee +++ b/flink-runtime-web/web-dashboard/app/scripts/common/directives.coffee @@ -35,6 +35,21 @@ angular.module('flinkApp') # ---------------------------------------------- +.directive 'bpLabel', (JobsService) -> + transclude: true + replace: true + scope: + getBackPressureLabelClass: "&" + status: "@" + + template: "<span title='{{status}}' ng-class='getBackPressureLabelClass()'><ng-transclude></ng-transclude></span>" + + link: (scope, element, attrs) -> + scope.getBackPressureLabelClass = -> + 'label label-' + JobsService.translateBackPressureLabelState(attrs.status) + +# ---------------------------------------------- + .directive 'indicatorPrimary', (JobsService) -> replace: true scope: http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/scripts/common/filters.coffee ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/scripts/common/filters.coffee b/flink-runtime-web/web-dashboard/app/scripts/common/filters.coffee index 473adc3..093c599 100644 --- a/flink-runtime-web/web-dashboard/app/scripts/common/filters.coffee +++ b/flink-runtime-web/web-dashboard/app/scripts/common/filters.coffee @@ -73,3 +73,5 @@ angular.module('flinkApp') return "" if typeof bytes is "undefined" or bytes is null if bytes < 1000 then bytes + " B" else converter(bytes, 1) +.filter "toUpperCase", -> + (text) -> text.toUpperCase() http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/scripts/index.coffee ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/scripts/index.coffee b/flink-runtime-web/web-dashboard/app/scripts/index.coffee index 07e13ff..07e5265 100644 --- a/flink-runtime-web/web-dashboard/app/scripts/index.coffee +++ b/flink-runtime-web/web-dashboard/app/scripts/index.coffee @@ -113,6 +113,13 @@ angular.module('flinkApp', ['ui.router', 'angularMoment']) templateUrl: "partials/jobs/job.plan.node-list.checkpoints.html" controller: 'JobPlanCheckpointsController' + .state "single-job.plan.backpressure", + url: "/backpressure" + views: + 'node-details': + templateUrl: "partials/jobs/job.plan.node-list.backpressure.html" + controller: 'JobPlanBackPressureController' + .state "single-job.timeline", url: "/timeline" views: http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.ctrl.coffee ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.ctrl.coffee b/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.ctrl.coffee index 899a099..37ce217 100644 --- a/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.ctrl.coffee +++ b/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.ctrl.coffee @@ -51,6 +51,7 @@ angular.module('flinkApp') $scope.vertices = null $scope.jobCheckpointStats = null $scope.showHistory = false + $scope.backPressureOperatorStats = {} JobsService.loadJob($stateParams.jobid).then (data) -> $scope.job = data @@ -70,6 +71,7 @@ angular.module('flinkApp') $scope.plan = null $scope.vertices = null $scope.jobCheckpointStats = null + $scope.backPressureOperatorStats = null $interval.cancel(refresher) @@ -179,6 +181,24 @@ angular.module('flinkApp') # -------------------------------------- +.controller 'JobPlanBackPressureController', ($scope, JobsService) -> + console.log 'JobPlanBackPressureController' + $scope.now = Date.now() + + if $scope.nodeid + JobsService.getOperatorBackPressure($scope.nodeid).then (data) -> + $scope.backPressureOperatorStats[$scope.nodeid] = data + + $scope.$on 'reload', (event) -> + console.log 'JobPlanBackPressureController (relaod)' + $scope.now = Date.now() + + if $scope.nodeid + JobsService.getOperatorBackPressure($scope.nodeid).then (data) -> + $scope.backPressureOperatorStats[$scope.nodeid] = data + +# -------------------------------------- + .controller 'JobTimelineVertexController', ($scope, $state, $stateParams, JobsService) -> console.log 'JobTimelineVertexController' http://git-wip-us.apache.org/repos/asf/flink/blob/ba13caa1/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.svc.coffee ---------------------------------------------------------------------- diff --git a/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.svc.coffee b/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.svc.coffee index 404647b..8756496 100644 --- a/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.svc.coffee +++ b/flink-runtime-web/web-dashboard/app/scripts/modules/jobs/jobs.svc.coffee @@ -232,6 +232,24 @@ angular.module('flinkApp') deferred.promise + # Operator-level back pressure stats + @getOperatorBackPressure = (vertexid) -> + deferred = $q.defer() + + $http.get flinkConfig.jobServer + "jobs/" + currentJob.jid + "/vertices/" + vertexid + "/backpressure" + .success (data) => + deferred.resolve(data) + + deferred.promise + + @translateBackPressureLabelState = (state) -> + switch state.toLowerCase() + when 'in-progress' then 'danger' + when 'ok' then 'success' + when 'low' then 'warning' + when 'high' then 'danger' + else 'default' + @loadExceptions = -> deferred = $q.defer()