http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/dashboard.js ---------------------------------------------------------------------- diff --git a/services/dashboard/dashboard.js b/services/dashboard/dashboard.js index 90f3609..37af2bf 100644 --- a/services/dashboard/dashboard.js +++ b/services/dashboard/dashboard.js @@ -3,10 +3,10 @@ * See accompanying LICENSE file. */ -(function() { +(function () { // rootPath of this site, it has a tailing slash / - var rootPath = function() { + var rootPath = function () { var root = location.origin + location.pathname; return root.substring(0, root.lastIndexOf("/") + 1); }(); @@ -25,102 +25,102 @@ 'io.gearpump.models' ]) - // configure routes - .config(['$stateProvider', '$urlRouterProvider', - function($stateProvider, $urlRouterProvider) { + // configure routes + .config(['$stateProvider', '$urlRouterProvider', + function ($stateProvider, $urlRouterProvider) { + 'use strict'; + + $urlRouterProvider + .when('', '/') + .when('/', '/cluster') + .when('/cluster', '/cluster/master'); + + $stateProvider + .state('cluster', { + abstract: true, // todo: we have a sidebar for cluster only + url: '/cluster', + templateUrl: 'views/cluster/overview.html' + }); + // Please check every controller for corresponding state definition + }]) + + // configure loading bar effect + .config(['cfpLoadingBarProvider', function (cfpLoadingBarProvider) { 'use strict'; - $urlRouterProvider - .when('', '/') - .when('/', '/cluster') - .when('/cluster', '/cluster/master'); - - $stateProvider - .state('cluster', { - abstract: true, // todo: we have a sidebar for cluster only - url: '/cluster', - templateUrl: 'views/cluster/overview.html' - }); - // Please check every controller for corresponding state definition + cfpLoadingBarProvider.includeSpinner = false; + cfpLoadingBarProvider.latencyThreshold = 1000; }]) - // configure loading bar effect - .config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) { - 'use strict'; - - cfpLoadingBarProvider.includeSpinner = false; - cfpLoadingBarProvider.latencyThreshold = 1000; - }]) - - // configure angular-strap - .config(['$tooltipProvider', function($tooltipProvider) { - 'use strict'; - - angular.extend($tooltipProvider.defaults, { - html: true - }); - }]) - - // configure dashing - .config(['dashing.i18n', function(i18n) { - 'use strict'; - - i18n.confirmationYesButtonText = 'OK'; - i18n.confirmationNoButtonText = 'Cancel'; - }]) - - // disable logging for production - .config(['$compileProvider', function($compileProvider) { - 'use strict'; - - $compileProvider.debugInfoEnabled(false); - }]) - - // constants - .constant('conf', { - restapiProtocol: 'v1.0', - restapiRoot: rootPath, - restapiQueryInterval: 3 * 1000, // in milliseconds - restapiQueryTimeout: 30 * 1000, // in milliseconds - restapiTaskLevelMetricsQueryLimit: 100, - loginUrl: rootPath + 'login' - }) - - /* add a retry delay for angular-ui-router, when resolving a data is failed */ - .run(['$rootScope', '$state', 'conf', function($rootScope, $state, conf) { - 'use strict'; - - $rootScope.$on('$stateChangeError', function(event, toState) { - event.preventDefault(); - _.delay($state.go, conf.restapiQueryTimeout, toState); - }); - }]) - - /* enable a health check service */ - .run(['$modal', 'HealthCheckService', 'conf', function($modal, HealthCheckService, conf) { - 'use strict'; - - var dialog = $modal({ - templateUrl: 'views/service_unreachable_notice.html', - backdrop: 'static', - show: false - }); - - var showDialogFn = function() { - dialog.$promise.then(dialog.show); - }; - - var hideDialogFn = function() { - // simply refresh the page, to make sure page status is fresh - location.reload(); - }; - - HealthCheckService.config( - conf.restapiRoot + 'version', - conf.restapiQueryInterval, - showDialogFn, - hideDialogFn - ); - HealthCheckService.checkForever(); - }]); + // configure angular-strap + .config(['$tooltipProvider', function ($tooltipProvider) { + 'use strict'; + + angular.extend($tooltipProvider.defaults, { + html: true + }); + }]) + + // configure dashing + .config(['dashing.i18n', function (i18n) { + 'use strict'; + + i18n.confirmationYesButtonText = 'OK'; + i18n.confirmationNoButtonText = 'Cancel'; + }]) + + // disable logging for production + .config(['$compileProvider', function ($compileProvider) { + 'use strict'; + + $compileProvider.debugInfoEnabled(false); + }]) + + // constants + .constant('conf', { + restapiProtocol: 'v1.0', + restapiRoot: rootPath, + restapiQueryInterval: 3 * 1000, // in milliseconds + restapiQueryTimeout: 30 * 1000, // in milliseconds + restapiTaskLevelMetricsQueryLimit: 100, + loginUrl: rootPath + 'login' + }) + + /* add a retry delay for angular-ui-router, when resolving a data is failed */ + .run(['$rootScope', '$state', 'conf', function ($rootScope, $state, conf) { + 'use strict'; + + $rootScope.$on('$stateChangeError', function (event, toState) { + event.preventDefault(); + _.delay($state.go, conf.restapiQueryTimeout, toState); + }); + }]) + + /* enable a health check service */ + .run(['$modal', 'HealthCheckService', 'conf', function ($modal, HealthCheckService, conf) { + 'use strict'; + + var dialog = $modal({ + templateUrl: 'views/service_unreachable_notice.html', + backdrop: 'static', + show: false + }); + + var showDialogFn = function () { + dialog.$promise.then(dialog.show); + }; + + var hideDialogFn = function () { + // simply refresh the page, to make sure page status is fresh + location.reload(); + }; + + HealthCheckService.config( + conf.restapiRoot + 'version', + conf.restapiQueryInterval, + showDialogFn, + hideDialogFn + ); + HealthCheckService.checkForever(); + }]); })(); \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/index.html ---------------------------------------------------------------------- diff --git a/services/dashboard/index.html b/services/dashboard/index.html index 26511ec..a312338 100644 --- a/services/dashboard/index.html +++ b/services/dashboard/index.html @@ -4,7 +4,8 @@ <!-- Standard Meta --> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> - <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/> + <meta name="viewport" + content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/> <!-- Site Properties --> <title>Dashboard</title> http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/login/login.html ---------------------------------------------------------------------- diff --git a/services/dashboard/login/login.html b/services/dashboard/login/login.html index d80984d..189ad04 100644 --- a/services/dashboard/login/login.html +++ b/services/dashboard/login/login.html @@ -5,7 +5,8 @@ <!-- Standard Meta --> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> - <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/> + <meta name="viewport" + content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/> <title>Login</title> @@ -83,30 +84,34 @@ <title>Login</title> </head> -<body style="background-color: #555;"> +<body style="background-color: #555;"> <h1 class="icon"><span class="glyphicon glyphicon-th" aria-hidden="true"/></h1> + <h1 class="text-center welcome-message">Sign in to Gearpump</h1> -<a href="../login" id = "loginUrl"></a> -<a href="../logout" id = "logoutUrl"></a> -<a href="../" id = "index"></a> +<a href="../login" id="loginUrl"></a> +<a href="../logout" id="logoutUrl"></a> +<a href="../" id="index"></a> <div class="container"> <div class="row"> <div class="col-md-4 col-md-offset-4 "> <form id="loginForm" class="login-form" method="post"> - <input type="text" class="form-control" name="username" placeholder="User Name" required autofocus /> - <input type="password" class="form-control" name="password" placeholder="Password" required /> - <button class="btn btn-lg btn-primary btn-block" type="button" onclick="login()">Sign In</button> + <input type="text" class="form-control" name="username" placeholder="User Name" required + autofocus/> + <input type="password" class="form-control" name="password" placeholder="Password" + required/> + <button class="btn btn-lg btn-primary btn-block" type="button" onclick="login()">Sign In + </button> <div class="social-login" id="social_login"></div> <div class="error" id="error"></div> <a href="#" class="pull-left" style="margin-top: 15px;"><!--Need help? --></a> - <span class="clearfix" ></span> + <span class="clearfix"></span> </form> </div> </div> http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/login/login.js ---------------------------------------------------------------------- diff --git a/services/dashboard/login/login.js b/services/dashboard/login/login.js index 5a520f9..ffc3cd0 100644 --- a/services/dashboard/login/login.js +++ b/services/dashboard/login/login.js @@ -21,11 +21,11 @@ function login() { $(location).attr('href', index); } ) - .fail(function (xhr, textStatus, errorThrown) { - var elem = $("#error"); - elem.html(xhr.responseText); - elem.text(textStatus + "(" + xhr.status + "): " + elem.text()); - }); + .fail(function (xhr, textStatus, errorThrown) { + var elem = $("#error"); + elem.html(xhr.responseText); + elem.text(textStatus + "(" + xhr.status + "): " + elem.text()); + }); } /** http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/health_check_service.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/health_check_service.js b/services/dashboard/services/health_check_service.js index 2af1fba..d9f5da3 100644 --- a/services/dashboard/services/health_check_service.js +++ b/services/dashboard/services/health_check_service.js @@ -8,25 +8,25 @@ angular.module('dashboard') /** * The service will continuously contact service endpoint. A dialog will be shown, when the service is unreachable. */ - .service('HealthCheckService', ['$http', function($http) { + .service('HealthCheckService', ['$http', function ($http) { 'use strict'; var service = this; service._available = true; - service.config = function(checkUrl, checkInterval, showDialogFn, hideDialogFn) { + service.config = function (checkUrl, checkInterval, showDialogFn, hideDialogFn) { this.checkUrl = checkUrl; this.checkInterval = checkInterval; this.showDialogFn = showDialogFn; this.hideDialogFn = hideDialogFn; }; - service.isServiceAvailable = function() { + service.isServiceAvailable = function () { return service._available; }; - service.checkForever = function() { - var fn = function() { + service.checkForever = function () { + var fn = function () { service._check().finally( function retry() { _.delay(fn, service.checkInterval); @@ -35,7 +35,7 @@ angular.module('dashboard') fn(); }; - service._check = function() { + service._check = function () { return $http.get(service.checkUrl).then( function handleSuccess() { if (!service.isServiceAvailable()) { @@ -48,7 +48,7 @@ angular.module('dashboard') ); }; - service._setServiceAvailable = function(available) { + service._setServiceAvailable = function (available) { service._available = available; if (available) { service.hideDialogFn(); http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/locator.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/locator.js b/services/dashboard/services/locator.js index d855ea4..c034b57 100644 --- a/services/dashboard/services/locator.js +++ b/services/dashboard/services/locator.js @@ -5,18 +5,18 @@ angular.module('dashboard') - /** Routing helper */ - .factory('locator', function() { +/** Routing helper */ + .factory('locator', function () { 'use strict'; var self = { - worker: function(workerId) { + worker: function (workerId) { return '#/cluster/workers/worker/' + workerId; }, - executor: function(appId, appType, executorId) { + executor: function (appId, appType, executorId) { return self.app(appId, appType) + '/executor/' + executorId; }, - app: function(appId, appType) { + app: function (appId, appType) { var prefix = appType === 'streaming' ? 'streaming' : ''; return '#/apps/' + prefix + 'app/' + appId; } http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/login_check.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/login_check.js b/services/dashboard/services/login_check.js index 1d15dc4..66cdedf 100644 --- a/services/dashboard/services/login_check.js +++ b/services/dashboard/services/login_check.js @@ -6,26 +6,26 @@ angular.module('dashboard') // Authentication Angular interceptor for http methods. // If server respond 401 (unauthenticated), will redirect to login page. -.factory('authInterceptor', ['$q', 'conf', function ($q, conf) { + .factory('authInterceptor', ['$q', 'conf', function ($q, conf) { // Defer the error response to caller after this timeout to avoid browser hang issue // See https://github.com/gearpump/gearpump/issues/1855 var deferErrorResponseMs = 3000; return { - 'responseError': function(response) { - if (response.status == 401) { - window.location.href = conf.loginUrl; - } + 'responseError': function (response) { + if (response.status == 401) { + window.location.href = conf.loginUrl; + } - var deferred = $q.defer(); - setTimeout(function() { - deferred.reject(response); - }, 3000); - return deferred.promise; + var deferred = $q.defer(); + setTimeout(function () { + deferred.reject(response); + }, 3000); + return deferred.promise; - } + } }; -}]) -.config(['$httpProvider', function ($httpProvider) { + }]) + .config(['$httpProvider', function ($httpProvider) { $httpProvider.interceptors.push('authInterceptor'); -}]); \ No newline at end of file + }]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/models/dag.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/models/dag.js b/services/dashboard/services/models/dag.js index 876c80c..bff12db 100644 --- a/services/dashboard/services/models/dag.js +++ b/services/dashboard/services/models/dag.js @@ -5,7 +5,7 @@ angular.module('io.gearpump.models') - .service('Dag', function() { + .service('Dag', function () { 'use strict'; /** This class represents a DAG. The topology is immutable after creation. */ @@ -20,50 +20,50 @@ angular.module('io.gearpump.models') Dag.prototype = { /** Indicate whether the topology of specified processors and edges is equal to the current topology. */ - isEqual: function(processors, edges) { + isEqual: function (processors, edges) { return _.isEqual(this.processors, processors) && _.isEqual(this.edges, edges); }, /** Return processor ids as an array. */ - getProcessorIds: function() { + getProcessorIds: function () { return this.sortedProcessorIds; }, /** Return source processor ids as an array. */ - getSourceProcessorIds: function() { - return _.filter(this.getProcessorIds(), function(processorId) { + getSourceProcessorIds: function () { + return _.filter(this.getProcessorIds(), function (processorId) { return this.degrees[processorId].indegree === 0; }, this); }, /** Return sink processor ids as an array. */ - getSinkProcessorIds: function() { - return _.filter(this.getProcessorIds(), function(processorId) { + getSinkProcessorIds: function () { + return _.filter(this.getProcessorIds(), function (processorId) { return this.degrees[processorId].outdegree === 0; }, this); }, /** Return the number of processors on the longest path. */ - hierarchyDepth: function() { + hierarchyDepth: function () { return _.max(_.map(this.processors, 'hierarchy')); }, - _getProcessorIdsByTopologicalOrdering: function() { + _getProcessorIdsByTopologicalOrdering: function () { return _(this.processors).sortBy('hierarchy').map('id').value(); }, - _getPredecessorIds: function() { + _getPredecessorIds: function () { var result = {}; - _.forEach(this.getProcessorIds(), function(processorId) { + _.forEach(this.getProcessorIds(), function (processorId) { result[processorId] = this._calculatePredecessorIds(processorId); }, this); return result; }, - _calculatePredecessorIds: function(processorId) { + _calculatePredecessorIds: function (processorId) { var result = []; - _.forEach(this.edges, function(edge) { + _.forEach(this.edges, function (edge) { if (edge.to === processorId) { result.push(edge.from); } @@ -71,13 +71,13 @@ angular.module('io.gearpump.models') return result; }, - _calculateDegrees: function() { + _calculateDegrees: function () { var result = {}; - _.forEach(this.processors, function(_, key) { + _.forEach(this.processors, function (_, key) { result[key] = {indegree: 0, outdegree: 0}; }); - _.forEach(this.edges, function(edge) { + _.forEach(this.edges, function (edge) { result[edge.from].outdegree++; result[edge.to].indegree++; }); @@ -88,10 +88,10 @@ angular.module('io.gearpump.models') * Return the latency of critical path and all matched paths. * Note that the latency is the sum of all processors on the path. */ - calculateCriticalPathAndLatency: function(metricsProvider, time) { + calculateCriticalPathAndLatency: function (metricsProvider, time) { // calculate independent processor latency var candidates = {}; - _.forEach(this.sortedProcessorIds, function(processorId) { + _.forEach(this.sortedProcessorIds, function (processorId) { candidates[processorId] = { latency: this._getProcessorLatency(processorId, metricsProvider, time), path: [processorId] @@ -99,10 +99,10 @@ angular.module('io.gearpump.models') }, this); // iteratively update processor's latency (and path) by adding its maximal predecessor's latency - _.forEach(this.sortedProcessorIds, function(processorId) { + _.forEach(this.sortedProcessorIds, function (processorId) { var predecessorIds = this.predecessorIds[processorId]; if (predecessorIds.length > 0) { - var maxLatencyPredecessor = _.max(_.map(predecessorIds, function(predecessorId) { + var maxLatencyPredecessor = _.max(_.map(predecessorIds, function (predecessorId) { return candidates[predecessorId]; }), 'latency'); var current = candidates[processorId]; @@ -115,7 +115,7 @@ angular.module('io.gearpump.models') var criticalPathLatency = _.max(_.map(candidates, 'latency')); // find the critical paths - var criticalPaths = _.map(_.pick(candidates, function(candidate) { + var criticalPaths = _.map(_.pick(candidates, function (candidate) { return candidate.latency === criticalPathLatency; }), 'path'); @@ -125,7 +125,7 @@ angular.module('io.gearpump.models') }; }, - _getProcessorLatency: function(processorId, metricsProvider, time) { + _getProcessorLatency: function (processorId, metricsProvider, time) { if (this.processors[processorId].hierarchy === 0) { return 0; // the latency of source process is set to 0 } http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/models/metrics.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/models/metrics.js b/services/dashboard/services/models/metrics.js index ab40556..00b2305 100644 --- a/services/dashboard/services/models/metrics.js +++ b/services/dashboard/services/models/metrics.js @@ -6,23 +6,23 @@ angular.module('io.gearpump.models') /** TODO: to be absorbed as scalajs (#458) */ - .factory('Metrics', [function() { + .factory('Metrics', [function () { 'use strict'; var decoder = { - _common: function(data) { + _common: function (data) { return { meta: decoder._extractPathAndName(data.value.name), time: Number(data.time) }; }, - _extractPathAndName: function(name) { + _extractPathAndName: function (name) { var tuple = name.split(':'); return tuple.length === 2 ? - {path: tuple[0], name: tuple[1]} : - {path: '', name: name}; + {path: tuple[0], name: tuple[1]} : + {path: '', name: name}; }, - meter: function(data) { + meter: function (data) { var result = decoder._common(data); var value = data.value; result.values = { @@ -32,7 +32,7 @@ angular.module('io.gearpump.models') }; return result; }, - histogram: function(data) { + histogram: function (data) { var result = decoder._common(data); var value = data.value; result.values = { @@ -45,14 +45,14 @@ angular.module('io.gearpump.models') }; return result; }, - gauge: function(data) { + gauge: function (data) { var result = decoder._common(data); var value = data.value; result.value = Number(value.value); return result; }, /** automatically guess metric type and decode or return null */ - $auto: function(data) { + $auto: function (data) { switch (data.value.$type) { case 'io.gearpump.metrics.Metrics.Meter': return decoder.meter(data); http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/models/metrics_provider.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/models/metrics_provider.js b/services/dashboard/services/models/metrics_provider.js index 71fc7ab..cddd1f1 100644 --- a/services/dashboard/services/models/metrics_provider.js +++ b/services/dashboard/services/models/metrics_provider.js @@ -5,7 +5,7 @@ angular.module('io.gearpump.models') - .service('MetricsProvider', function() { + .service('MetricsProvider', function () { 'use strict'; /** @@ -22,12 +22,12 @@ angular.module('io.gearpump.models') MetricsProvider.prototype = { /** Add or update metrics to the repository and return the number of updated metrics. */ - update: function(metrics, args) { + update: function (metrics, args) { var that = this; var count = 0; // metrics is {multi-dimension associative array} name -> path -> array of metric - _.forEach(metrics, function(pathAndMetrics, name) { - _.forEach(pathAndMetrics, function(metricArray, path) { + _.forEach(metrics, function (pathAndMetrics, name) { + _.forEach(pathAndMetrics, function (metricArray, path) { if (that.paths.hasOwnProperty(path)) { count += args.latestOnly ? that._updateLatestMetrics(path, name, metricArray) : @@ -38,7 +38,7 @@ angular.module('io.gearpump.models') return count; }, - _updateLatestMetrics: function(path, name, metrics) { + _updateLatestMetrics: function (path, name, metrics) { if (metrics.length > 0) { var metric = _.last(metrics); this._updateMetric(path, name, this.LATEST_METRIC_TIME, metric.values); @@ -49,10 +49,10 @@ angular.module('io.gearpump.models') return 0; }, - _updateMetricsByRetainInterval: function(path, name, metrics, timeResolution) { + _updateMetricsByRetainInterval: function (path, name, metrics, timeResolution) { var count = 0; if (timeResolution > 0) { - _.forEach(metrics, function(metric) { + _.forEach(metrics, function (metric) { var retainIntervalTime = Math.floor(metric.time / timeResolution) * timeResolution; this._updateMetric(path, name, retainIntervalTime, metric.values); count++; @@ -63,7 +63,7 @@ angular.module('io.gearpump.models') return count; }, - _updateMetric: function(path, name, time, values) { + _updateMetric: function (path, name, time, values) { this.data[path] = this.data[path] || {}; this.data[path][name] = this.data[path][name] || {}; this.data[path][name][time] = values; @@ -74,11 +74,11 @@ angular.module('io.gearpump.models') }, /** Return all metric time as an array in ascending order. */ - getMetricTimeArray: function() { + getMetricTimeArray: function () { return _.values(this.timeLookup).sort(); }, - _getMetricFieldOrElse: function(path, name, field, fallback, time) { + _getMetricFieldOrElse: function (path, name, field, fallback, time) { try { return time > 0 ? this.data[path][name][time][field] : @@ -89,17 +89,17 @@ angular.module('io.gearpump.models') }, /** Return the sum of particular metric field of particular processors. */ - getMeterMetricSum: function(paths, name, field, time) { + getMeterMetricSum: function (paths, name, field, time) { var result = this.getMeterMetricSumByFields(paths, name, [field], time); return result[field]; }, /** Return a map of the sum of particular metric fields of particular processors. */ - getMeterMetricSumByFields: function(paths, name, fields, time) { + getMeterMetricSumByFields: function (paths, name, fields, time) { var result = _.zipObject(fields, _.times(fields.length, 0)); var that = this; - _.forEach(paths, function(path) { - _.forEach(fields, function(field) { + _.forEach(paths, function (path) { + _.forEach(fields, function (field) { result[field] += that._getMetricFieldOrElse(path, name, field, 0, time); }); }); @@ -110,9 +110,9 @@ angular.module('io.gearpump.models') * Return the average of particular metric field of particular processors. * Return a fallback value, if no metric value is captured. */ - getHistogramMetricAverageOrElse: function(paths, name, field, fallback, time) { + getHistogramMetricAverageOrElse: function (paths, name, field, fallback, time) { var array = []; - _.forEach(paths, function(path) { + _.forEach(paths, function (path) { var value = this._getMetricFieldOrElse(path, name, field, false, time); if (value !== false) { array.push(value); @@ -125,13 +125,13 @@ angular.module('io.gearpump.models') * Batch read particular metric field from the repository and then return a map. The key is metric * time; the value is an array of metric field values or the aggregated field value. */ - getAggregatedMetricsByRetainInterval: function(paths, name, field, options) { + getAggregatedMetricsByRetainInterval: function (paths, name, field, options) { var that = this; var result = {}; - _.forEach(paths, function(path) { + _.forEach(paths, function (path) { var metrics = that._filterMetricsByPathAndName(path, name); - _.forEach(metrics, function(metric, time) { + _.forEach(metrics, function (metric, time) { if (time !== that.LATEST_METRIC_TIME) { result[time] = result[time] || []; if (metric.hasOwnProperty(field)) { @@ -141,14 +141,14 @@ angular.module('io.gearpump.models') }); }); - _.forEach(result, function(array, time) { + _.forEach(result, function (array, time) { result[time] = _.isFunction(options.aggregateFn) ? options.aggregateFn(array) : array; }); return options.unsort ? result : util.keysSortedObject(result); }, - _filterMetricsByPathAndName: function(path, name) { + _filterMetricsByPathAndName: function (path, name) { var match = this.data[path]; if (match && match.hasOwnProperty(name)) { return match[name]; @@ -158,13 +158,13 @@ angular.module('io.gearpump.models') }; var util = { - mean: function(array) { + mean: function (array) { // No idea why there is no Math.mean() or Array.mean() or _.mean() return array.length ? _.sum(array) / array.length : NaN; }, - keysSortedObject: function(object) { + keysSortedObject: function (object) { var result = {}; - _.forEach(_.keys(object).sort(), function(key) { + _.forEach(_.keys(object).sort(), function (key) { result[key] = object[key]; }); return result; http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/models/models.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/models/models.js b/services/dashboard/services/models/models.js index 794f2ce..15755bc 100644 --- a/services/dashboard/services/models/models.js +++ b/services/dashboard/services/models/models.js @@ -7,20 +7,20 @@ angular.module('io.gearpump.models', []) /** TODO: to be absorbed as scalajs */ .factory('models', ['$timeout', 'conf', 'restapi', 'locator', 'StreamingAppDag', 'Metrics', - function($timeout, conf, restapi, locator, StreamingAppDag, Metrics) { + function ($timeout, conf, restapi, locator, StreamingAppDag, Metrics) { 'use strict'; var util = { - usage: function(current, total) { + usage: function (current, total) { return total > 0 ? 100 * current / total : 0; }, - getOrCreate: function(obj, prop, init) { + getOrCreate: function (obj, prop, init) { if (!obj.hasOwnProperty(prop)) { obj[prop] = init; } return obj[prop]; }, - parseIntFromQueryPathTail: function(path) { + parseIntFromQueryPathTail: function (path) { return Number(_.last(path.split('.')).replace(/[^0-9]/g, '')); } }; @@ -33,12 +33,12 @@ angular.module('io.gearpump.models', []) */ function get(path, decodeFn, args) { args = args || {}; - return restapi.get(path).then(function(response) { + return restapi.get(path).then(function (response) { var oldModel; var model = decodeFn(response.data, args); - model.$subscribe = function(scope, onData, onError) { - restapi.subscribe(args.pathOverride || path, scope, function(data) { + model.$subscribe = function (scope, onData, onError) { + restapi.subscribe(args.pathOverride || path, scope, function (data) { try { var newModel = decodeFn(data, args); if (!_.isEqual(newModel, oldModel)) { @@ -53,7 +53,7 @@ angular.module('io.gearpump.models', []) }, args.period); }; - model.$data = function() { + model.$data = function () { return _.omit(model, _.isFunction); }; @@ -62,21 +62,21 @@ angular.module('io.gearpump.models', []) } var decoder = { - _asAssociativeArray: function(objs, decodeFn, keyName) { + _asAssociativeArray: function (objs, decodeFn, keyName) { var result = {}; - _.map(objs, function(obj) { + _.map(objs, function (obj) { var model = decodeFn(obj); var key = model[keyName]; result[key] = model; }); return result; }, - _akkaAddr: function(actorPath) { + _akkaAddr: function (actorPath) { return actorPath .split('@')[1] .split('/')[0]; }, - _jvm: function(s) { + _jvm: function (s) { var tuple = s.split('@'); return { pid: tuple[0], @@ -84,11 +84,11 @@ angular.module('io.gearpump.models', []) }; }, /** Do the necessary deserialization. */ - master: function(wrapper) { + master: function (wrapper) { var obj = wrapper.masterDescription; angular.merge(obj, { // upickle conversion - cluster: _.map(obj.cluster, function(node) { + cluster: _.map(obj.cluster, function (node) { return node.host + ":" + node.port; }), jvm: decoder._jvm(obj.jvmName), @@ -99,13 +99,13 @@ angular.module('io.gearpump.models', []) }); return obj; }, - partitioners: function(wrapper) { + partitioners: function (wrapper) { return wrapper.partitioners; }, - workers: function(objs) { + workers: function (objs) { return decoder._asAssociativeArray(objs, decoder.worker, 'workerId'); }, - worker: function(obj) { + worker: function (obj) { var slotsUsed = obj.totalSlots - obj.availableSlots; return angular.merge(obj, { // extra properties @@ -122,14 +122,14 @@ angular.module('io.gearpump.models', []) configLink: restapi.workerConfigLink(obj.workerId) }); }, - supervisor: function(obj) { + supervisor: function (obj) { return obj; }, - apps: function(wrapper) { + apps: function (wrapper) { var objs = wrapper.appMasters; return decoder._asAssociativeArray(objs, decoder.appSummary, 'appId'); }, - appSummary: function(obj) { + appSummary: function (obj) { // todo: add `type` field to summary and detailed app response angular.merge(obj, { type: 'streaming' @@ -142,15 +142,15 @@ angular.module('io.gearpump.models', []) // extra methods pageUrl: locator.app(obj.appId, obj.type), configLink: restapi.appConfigLink(obj.appId), - terminate: function() { + terminate: function () { return restapi.killApp(obj.appId); }, - restart: function() { + restart: function () { return restapi.restartAppAsync(obj.appId); } }); }, - app: function(obj) { + app: function (obj) { // todo: add `type` field to summary and detailed app response angular.merge(obj, { status: 'active', @@ -166,7 +166,7 @@ angular.module('io.gearpump.models', []) // upickle conversion 1: streaming app related decoding obj.processors = _.zipObject(obj.processors); - _.forEach(obj.processors, function(processor) { + _.forEach(obj.processors, function (processor) { // add an active property var active = true; var replaced = false; @@ -180,14 +180,14 @@ angular.module('io.gearpump.models', []) processor.active = active; processor.replaced = replaced; }); - _.forEach(_.zipObject(obj.processorLevels), function(hierarchy, processorId) { + _.forEach(_.zipObject(obj.processorLevels), function (hierarchy, processorId) { obj.processors[processorId].hierarchy = hierarchy; }); delete obj.processorLevels; if (obj.dag && Array.isArray(obj.dag.edgeList)) { var edges = {}; - _.forEach(obj.dag.edgeList, function(tuple) { + _.forEach(obj.dag.edgeList, function (tuple) { var from = parseInt(tuple[0]); var to = parseInt(tuple[2]); var partitionerClass = tuple[1]; @@ -204,7 +204,7 @@ angular.module('io.gearpump.models', []) obj.executors = _.object(_.map(obj.executors, 'executorId'), obj.executors); // upickle conversion 2b: add extra executor properties and methods - _.forEach(obj.executors, function(executor) { + _.forEach(obj.executors, function (executor) { angular.merge(executor, { isRunning: executor.status === 'active', pageUrl: locator.executor(obj.appId, obj.type, executor.executorId), @@ -213,10 +213,10 @@ angular.module('io.gearpump.models', []) }); // upickle conversion 2c: task count is executor specific property for streaming app - _.forEach(obj.processors, function(processor) { + _.forEach(obj.processors, function (processor) { var taskCountLookup = _.zipObject(processor.taskCount); // Backend returns executor ids, but names as `executor`. We change them to real executors. - processor.executors = _.map(processor.executors, function(executorId) { + processor.executors = _.map(processor.executors, function (executorId) { var executor = obj.executors[executorId]; var processorExecutor = angular.copy(executor); // The task count is for particular processor, so we make a copy processorExecutor.taskCount = taskCountLookup[executorId].count; @@ -232,13 +232,13 @@ angular.module('io.gearpump.models', []) // extra methods pageUrl: locator.app(obj.appId, obj.type), configLink: restapi.appConfigLink(obj.appId), - terminate: function() { + terminate: function () { return restapi.killApp(obj.appId); } }); return obj; }, - appExecutor: function(obj) { + appExecutor: function (obj) { return angular.merge(obj, { // extra properties and methods jvm: decoder._jvm(obj.jvmName), @@ -247,15 +247,15 @@ angular.module('io.gearpump.models', []) }); }, /** Return a map. the key is processor id, the value is an array of its stalling tasks */ - appStallingTasks: function(wrapper) { + appStallingTasks: function (wrapper) { var result = _.groupBy(wrapper.tasks, 'processorId'); - _.forEach(result, function(processor, processorId) { + _.forEach(result, function (processor, processorId) { result[processorId] = _.map(processor, 'index'); }); return result; }, /** Return an array of application alerts */ - appAlerts: function(obj) { + appAlerts: function (obj) { if (obj.time > 0) { return [{ severity: 'error', @@ -265,7 +265,7 @@ angular.module('io.gearpump.models', []) } return []; }, - metrics: function(wrapper, args) { + metrics: function (wrapper, args) { var metrics = decoder._metricsGroups(wrapper); // Reduce nested array by one level, if we want to filter particular search path. if (args.filterPath) { @@ -273,19 +273,19 @@ angular.module('io.gearpump.models', []) } return metrics; }, - appMetrics: function(wrapper, args) { + appMetrics: function (wrapper, args) { var metrics = decoder.metrics(wrapper, args); - return _.mapValues(metrics, function(values) { - return _.transform(values, function(result, metrics, path) { + return _.mapValues(metrics, function (values) { + return _.transform(values, function (result, metrics, path) { var id = util.parseIntFromQueryPathTail(path); result[id] = metrics; }); }); }, - appTaskLatestMetricValues: function(wrapper, args) { + appTaskLatestMetricValues: function (wrapper, args) { var metrics = decoder.metrics(wrapper, args); - return _.mapValues(metrics, function(values) { - return _.transform(values, function(result, metrics, path) { + return _.mapValues(metrics, function (values) { + return _.transform(values, function (result, metrics, path) { var id = util.parseIntFromQueryPathTail(path); result[id] = _.last(metrics).values; }); @@ -297,9 +297,9 @@ angular.module('io.gearpump.models', []) * The 2nd level key is the object path (e.g. master or app0.processor0) * The value is an array of metrics, which are sorted by time. */ - _metricsGroups: function(wrapper) { + _metricsGroups: function (wrapper) { var result = {}; - _.forEach(wrapper.metrics, function(obj) { + _.forEach(wrapper.metrics, function (obj) { var metric = Metrics.$auto(obj); if (metric) { var metricsGroup = util.getOrCreate(result, metric.meta.name, {}); @@ -311,16 +311,16 @@ angular.module('io.gearpump.models', []) // Remove duplicates and sort metrics by time defensively // https://github.com/gearpump/gearpump/issues/1385 - _.forEach(result, function(metricsGroup) { - _.forEach(metricsGroup, function(metricSeries, path) { + _.forEach(result, function (metricsGroup) { + _.forEach(metricsGroup, function (metricSeries, path) { metricsGroup[path] = _.sortBy(metricSeries, 'time'); }); }); return result; }, /** Remove related metrics paths and change the given 2d array to 1d. */ - _removeUnrelatedMetricsFrom2dArray: function(metrics, filterPath) { - _.forEach(metrics, function(metricsGroup, name) { + _removeUnrelatedMetricsFrom2dArray: function (metrics, filterPath) { + _.forEach(metrics, function (metricsGroup, name) { if (metricsGroup.hasOwnProperty(filterPath)) { metrics[name] = metricsGroup[filterPath]; } else { @@ -331,103 +331,103 @@ angular.module('io.gearpump.models', []) }; var getter = { - master: function() { + master: function () { return get('master', decoder.master); }, - masterMetrics: function(updateInterval) { + masterMetrics: function (updateInterval) { return getter._masterMetrics({period: updateInterval}); }, - masterHistMetrics: function() { + masterHistMetrics: function () { return getter._masterMetrics({all: true}); }, - _masterMetrics: function(args) { + _masterMetrics: function (args) { return getter._metrics('master/metrics/', 'master', args); }, - partitioners: function() { + partitioners: function () { return get('master/partitioners', decoder.partitioners); }, - workers: function() { + workers: function () { return get('master/workerlist', decoder.workers); }, - worker: function(workerId) { + worker: function (workerId) { return get('worker/' + workerId, decoder.worker); }, - workerMetrics: function(workerId, updateInterval) { + workerMetrics: function (workerId, updateInterval) { return getter._workerMetrics(workerId, {period: updateInterval}); }, - workerHistMetrics: function(workerId) { + workerHistMetrics: function (workerId) { return getter._workerMetrics(workerId, {all: true}); }, - _workerMetrics: function(workerId, args) { + _workerMetrics: function (workerId, args) { return getter._metrics('worker/' + workerId + '/metrics/', 'worker' + workerId, args); }, - supervisor: function() { + supervisor: function () { return get('supervisor', decoder.supervisor); }, - apps: function() { + apps: function () { return get('master/applist', decoder.apps); }, - app: function(appId) { + app: function (appId) { return get('appmaster/' + appId + '?detail=true', decoder.app); }, /** Note that executor related metrics will be excluded. */ - appMetrics: function(appId, updateInterval) { + appMetrics: function (appId, updateInterval) { return getter._appMetrics(appId, {period: updateInterval}); }, - appHistMetrics: function(appId) { + appHistMetrics: function (appId) { return getter._appMetrics(appId, {all: true}); }, - appLatestMetrics: function(appId) { + appLatestMetrics: function (appId) { return getter._appMetrics(appId, {all: 'latest'}); }, - _appMetrics: function(appId, args) { + _appMetrics: function (appId, args) { args.aggregator = 'io.gearpump.streaming.metrics.ProcessorAggregator'; args.decoder = decoder.appMetrics; return getter._metrics('appmaster/' + appId + '/metrics/app' + appId, '', args); }, - appTaskLatestMetricValues: function(appId, processorId, metricName, range) { + appTaskLatestMetricValues: function (appId, processorId, metricName, range) { var taskRangeArgs = range && range.hasOwnProperty('start') ? - '&startTask=' + range.start + '&endTask=' + (range.stop + 1) : ''; + '&startTask=' + range.start + '&endTask=' + (range.stop + 1) : ''; var args = { all: 'latest', aggregator: 'io.gearpump.streaming.metrics.TaskFilterAggregator' + - '&startProcessor=' + processorId + '&endProcessor=' + (processorId + 1) + taskRangeArgs, + '&startProcessor=' + processorId + '&endProcessor=' + (processorId + 1) + taskRangeArgs, decoder: decoder.appTaskLatestMetricValues }; metricName = metricName ? ':' + metricName : ''; return getter._metrics('appmaster/' + appId + '/metrics/app' + appId + '.processor' + processorId + '.*' + metricName, '', args); }, - appExecutor: function(appId, executorId) { + appExecutor: function (appId, executorId) { return get('appmaster/' + appId + '/executor/' + executorId, decoder.appExecutor); }, - appExecutorMetrics: function(appId, executorId, updateInterval) { + appExecutorMetrics: function (appId, executorId, updateInterval) { return getter._appExecutorMetrics(appId, executorId, {period: updateInterval}); }, - appExecutorHistMetrics: function(appId, executorId) { + appExecutorHistMetrics: function (appId, executorId) { return getter._appExecutorMetrics(appId, executorId, {all: true}); }, - _appExecutorMetrics: function(appId, executorId, args) { + _appExecutorMetrics: function (appId, executorId, args) { return getter._metrics( 'appmaster/' + appId + '/metrics/', 'app' + appId + '.executor' + executorId, args); }, - appStallingTasks: function(appId) { + appStallingTasks: function (appId) { return get('appmaster/' + appId + '/stallingtasks', decoder.appStallingTasks); }, - appAlerts: function(appId) { + appAlerts: function (appId) { return get('appmaster/' + appId + '/errors', decoder.appAlerts); }, - _metrics: function(pathPrefix, path, args) { + _metrics: function (pathPrefix, path, args) { args = args || {}; var aggregatorArg = angular.isString(args.aggregator) ? ('&aggregator=' + args.aggregator) : ''; @@ -445,10 +445,10 @@ angular.module('io.gearpump.models', []) return { $get: getter, /** Attempts to get model and then subscribe changes as long as the scope is valid. */ - $subscribe: function(scope, getModelFn, onData, period) { + $subscribe: function (scope, getModelFn, onData, period) { var shouldCancel = false; var promise; - scope.$on('$destroy', function() { + scope.$on('$destroy', function () { shouldCancel = true; $timeout.cancel(promise); }); @@ -456,9 +456,9 @@ angular.module('io.gearpump.models', []) if (shouldCancel) { return; } - getModelFn().then(function(data) { + getModelFn().then(function (data) { return onData(data); - }, /*onerror=*/function() { + }, /*onerror=*/function () { promise = $timeout(trySubscribe, period || conf.restapiQueryInterval); }); } @@ -466,26 +466,26 @@ angular.module('io.gearpump.models', []) trySubscribe(); }, // TODO: scalajs should return a app.details object with dag, if it is a streaming application. - createDag: function(clock, processors, edges) { + createDag: function (clock, processors, edges) { var dag = new StreamingAppDag(clock, processors, edges); dag.replaceProcessor = restapi.replaceDagProcessor; return dag; }, /** Submit a DAG along with jar files */ - submitDag: function(files, dag, onComplete) { + submitDag: function (files, dag, onComplete) { if (Object.keys(files).length !== 1) { return onComplete({success: false, message: 'One jar file is expected'}); } files = _.values(files)[0]; // todo: only one file can be uploaded once (issue 1450) - return restapi.uploadJars(files, function(response) { + return restapi.uploadJars(files, function (response) { if (!response.success) { return onComplete(response); } // todo: cannot set jar for individual processor - angular.forEach(dag.processors, function(elem) { + angular.forEach(dag.processors, function (elem) { elem[1].jar = response.files; }); - return restapi.submitDag(dag, function(response) { + return restapi.submitDag(dag, function (response) { return onComplete(response); }); }); http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/models/streamingapp_dag.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/models/streamingapp_dag.js b/services/dashboard/services/models/streamingapp_dag.js index 1fa220f..7fd5800 100644 --- a/services/dashboard/services/models/streamingapp_dag.js +++ b/services/dashboard/services/models/streamingapp_dag.js @@ -5,7 +5,7 @@ angular.module('io.gearpump.models') - .service('StreamingAppDag', ['Dag', 'StreamingAppMetricsProvider', function(Dag, StreamingAppMetricsProvider) { + .service('StreamingAppDag', ['Dag', 'StreamingAppMetricsProvider', function (Dag, StreamingAppMetricsProvider) { 'use strict'; /** @@ -23,7 +23,7 @@ angular.module('io.gearpump.models') StreamingAppDag.prototype = { /** Set the current dag data */ - setData: function(clock, processors, edges) { + setData: function (clock, processors, edges) { this.clock = clock; // The physical view contains all the processors of the application, even those dead processors. // The logical view contains only the alive processors. Once processors or edges are changed, we @@ -38,12 +38,12 @@ angular.module('io.gearpump.models') } }, - setStallingTasks: function(tasks) { + setStallingTasks: function (tasks) { this.stallingTasks = tasks; }, /** Update (or add) a set of latest metrics. */ - updateLatestMetrics: function(metrics) { + updateLatestMetrics: function (metrics) { var count = this.metricsProvider.updateLatestMetrics(metrics); if (count > 0) { // advance the metric update time so that view can subscribe metric changes @@ -52,7 +52,7 @@ angular.module('io.gearpump.models') }, /** Replace existing historical metrics with new data. */ - replaceHistoricalMetrics: function(metrics, timeResolution) { + replaceHistoricalMetrics: function (metrics, timeResolution) { // as the metrics can be application wide or processor wide, to be perfectly clean, we store // historical metrics in a separate metrics provider var processorIds = this.dagPhysicalView.getProcessorIds(); @@ -61,28 +61,28 @@ angular.module('io.gearpump.models') }, /** Return the number of current active processors. */ - getProcessorCount: function() { + getProcessorCount: function () { return this.dagLogicalView.getProcessorIds().length; }, /** Return the processor object. */ - getProcessor: function(processorId) { + getProcessor: function (processorId) { return this.dagPhysicalView.processors[processorId]; }, /** Return the logical view of dag with weighted information for drawing a DAG graph. */ - getWeightedDagView: function() { + getWeightedDagView: function () { var viewProvider = this.dagLogicalView; var processors = viewProvider.processors; var edges = viewProvider.edges; var weights = {}; - _.forEach(processors, function(processor) { + _.forEach(processors, function (processor) { weights[processor.id] = this._calculateProcessorWeight(processor.id); }, this); var bandwidths = {}; - _.forEach(edges, function(edge, key) { + _.forEach(edges, function (edge, key) { bandwidths[key] = this._calculateEdgeBandwidth(edge); }, this); @@ -96,7 +96,7 @@ angular.module('io.gearpump.models') }, /** Weight of a processor equals the sum of its send throughput and receive throughput. */ - _calculateProcessorWeight: function(processorId) { + _calculateProcessorWeight: function (processorId) { return Math.max( this.metricsProvider.getSendMessageMovingAverage([processorId]), this.metricsProvider.getReceiveMessageMovingAverage([processorId]) @@ -104,7 +104,7 @@ angular.module('io.gearpump.models') }, /** Bandwidth of an edge equals the minimum of average send throughput and average receive throughput. */ - _calculateEdgeBandwidth: function(edge) { + _calculateEdgeBandwidth: function (edge) { var sourceOutdegree = this.dagLogicalView.degrees[edge.from].outdegree; var targetIndegree = this.dagLogicalView.degrees[edge.to].indegree; var sourceSendThroughput = this.metricsProvider.getSendMessageMovingAverage([edge.from]); @@ -116,71 +116,71 @@ angular.module('io.gearpump.models') }, /** Return total received messages and rate of all active sink processors. */ - getSinkProcessorReceivedMessageTotalAndRate: function() { + getSinkProcessorReceivedMessageTotalAndRate: function () { var processorIds = this.dagLogicalView.getSinkProcessorIds(); return this.metricsProvider.getReceiveMessageTotalAndRate(processorIds); }, /** Return total received messages and rate of particular processor. */ - getProcessorReceivedMessages: function(processorId) { + getProcessorReceivedMessages: function (processorId) { return this.metricsProvider.getReceiveMessageTotalAndRate([processorId]); }, /** Return total sent messages and rate of all active source processors. */ - getSourceProcessorSentMessageTotalAndRate: function() { + getSourceProcessorSentMessageTotalAndRate: function () { var processorIds = this.dagLogicalView.getSourceProcessorIds(); return this.metricsProvider.getSendMessageTotalAndRate(processorIds); }, /** Return total sent messages and rate of particular processor. */ - getProcessorSentMessages: function(processorId) { + getProcessorSentMessages: function (processorId) { return this.metricsProvider.getSendMessageTotalAndRate([processorId]); }, /** Return the latency on critical path. */ - getCriticalPathLatency: function() { + getCriticalPathLatency: function () { var criticalPathAndLatency = this.dagLogicalView.calculateCriticalPathAndLatency(this.metricsProvider); return criticalPathAndLatency.latency; }, /** Return the average message processing time of particular processor. */ - getProcessorAverageMessageProcessingTime: function(processorId) { + getProcessorAverageMessageProcessingTime: function (processorId) { return this.metricsProvider.getAverageMessageProcessingTime([processorId]); }, /** Return the average message receive latency of particular processor or the latency on critical path. */ - getProcessorMessageReceiveLatency: function(processorId) { + getProcessorMessageReceiveLatency: function (processorId) { return this.metricsProvider.getAverageMessageReceiveLatency([processorId]); }, /** Return the historical message receive throughput of data sink processors as an array. */ - getSinkProcessorHistoricalMessageReceiveThroughput: function() { + getSinkProcessorHistoricalMessageReceiveThroughput: function () { var processorIds = this.dagPhysicalView.getSinkProcessorIds(); return this.histMetricsProvider.getReceiveMessageThroughputByRetainInterval(processorIds); }, /** Return the historical message receive throughput of particular processor as an array. */ - getProcessorHistoricalMessageReceiveThroughput: function(processorId) { + getProcessorHistoricalMessageReceiveThroughput: function (processorId) { return this.histMetricsProvider.getReceiveMessageThroughputByRetainInterval([processorId]); }, /** Return the historical message send throughput of data sink processors as an array. */ - getSourceProcessorHistoricalMessageSendThroughput: function() { + getSourceProcessorHistoricalMessageSendThroughput: function () { var processorIds = this.dagPhysicalView.getSourceProcessorIds(); return this.histMetricsProvider.getSendMessageThroughputByRetainInterval(processorIds); }, /** Return the historical message send throughput of particular processor as an array. */ - getProcessorHistoricalMessageSendThroughput: function(processorId) { + getProcessorHistoricalMessageSendThroughput: function (processorId) { return this.histMetricsProvider.getSendMessageThroughputByRetainInterval([processorId]); }, /** Return the historical message receive latency on critical path as an array. */ - getHistoricalCriticalPathLatency: function() { + getHistoricalCriticalPathLatency: function () { var provider = this.histMetricsProvider; var metricTimeArray = provider.getMetricTimeArray(); var result = {}; - _.forEach(metricTimeArray, function(time) { + _.forEach(metricTimeArray, function (time) { var criticalPathAndLatency = this.dagPhysicalView.calculateCriticalPathAndLatency(provider, time); result[time] = criticalPathAndLatency.latency; }, this); @@ -188,27 +188,27 @@ angular.module('io.gearpump.models') }, /** Return the historical average message processing time of particular processor as an array. */ - getProcessorHistoricalAverageMessageProcessingTime: function(processorId) { + getProcessorHistoricalAverageMessageProcessingTime: function (processorId) { return this.histMetricsProvider.getAverageMessageProcessingTimeByRetainInterval([processorId]); }, /** Return the historical average message receive latency of particular processor. */ - getProcessorHistoricalAverageMessageReceiveLatency: function(processorId) { + getProcessorHistoricalAverageMessageReceiveLatency: function (processorId) { return this.histMetricsProvider.getAverageMessageReceiveLatencyByRetainInterval([processorId]); }, /** Return an array of all processors' metrics of particular metric name. */ - getMetricsByMetricName: function(name) { + getMetricsByMetricName: function (name) { return this.metricsProvider.getMetricsByMetricName(name); }, /** Return the logical indegree and outdegree of a processor. */ - getProcessorIndegreeAndOutdegree: function(processorId) { + getProcessorIndegreeAndOutdegree: function (processorId) { return this.dagLogicalView.degrees[processorId]; }, /** Return the number of processors on the longest alive path. */ - hierarchyDepth: function() { + hierarchyDepth: function () { return this.dagLogicalView.hierarchyDepth(); } @@ -216,14 +216,14 @@ angular.module('io.gearpump.models') /** static method */ function filterActiveProcessors(processors) { - return _.pick(processors, function(processor) { + return _.pick(processors, function (processor) { return processor.active; }); } /** static method */ function filterRelatedEdges(edges, processors) { - return _.pick(edges, function(edge) { + return _.pick(edges, function (edge) { return processors.hasOwnProperty(edge.from) && processors.hasOwnProperty(edge.to); }); http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/models/streamingapp_metrics_provider.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/models/streamingapp_metrics_provider.js b/services/dashboard/services/models/streamingapp_metrics_provider.js index 5f9795b..2a9f655 100644 --- a/services/dashboard/services/models/streamingapp_metrics_provider.js +++ b/services/dashboard/services/models/streamingapp_metrics_provider.js @@ -5,7 +5,7 @@ angular.module('io.gearpump.models') - .service('StreamingAppMetricsProvider', ['MetricsProvider', function(MetricsProvider) { + .service('StreamingAppMetricsProvider', ['MetricsProvider', function (MetricsProvider) { 'use strict'; /** This repository stores streaming app related metrics. */ @@ -16,7 +16,7 @@ angular.module('io.gearpump.models') StreamingAppMetricsProvider.prototype = { /** Add metrics or update to the latest value and return the number of updated metrics. */ - updateLatestMetrics: function(metrics) { + updateLatestMetrics: function (metrics) { return this.impl.update(metrics, {latestOnly: true}); }, @@ -24,26 +24,26 @@ angular.module('io.gearpump.models') * Add all metrics to a multiple dimension associative array and return the number of updated metrics. * Note that every metric will be stored only once and the metric time is the closest retain interval. */ - updateAllMetricsByRetainInterval: function(metrics, timeResolution) { + updateAllMetricsByRetainInterval: function (metrics, timeResolution) { return this.impl.update(metrics, {latestOnly: false, timeResolution: timeResolution}); }, /** Return all metric time as an array in ascending order. */ - getMetricTimeArray: function() { + getMetricTimeArray: function () { return this.impl.getMetricTimeArray(); }, /** Return total and moving average received messages of one or more processors */ - getReceiveMessageTotalAndRate: function(ids, time) { + getReceiveMessageTotalAndRate: function (ids, time) { return this._getMeterMetricsTotalAndRate(ids, 'receiveThroughput', time); }, /** Return total and moving average sent messages of one or more processors */ - getSendMessageTotalAndRate: function(ids, time) { + getSendMessageTotalAndRate: function (ids, time) { return this._getMeterMetricsTotalAndRate(ids, 'sendThroughput', time); }, - _getMeterMetricsTotalAndRate: function(ids, name, time) { + _getMeterMetricsTotalAndRate: function (ids, name, time) { var result = this.impl.getMeterMetricSumByFields(ids, name, ['count', 'movingAverage1m'], time); return { total: result.count, @@ -52,25 +52,25 @@ angular.module('io.gearpump.models') }, /** Return moving average received messages of one or more processors */ - getReceiveMessageMovingAverage: function(ids, time) { + getReceiveMessageMovingAverage: function (ids, time) { var field = 'movingAverage1m'; return this.impl.getMeterMetricSumByFields(ids, 'receiveThroughput', [field], time)[field]; }, /** Return moving average sent messages of one or more processors */ - getSendMessageMovingAverage: function(ids, time) { + getSendMessageMovingAverage: function (ids, time) { var field = 'movingAverage1m'; return this.impl.getMeterMetricSumByFields(ids, 'sendThroughput', [field], time)[field]; }, /** Return the average message processing time of one or more processors */ - getAverageMessageProcessingTime: function(ids, time) { + getAverageMessageProcessingTime: function (ids, time) { var fallback = 0; return this.impl.getHistogramMetricAverageOrElse(ids, 'processTime', 'mean', fallback, time); }, /** Return the average message receive latency of one or more processors */ - getAverageMessageReceiveLatency: function(ids, time) { + getAverageMessageReceiveLatency: function (ids, time) { var fallback = 0; return this.impl.getHistogramMetricAverageOrElse(ids, 'receiveLatency', 'mean', fallback, time); }, @@ -79,7 +79,7 @@ angular.module('io.gearpump.models') * Return an array of message receive throughput of one or more processors, which is * aggregated by retain interval. */ - getReceiveMessageThroughputByRetainInterval: function(ids) { + getReceiveMessageThroughputByRetainInterval: function (ids) { return this.impl.getAggregatedMetricsByRetainInterval(ids, 'receiveThroughput', 'movingAverage1m', {aggregateFn: _.sum}); }, @@ -88,7 +88,7 @@ angular.module('io.gearpump.models') * Return an array of message send throughput of one or more processors, which is aggregated * by retain interval. */ - getSendMessageThroughputByRetainInterval: function(ids) { + getSendMessageThroughputByRetainInterval: function (ids) { return this.impl.getAggregatedMetricsByRetainInterval(ids, 'sendThroughput', 'movingAverage1m', {aggregateFn: _.sum}); }, @@ -97,7 +97,7 @@ angular.module('io.gearpump.models') * Return an array of the average message processing time of one or more processors, which is aggregated * by retain interval. */ - getAverageMessageProcessingTimeByRetainInterval: function(ids) { + getAverageMessageProcessingTimeByRetainInterval: function (ids) { return this.impl.getAggregatedMetricsByRetainInterval(ids, 'processTime', 'mean', {aggregateFn: d3.mean}); }, @@ -106,14 +106,14 @@ angular.module('io.gearpump.models') * Return an array of the average message receive latency of one or more processors, which is aggregated * by retain interval. */ - getAverageMessageReceiveLatencyByRetainInterval: function(ids) { + getAverageMessageReceiveLatencyByRetainInterval: function (ids) { return this.impl.getAggregatedMetricsByRetainInterval(ids, 'receiveLatency', 'mean', {aggregateFn: d3.mean}); }, /** Return an array of processor metrics of particular metric name. */ - getMetricsByMetricName: function(name) { - return _.mapValues(this.impl.data, function(metricsGroups) { + getMetricsByMetricName: function (name) { + return _.mapValues(this.impl.data, function (metricsGroups) { return metricsGroups[name].latest; }); } http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/services/restapi.js ---------------------------------------------------------------------- diff --git a/services/dashboard/services/restapi.js b/services/dashboard/services/restapi.js index 483fcf9..29a1683 100644 --- a/services/dashboard/services/restapi.js +++ b/services/dashboard/services/restapi.js @@ -7,7 +7,7 @@ angular.module('dashboard') /** TODO: refactoring work required */ .factory('restapi', ['$q', '$http', '$timeout', '$modal', 'Upload', 'conf', 'HealthCheckService', - function($q, $http, $timeout, $modal, Upload, conf, HealthCheckService) { + function ($q, $http, $timeout, $modal, Upload, conf, HealthCheckService) { 'use strict'; function decodeSuccessResponse(data) { @@ -32,27 +32,27 @@ angular.module('dashboard') /** * Retrieve data from rest service endpoint (HTTP GET) periodically in an angular scope. */ - subscribe: function(path, scope, onData, interval) { + subscribe: function (path, scope, onData, interval) { var timeoutPromise; var shouldCancel = false; - scope.$on('$destroy', function() { + scope.$on('$destroy', function () { shouldCancel = true; $timeout.cancel(timeoutPromise); }); interval = interval || conf.restapiQueryInterval; - var fn = function() { + var fn = function () { var promise = self.get(path); - promise.then(function(response) { - if (!shouldCancel && angular.isFunction(onData)) { - shouldCancel = onData(response.data); - } - }, function(response) { - if (!shouldCancel && angular.isFunction(onData)) { - shouldCancel = onData(response.data); - } - }) - .finally(function() { + promise.then(function (response) { + if (!shouldCancel && angular.isFunction(onData)) { + shouldCancel = onData(response.data); + } + }, function (response) { + if (!shouldCancel && angular.isFunction(onData)) { + shouldCancel = onData(response.data); + } + }) + .finally(function () { if (!shouldCancel) { timeoutPromise = $timeout(fn, interval); } @@ -67,7 +67,7 @@ angular.module('dashboard') * health check indicates the service is unavailable, no request will be sent to server, just * simple return a failure after a default timeout. */ - get: function(path) { + get: function (path) { if (!HealthCheckService.isServiceAvailable()) { var deferred = $q.defer(); _.delay(deferred.reject, conf.restapiQueryTimeout); @@ -77,59 +77,59 @@ angular.module('dashboard') }, /** Get data from server periodically until an user cancellation or scope exit. */ - repeatUntil: function(url, scope, onData) { + repeatUntil: function (url, scope, onData) { // TODO: Once `subscribe` is turned to websocket push model, there is no need to have this method this.subscribe(url, scope, - function(data) { + function (data) { return !onData || onData(data); }); }, /** Kill a running application */ - killApp: function(appId) { + killApp: function (appId) { var url = restapiV1Root + 'appmaster/' + appId; return $http.delete(url); }, /** Restart a running application and return a promise */ - restartAppAsync: function(appId) { + restartAppAsync: function (appId) { var url = restapiV1Root + 'appmaster/' + appId + '/restart'; return $http.post(url); }, /** Return the config link of an application */ - appConfigLink: function(appId) { + appConfigLink: function (appId) { return restapiV1Root + 'appmaster/' + appId + '/config'; }, /** Return the config link of an application */ - appExecutorConfigLink: function(appId, executorId) { + appExecutorConfigLink: function (appId, executorId) { return restapiV1Root + 'appmaster/' + appId + '/executor/' + executorId + '/config'; }, /** Return the config link of a worker */ - workerConfigLink: function(workerId) { + workerConfigLink: function (workerId) { return restapiV1Root + 'worker/' + workerId + '/config'; }, /** Return the config link of the master */ - masterConfigLink: function() { + masterConfigLink: function () { return restapiV1Root + 'master/config'; }, /** Submit an user defined application with user configuration */ - submitUserApp: function(files, fileFieldNames, executorNum, args, onComplete) { + submitUserApp: function (files, fileFieldNames, executorNum, args, onComplete) { return self._submitApp(restapiV1Root + 'master/submitapp', files, fileFieldNames, executorNum, args, onComplete); }, /** Submit a Storm application */ - submitStormApp: function(files, formFormNames, executorNum, args, onComplete) { + submitStormApp: function (files, formFormNames, executorNum, args, onComplete) { return self._submitApp(restapiV1Root + 'master/submitstormapp', files, formFormNames, executorNum, args, onComplete); }, - _submitApp: function(url, files, fileFieldNames, executorNum, args, onComplete) { + _submitApp: function (url, files, fileFieldNames, executorNum, args, onComplete) { var upload = Upload.upload({ url: url, method: 'POST', @@ -141,12 +141,12 @@ angular.module('dashboard') } }); - upload.then(function(response) { + upload.then(function (response) { if (onComplete) { var data = response.data; onComplete({success: data && data.success}); } - }, function(response) { + }, function (response) { if (onComplete) { onComplete(decodeErrorResponse(response.data)); } @@ -154,13 +154,13 @@ angular.module('dashboard') }, /** Submit an user defined application with user configuration */ - submitDag: function(args, onComplete) { + submitDag: function (args, onComplete) { var url = restapiV1Root + 'master/submitdag'; - return $http.post(url, args).then(function(response) { + return $http.post(url, args).then(function (response) { if (onComplete) { onComplete(decodeSuccessResponse(response.data)); } - }, function(response) { + }, function (response) { if (onComplete) { onComplete(decodeErrorResponse(response.data)); } @@ -168,7 +168,7 @@ angular.module('dashboard') }, /** Upload a set of JAR files */ - uploadJars: function(files, onComplete) { + uploadJars: function (files, onComplete) { var upload = Upload.upload({ url: restapiV1Root + 'master/uploadjar', method: 'POST', @@ -176,11 +176,11 @@ angular.module('dashboard') fileFormDataName: 'jar' }); - upload.then(function(response) { + upload.then(function (response) { if (onComplete) { onComplete(decodeSuccessResponse({files: response.data})); } - }, function(response) { + }, function (response) { if (onComplete) { onComplete(decodeErrorResponse(response.data)); } @@ -188,14 +188,14 @@ angular.module('dashboard') }, /** Add a new worker */ - addWorker: function(onComplete) { + addWorker: function (onComplete) { var count = 1; var url = restapiV1Root + 'supervisor/addworker/' + count; - return $http.post(url).then(function(response) { + return $http.post(url).then(function (response) { if (angular.isFunction(onComplete)) { onComplete(decodeSuccessResponse(response.data)); } - }, function(response) { + }, function (response) { if (angular.isFunction(onComplete)) { onComplete(decodeErrorResponse(response.data)); } @@ -203,13 +203,13 @@ angular.module('dashboard') }, /** Remove a new worker */ - removeWorker: function(workerId, onComplete) { + removeWorker: function (workerId, onComplete) { var url = restapiV1Root + 'supervisor/removeworker/' + workerId; - return $http.post(url).then(function(response) { + return $http.post(url).then(function (response) { if (angular.isFunction(onComplete)) { onComplete(decodeSuccessResponse(response.data)); } - }, function(response) { + }, function (response) { if (angular.isFunction(onComplete)) { onComplete(decodeErrorResponse(response.data)); } @@ -217,7 +217,7 @@ angular.module('dashboard') }, /** Replace a dag processor at runtime */ - replaceDagProcessor: function(files, formFormNames, appId, oldProcessorId, newProcessorDescription, onComplete) { + replaceDagProcessor: function (files, formFormNames, appId, oldProcessorId, newProcessorDescription, onComplete) { var url = restapiV1Root + 'appmaster/' + appId + '/dynamicdag'; var args = { "$type": 'io.gearpump.streaming.appmaster.DagManager.ReplaceProcessor', @@ -229,7 +229,7 @@ angular.module('dashboard') url += '?args=' + encodeURIComponent(angular.toJson(args)); var promise; - var filtered = _.filter(files, function(file) { + var filtered = _.filter(files, function (file) { return file; }); if (filtered.length) { @@ -243,11 +243,11 @@ angular.module('dashboard') promise = $http.post(url); } - promise.then(function() { + promise.then(function () { if (onComplete) { onComplete({success: true}); } - }, function(response) { + }, function (response) { if (onComplete) { onComplete({success: false, reason: response.data}); } @@ -255,8 +255,8 @@ angular.module('dashboard') }, /** Return the service version in onData callback */ - serviceVersion: function(onData) { - return $http.get(conf.restapiRoot + 'version').then(function(response) { + serviceVersion: function (onData) { + return $http.get(conf.restapiRoot + 'version').then(function (response) { if (angular.isFunction(onData)) { onData(response.data); } http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/styles/dashboard.css ---------------------------------------------------------------------- diff --git a/services/dashboard/styles/dashboard.css b/services/dashboard/styles/dashboard.css index 8062959..32a52b3 100644 --- a/services/dashboard/styles/dashboard.css +++ b/services/dashboard/styles/dashboard.css @@ -77,13 +77,21 @@ h4, table > caption { } @-webkit-keyframes spin2 { - from { -webkit-transform: rotate(0deg); } - to { -webkit-transform: rotate(360deg); } + from { + -webkit-transform: rotate(0deg); + } + to { + -webkit-transform: rotate(360deg); + } } @keyframes spin { - from { transform: scale(1) rotate(0deg); } - to { transform: scale(1) rotate(360deg); } + from { + transform: scale(1) rotate(0deg); + } + to { + transform: scale(1) rotate(360deg); + } } /* Help text */ http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/views/apps/app/alerts_table.html ---------------------------------------------------------------------- diff --git a/services/dashboard/views/apps/app/alerts_table.html b/services/dashboard/views/apps/app/alerts_table.html index b545165..c463be3 100644 --- a/services/dashboard/views/apps/app/alerts_table.html +++ b/services/dashboard/views/apps/app/alerts_table.html @@ -1,8 +1,8 @@ -<sortable-table - caption="Alerts" - columns-bind="table.cols" records-bind="table.rows" pagination="4"> - <div class="table-no-data-sm"> - <h5><span class="glyphicon glyphicon-bullhorn"></span> - No alert reported so far</h5> - </div> +<sortable-table + caption="Alerts" + columns-bind="table.cols" records-bind="table.rows" pagination="4"> + <div class="table-no-data-sm"> + <h5><span class="glyphicon glyphicon-bullhorn"></span> + No alert reported so far</h5> + </div> </sortable-table> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/views/apps/app/alerts_table.js ---------------------------------------------------------------------- diff --git a/services/dashboard/views/apps/app/alerts_table.js b/services/dashboard/views/apps/app/alerts_table.js index 86bf3b1..014f396 100644 --- a/services/dashboard/views/apps/app/alerts_table.js +++ b/services/dashboard/views/apps/app/alerts_table.js @@ -5,7 +5,7 @@ angular.module('dashboard') - .directive('alertsTable', function() { + .directive('alertsTable', function () { 'use strict'; return { @@ -16,7 +16,7 @@ angular.module('dashboard') alerts: '=alertsBind' }, controller: ['$scope', '$sortableTableBuilder', - function($scope, $stb) { + function ($scope, $stb) { $scope.table = { cols: [ $stb.indicator().key('severity').canSort().styleClass('td-no-padding').done(), @@ -33,7 +33,7 @@ angular.module('dashboard') function updateTable(alerts) { $scope.table.rows = $stb.$update($scope.table.rows, - _.map(alerts, function(alert) { + _.map(alerts, function (alert) { var severity = severityLookup[alert.severity]; return { severity: { @@ -47,7 +47,7 @@ angular.module('dashboard') })); } - $scope.$watch('alerts', function(alerts) { + $scope.$watch('alerts', function (alerts) { updateTable(alerts); }); }] http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/views/apps/app/app.js ---------------------------------------------------------------------- diff --git a/services/dashboard/views/apps/app/app.js b/services/dashboard/views/apps/app/app.js index 6372756..911e480 100644 --- a/services/dashboard/views/apps/app/app.js +++ b/services/dashboard/views/apps/app/app.js @@ -6,7 +6,7 @@ angular.module('dashboard') .config(['$stateProvider', - function($stateProvider) { + function ($stateProvider) { 'use strict'; $stateProvider @@ -16,7 +16,7 @@ angular.module('dashboard') templateUrl: 'views/apps/app/app.html', controller: 'AppCtrl', resolve: { - app0: ['$stateParams', 'models', function($stateParams, models) { + app0: ['$stateParams', 'models', function ($stateParams, models) { return models.$get.app($stateParams.appId); }] } @@ -27,11 +27,11 @@ angular.module('dashboard') * This controller is used to obtain app. All nested views will read status from here. */ .controller('AppCtrl', ['$scope', 'app0', - function($scope, app0) { + function ($scope, app0) { 'use strict'; $scope.app = app0.$data(); - app0.$subscribe($scope, function(app) { + app0.$subscribe($scope, function (app) { $scope.app = app; }); }]) http://git-wip-us.apache.org/repos/asf/incubator-gearpump/blob/c176e448/services/dashboard/views/apps/app/executors_table.html ---------------------------------------------------------------------- diff --git a/services/dashboard/views/apps/app/executors_table.html b/services/dashboard/views/apps/app/executors_table.html index e7ca23c..ca58145 100644 --- a/services/dashboard/views/apps/app/executors_table.html +++ b/services/dashboard/views/apps/app/executors_table.html @@ -1,5 +1,5 @@ -<sortable-table - caption="Executors" - caption-tooltip="{{whatIsExecutor}}" - columns-bind="table.cols" records-bind="table.rows" pagination="4"> +<sortable-table + caption="Executors" + caption-tooltip="{{whatIsExecutor}}" + columns-bind="table.cols" records-bind="table.rows" pagination="4"> </sortable-table> \ No newline at end of file
