Repository: ambari Updated Branches: refs/heads/trunk 12d608141 -> e7643d5eb
AMBARI-10557. Integrate widgets comprising of a specific host component metrics. (jaimin) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e7643d5e Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e7643d5e Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e7643d5e Branch: refs/heads/trunk Commit: e7643d5eb34621c5fb1256aac8625b970c43dc8e Parents: 12d6081 Author: Jaimin Jetly <jai...@hortonworks.com> Authored: Fri Apr 17 12:39:44 2015 -0700 Committer: Jaimin Jetly <jai...@hortonworks.com> Committed: Fri Apr 17 12:39:44 2015 -0700 ---------------------------------------------------------------------- .../common-services/HDFS/2.1.0.2.0/metrics.json | 2 +- .../common-services/HDFS/2.1.0.2.0/widgets.json | 8 +-- ambari-web/app/mixins/common/widget_mixin.js | 71 +++++++++++++++++--- ambari-web/app/utils/ajax/ajax.js | 7 +- .../views/common/widget/graph_widget_view.js | 64 +++++++++++------- .../test/mixins/common/widget_mixin_test.js | 31 ++++++--- 6 files changed, 134 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/e7643d5e/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/metrics.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/metrics.json b/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/metrics.json index 07f36bb..53575de 100644 --- a/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/metrics.json +++ b/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/metrics.json @@ -622,7 +622,7 @@ }, "metrics/dfs/FSNamesystem/UnderReplicatedBlocks": { "metric": "dfs.FSNamesystem.UnderReplicatedBlocks", - "pointInTime": false, + "pointInTime": true, "temporal": true }, "metrics/rpcdetailed/sendHeartbeat_avg_time": { http://git-wip-us.apache.org/repos/asf/ambari/blob/e7643d5e/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/widgets.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/widgets.json b/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/widgets.json index 8332d25..622ee03 100644 --- a/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/widgets.json +++ b/ambari-server/src/main/resources/common-services/HDFS/2.1.0.2.0/widgets.json @@ -209,16 +209,16 @@ "is_visible": true, "metrics": [ { - "name": "Hadoop:service=DataNode,name=DataNode.CorruptBlocks", + "name": "Hadoop:service=NameNode,name=FSNamesystem.CorruptBlocks", "metric_path": "metrics/dfs/FSNamesystem/CorruptBlocks", "service_name": "HDFS", - "component_name": "DATANODE" + "component_name": "NAMENODE" } ], "values": [ { "name": "Corrupted Blocks", - "value": "${Hadoop:service=DataNode,name=DataNode.CorruptBlocks}" + "value": "${Hadoop:service=NameNode,name=FSNamesystem.CorruptBlocks}" } ], "properties": { @@ -234,7 +234,7 @@ "name": "Hadoop:service=NameNode,name=FSNamesystem.UnderReplicatedBlocks", "metric_path": "metrics/dfs/FSNamesystem/UnderReplicatedBlocks", "service_name": "HDFS", - "component_name": "DATANODE" + "component_name": "NAMENODE" } ], "values": [ http://git-wip-us.apache.org/repos/asf/ambari/blob/e7643d5e/ambari-web/app/mixins/common/widget_mixin.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/widget_mixin.js b/ambari-web/app/mixins/common/widget_mixin.js index a9a6d59..35b11b1 100644 --- a/ambari-web/app/mixins/common/widget_mixin.js +++ b/ambari-web/app/mixins/common/widget_mixin.js @@ -36,7 +36,7 @@ App.WidgetMixin = Ember.Mixin.create({ * @type {RegExp} * @const */ - VALUE_NAME_REGEX: /[\w\.\:\=\[\]]+/g, + VALUE_NAME_REGEX: /[\w\.\,\:\=\[\]]+/g, /** * common metrics container @@ -73,7 +73,7 @@ App.WidgetMixin = Ember.Mixin.create({ request = requestData[i]; requestCounter++; if (request.host_component_criteria) { - this.getHostComponentMetrics(request).complete(function () { + this.getHostComponentMetrics(request).always(function () { requestCounter--; if (requestCounter === 0) self.onMetricsLoaded(); }); @@ -92,11 +92,11 @@ App.WidgetMixin = Ember.Mixin.create({ */ getRequestData: function (metrics) { var requestsData = {}; - if (metrics) { metrics.forEach(function (metric, index) { var key; if (metric.host_component_criteria) { + this.tweakHostComponentCriteria(metric); key = metric.service_name + '_' + metric.component_name + '_' + metric.host_component_criteria; } else { key = metric.service_name + '_' + metric.component_name; @@ -116,6 +116,25 @@ App.WidgetMixin = Ember.Mixin.create({ }, /** + * Tweak necessary host component criteria + * NameNode HA host component criteria is applicable only in HA mode + */ + tweakHostComponentCriteria: function (metric) { + switch (metric.component_name) { + case 'NAMENODE': + if (metric.host_component_criteria === 'host_components/metrics/dfs/FSNamesystem/HAState=active') { + //if (metric.host_component_criteria) + var hdfs = App.HDFSService.find().objectAt(0); + var activeNNHostName = !hdfs.get('snameNode') && hdfs.get('activeNameNode'); + if (!activeNNHostName) { + metric.host_component_criteria = 'host_components/HostRoles/component_name=NAMENODE'; + } + } + break; + } + }, + + /** * make GET call to server in order to fetch service-component metrics * @param {object} request * @returns {$.ajax} @@ -134,21 +153,53 @@ App.WidgetMixin = Ember.Mixin.create({ }, /** - * make GET call to server in order to fetch host-component metrics + * make GET call to server in order to fetch service-component metrics * @param {object} request - * @returns {$.ajax} + * @returns {$.Deferred} */ getHostComponentMetrics: function (request) { + var dfd; + var self = this; + dfd = $.Deferred(); + this.getHostComponentName(request).done(function (data) { + if (data) { + request.host_name = data.host_components[0].HostRoles.host_name; + App.ajax.send({ + name: 'widgets.hostComponent.metrics.get', + sender: self, + data: { + componentName: request.component_name, + hostName: request.host_name, + metricPaths: request.metric_paths.join(',') + } + }).done(function(metricData) { + self.getMetricsSuccessCallback(metricData); + dfd.resolve(); + }).fail(function(data){ + dfd.reject(); + }); + } + }).fail(function(data){ + dfd.reject(); + }); + return dfd.promise(); + }, + + /** + * make GET call to server in order to fetch host-component names + * @param {object} request + * @returns {$.ajax} + */ + getHostComponentName: function (request) { return App.ajax.send({ - name: 'widgets.hostComponent.metrics.get', + name: 'widgets.hostComponent.get.hostName', sender: this, data: { serviceName: request.service_name, componentName: request.component_name, metricPaths: request.metric_paths.join(','), - hostComponentCriteria: 'host_components/HostRoles/' + request.host_component_criteria - }, - success: 'getMetricsSuccessCallback' + hostComponentCriteria: request.host_component_criteria + } }); }, @@ -175,7 +226,7 @@ App.WidgetMixin = Ember.Mixin.create({ var self = this; this.set('isLoaded', true); this.drawWidget(); - setTimeout(function() { + setTimeout(function () { self.loadMetrics(); }, App.contentUpdateInterval); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/e7643d5e/ambari-web/app/utils/ajax/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js index d6c735b..1657196 100644 --- a/ambari-web/app/utils/ajax/ajax.js +++ b/ambari-web/app/utils/ajax/ajax.js @@ -2473,8 +2473,13 @@ var urls = { mock: '/data/metrics/{serviceName}/Append_num_ops_&_Delete_num_ops.json' }, + 'widgets.hostComponent.get.hostName': { + real: '/clusters/{clusterName}/services/{serviceName}/components/{componentName}?{hostComponentCriteria}', + mock: '/data/metrics/{serviceName}/Append_num_ops.json' + }, + 'widgets.hostComponent.metrics.get': { - real: '/clusters/{clusterName}/services/{serviceName}/components/{componentName}?{hostComponentCriteria}&fields={metricPaths}', + real: '/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}?fields={metricPaths}', mock: '/data/metrics/{serviceName}/Append_num_ops.json' }, http://git-wip-us.apache.org/repos/asf/ambari/blob/e7643d5e/ambari-web/app/views/common/widget/graph_widget_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/widget/graph_widget_view.js b/ambari-web/app/views/common/widget/graph_widget_view.js index 8baa8cc..9e81eee 100644 --- a/ambari-web/app/views/common/widget/graph_widget_view.js +++ b/ambari-web/app/views/common/widget/graph_widget_view.js @@ -56,20 +56,20 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, { calculateValues: function () { var metrics = this.get('metrics'); var seriesData = []; - if (this.get('content.values')) { - this.get('content.values').forEach(function (value) { - var expression = this.extractExpressions(value)[0]; - var computedExpressions; - - if (expression) { - computedExpressions = this.computeExpression(expression, metrics); - seriesData.push({ - name: value.name, - data: computedExpressions[value.value.match(this.get('EXPRESSION_REGEX'))[0]] - }); - } - }, this); - } + if (this.get('content.values')) { + this.get('content.values').forEach(function (value) { + var expression = this.extractExpressions(value)[0]; + var computedExpressions; + + if (expression) { + computedExpressions = this.computeExpression(expression, metrics); + seriesData.push({ + name: value.name, + data: computedExpressions[value.value.match(this.get('EXPRESSION_REGEX'))[0]] + }); + } + }, this); + } return seriesData; }, @@ -137,17 +137,31 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, { * @returns {$.ajax} */ getHostComponentMetrics: function (request) { - return App.ajax.send({ - name: 'widgets.hostComponent.metrics.get', - sender: this, - data: { - serviceName: request.service_name, - componentName: request.component_name, - metricPaths: this.addTimeProperties(request.metric_paths).join(','), - hostComponentCriteria: 'host_components/HostRoles/' + request.host_component_criteria - }, - success: 'getMetricsSuccessCallback' + var dfd; + var self = this; + dfd = $.Deferred(); + this.getHostComponentName(request).done(function (data) { + if (data) { + request.host_name = data.host_components[0].HostRoles.host_name; + App.ajax.send({ + name: 'widgets.hostComponent.metrics.get', + sender: self, + data: { + componentName: request.component_name, + hostName: request.host_name, + metricPaths: self.addTimeProperties(request.metric_paths).join(',') + } + }).done(function(metricData) { + self.getMetricsSuccessCallback(metricData); + dfd.resolve(); + }).fail(function(data){ + dfd.reject(); + }); + } + }).fail(function(data){ + dfd.reject(); }); + return dfd.promise(); }, /** @@ -197,7 +211,7 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, { transformToSeries: function (seriesData) { var seriesArray = []; - seriesData.forEach(function(_series){ + seriesData.forEach(function (_series) { seriesArray.push(this.transformData(_series.data, _series.name)); }, this); return seriesArray; http://git-wip-us.apache.org/repos/asf/ambari/blob/e7643d5e/ambari-web/test/mixins/common/widget_mixin_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mixins/common/widget_mixin_test.js b/ambari-web/test/mixins/common/widget_mixin_test.js index 9ef82a4..f29eb66 100644 --- a/ambari-web/test/mixins/common/widget_mixin_test.js +++ b/ambari-web/test/mixins/common/widget_mixin_test.js @@ -25,7 +25,7 @@ describe('App.WidgetMixin', function() { var mixinObject = mixinClass.create(); beforeEach(function () { this.mock = sinon.stub(mixinObject, 'getRequestData'); - sinon.stub(mixinObject, 'getHostComponentMetrics').returns({complete: function(callback){ + sinon.stub(mixinObject, 'getHostComponentMetrics').returns({always: function(callback){ callback(); }}); sinon.stub(mixinObject, 'getServiceComponentMetrics').returns({complete: function(callback){ @@ -208,14 +208,31 @@ describe('App.WidgetMixin', function() { describe("#getHostComponentMetrics()", function () { var mixinObject = mixinClass.create(); before(function () { - sinon.stub(App.ajax, 'send'); + sinon.stub(App.ajax, 'send').returns({done: function(callback){ + callback(); + return this; + },fail: function(callback){ + callback(); + return this; + }}); + sinon.stub(mixinObject, 'getHostComponentName').returns({done: function(callback){ + var data = {host_components: [{HostRoles:{host_name:"c6401"}}]}; + callback(data); + return this; + },fail: function(callback){ + callback(); + return this; + }}); + + sinon.stub(mixinObject, 'getMetricsSuccessCallback') }); after(function () { App.ajax.send.restore(); + mixinObject.getHostComponentName.restore(); + mixinObject.getMetricsSuccessCallback.restore(); }); it("", function () { var request = { - service_name: 'S1', component_name: 'C1', metric_paths: ['w1', 'w2'], host_component_criteria: 'c1' @@ -225,12 +242,10 @@ describe('App.WidgetMixin', function() { name: 'widgets.hostComponent.metrics.get', sender: mixinObject, data: { - serviceName: 'S1', componentName: 'C1', - metricPaths: 'w1,w2', - hostComponentCriteria: 'host_components/HostRoles/c1' - }, - success: 'getMetricsSuccessCallback' + hostName: "c6401", + metricPaths: 'w1,w2' + } }) }); });