Bladeren bron

AMBARI-11518. All Yarn NodeManager widgets not getting displayed. (jaimin)

Jaimin Jetly 10 jaren geleden
bovenliggende
commit
4e7a135edf

+ 38 - 6
ambari-web/app/mixins/common/widgets/widget_mixin.js

@@ -20,6 +20,11 @@ var App = require('app');
 
 App.WidgetMixin = Ember.Mixin.create({
 
+  /**
+   *  type of metric query from which the widget is comprised
+   */
+
+  metricType: 'POINT_IN_TIME',
   /**
    * @type {RegExp}
    * @const
@@ -152,9 +157,18 @@ App.WidgetMixin = Ember.Mixin.create({
         var requestMetric = $.extend({}, metric);
 
         if (requestsData[key]) {
-          requestsData[key]["metric_paths"].push(requestMetric["metric_path"]);
+          requestsData[key]["metric_paths"].push({
+            metric_path: requestMetric["metric_path"],
+            metric_type: this.get('metricType'),
+            id: requestMetric["metric_path"] + "_" + this.get('metricType'),
+            context: this
+          });
         } else {
-          requestMetric["metric_paths"] = [requestMetric["metric_path"]];
+          requestMetric["metric_paths"] = [{
+            metric_path: requestMetric["metric_path"],
+            metric_type: this.get('metricType'),
+            id: requestMetric["metric_path"] + "_" + this.get('metricType'),
+            context: this}];
           delete requestMetric["metric_path"];
           requestsData[key] = requestMetric;
         }
@@ -202,11 +216,27 @@ App.WidgetMixin = Ember.Mixin.create({
       data: {
         serviceName: request.service_name,
         componentName: request.component_name,
-        metricPaths: request.metric_paths.join(',')
+        metricPaths: this.prepareMetricPaths(request.metric_paths)
       }
     });
   },
 
+  /**
+   *  aggregate all metric names in the query. Add time range and step to temporal queries
+   */
+  prepareMetricPaths: function(metricPaths) {
+    var temporalMetrics = metricPaths.filterProperty('metric_type', 'TEMPORAL');
+    var pointInTimeMetrics = metricPaths.filterProperty('metric_type', 'POINT_IN_TIME');
+    var result = temporalMetrics.length ? temporalMetrics[0].context.addTimeProperties(temporalMetrics.mapProperty('metric_path')) : [];
+
+    if (pointInTimeMetrics.length) {
+      result = result.concat(pointInTimeMetrics.mapProperty('metric_path'));
+    }
+
+    return result.join(',');
+  },
+
+
   /**
    * make GET call to server in order to fetch specific host-component metrics
    * @param {object} request
@@ -218,7 +248,7 @@ App.WidgetMixin = Ember.Mixin.create({
       sender: this,
       data: {
         componentName: request.component_name,
-        metricPaths: request.metric_paths.join(','),
+        metricPaths: this.prepareMetricPaths(request.metric_paths),
         hostComponentCriteria: this.computeHostComponentCriteria(request)
       }
     });
@@ -639,6 +669,8 @@ App.WidgetLoadAggregator = Em.Object.create({
    */
   BULK_INTERVAL: 1000,
 
+  arrayUtils: require('utils/array_utils'),
+
   /**
    * add request
    * every {{BULK_INTERVAL}} requests get collected, aggregated and sent to server
@@ -699,10 +731,10 @@ App.WidgetLoadAggregator = Em.Object.create({
    */
   runRequests: function (requests) {
     var bulks = this.groupRequests(requests);
-
+    var self = this;
     for (var id in bulks) {
       (function (_request) {
-        _request.data.metric_paths = _request.data.metric_paths.uniq();
+        _request.data.metric_paths = self.arrayUtils.uniqObjectsbyId(_request.data.metric_paths, "id");
         _request.context[_request.startCallName].call(_request.context, _request.data).done(function (response) {
           _request.subRequests.forEach(function (subRequest) {
             subRequest.successCallback.call(subRequest.context, response);

+ 36 - 0
ambari-web/app/utils/array_utils.js

@@ -0,0 +1,36 @@
+/**
+ * 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.
+ */
+
+module.exports = {
+  /**
+   *
+   * @param arr {Array}
+   * @param id
+   * @return result {Array}
+   */
+  uniqObjectsbyId: function (arr, id) {
+    var result = [];
+    arr.forEach(function (item) {
+      var isIdPresent = result.someProperty('id', item.id);
+      if (!isIdPresent) {
+        result.pushObject(item);
+      }
+    });
+    return result;
+  }
+};

+ 6 - 36
ambari-web/app/views/common/widget/graph_widget_view.js

@@ -21,6 +21,12 @@ var App = require('app');
 App.GraphWidgetView = Em.View.extend(App.WidgetMixin, {
   templateName: require('templates/common/widget/graph_widget'),
 
+  /**
+   *  type of metric query from which the widget is comprised
+   */
+
+  metricType: 'TEMPORAL',
+
   /**
    * common metrics container
    * @type {Array}
@@ -184,42 +190,6 @@ App.GraphWidgetView = Em.View.extend(App.WidgetMixin, {
     }, this);
   },
 
-  /**
-   * make GET call to server in order to fetch service-component metrics
-   * @param {object} request
-   * @returns {$.ajax}
-   */
-  getServiceComponentMetrics: function (request) {
-    return App.ajax.send({
-      name: 'widgets.serviceComponent.metrics.get',
-      sender: this,
-      data: {
-        serviceName: request.service_name,
-        componentName: request.component_name,
-        metricPaths: this.addTimeProperties(request.metric_paths).join(',')
-      },
-      success: 'getMetricsSuccessCallback'
-    });
-  },
-
-  /**
-   * make GET call to server in order to fetch host-component metrics
-   * @param {object} request
-   * @returns {$.ajax}
-   */
-  getHostComponentMetrics: function (request) {
-    return App.ajax.send({
-      name: 'widgets.hostComponent.metrics.get',
-      sender: this,
-      data: {
-        componentName: request.component_name,
-        metricPaths: this.addTimeProperties(request.metric_paths).join(','),
-        hostComponentCriteria: this.computeHostComponentCriteria(request)
-      },
-      success: 'getHostComponentMetricsSuccessCallback'
-    });
-  },
-
   /**
    * add time properties
    * @param {Array} metricPaths

+ 74 - 28
ambari-web/test/mixins/common/widget_mixin_test.js

@@ -18,7 +18,7 @@
 
 var App = require('app');
 
-describe('App.WidgetMixin', function() {
+describe('App.WidgetMixin', function () {
   var mixinClass = Em.Object.extend(App.WidgetMixin, {metrics: [], content: {}});
 
   describe('#loadMetrics()', function () {
@@ -47,7 +47,7 @@ describe('App.WidgetMixin', function() {
     });
   });
 
-  describe("#extractExpressions()", function() {
+  describe("#extractExpressions()", function () {
     var mixinObject = mixinClass.create();
     var testCases = [
       {
@@ -79,9 +79,9 @@ describe('App.WidgetMixin', function() {
     });
   });
 
-  describe("#getRequestData()", function() {
+  describe("#getRequestData()", function () {
     var mixinObject = mixinClass.create();
-    it("", function() {
+    it("", function () {
       var data = [
         {
           "name": "regionserver.Server.percentFilesLocal",
@@ -111,14 +111,24 @@ describe('App.WidgetMixin', function() {
         }
       ];
 
-      expect(mixinObject.getRequestData(data)).to.eql({
+      expect(JSON.stringify(mixinObject.getRequestData(data))).to.eql(JSON.stringify({
         "HBASE_HBASE_REGIONSERVER": {
           "name": "regionserver.Server.percentFilesLocal",
           "service_name": "HBASE",
           "component_name": "HBASE_REGIONSERVER",
           "metric_paths": [
-            "metrics/hbase/regionserver/percentFilesLocal",
-            "w2"
+            {
+              "metric_path": "metrics/hbase/regionserver/percentFilesLocal",
+              "metric_type": "POINT_IN_TIME",
+              "id": "metrics/hbase/regionserver/percentFilesLocal_POINT_IN_TIME",
+              "context": {}
+            },
+            {
+              "metric_path": "w2",
+              "metric_type": "POINT_IN_TIME",
+              "id": "w2_POINT_IN_TIME",
+              "context": {}
+            }
           ]
         },
         "HBASE_HBASE_REGIONSERVER_c1": {
@@ -127,7 +137,12 @@ describe('App.WidgetMixin', function() {
           "component_name": "HBASE_REGIONSERVER",
           "host_component_criteria": "c1",
           "metric_paths": [
-            "metrics/hbase/regionserver/percentFilesLocal"
+            {
+              "metric_path": "metrics/hbase/regionserver/percentFilesLocal",
+              "metric_type": "POINT_IN_TIME",
+              "id": "metrics/hbase/regionserver/percentFilesLocal_POINT_IN_TIME",
+              "context": {}
+            }
           ]
         },
         "HDFS_DATANODE_c1": {
@@ -136,10 +151,15 @@ describe('App.WidgetMixin', function() {
           "component_name": "DATANODE",
           "host_component_criteria": "c1",
           "metric_paths": [
-            "metrics/hbase/regionserver/percentFilesLocal"
+            {
+              "metric_path": "metrics/hbase/regionserver/percentFilesLocal",
+              "metric_type": "POINT_IN_TIME",
+              "id": "metrics/hbase/regionserver/percentFilesLocal_POINT_IN_TIME",
+              "context": {}
+            }
           ]
         }
-      });
+      }));
     });
   });
 
@@ -155,7 +175,20 @@ describe('App.WidgetMixin', function() {
       var request = {
         service_name: 'S1',
         component_name: 'C1',
-        metric_paths: ['w1', 'w2']
+        metric_paths: [
+          {
+            "metric_path": "w1",
+            "metric_type": "POINT_IN_TIME",
+            "id": "w1_POINT_IN_TIME",
+            "context": {}
+          },
+          {
+            "metric_path": "w2",
+            "metric_type": "POINT_IN_TIME",
+            "id": "w2_POINT_IN_TIME",
+            "context": {}
+          }
+        ]
       };
       mixinObject.getServiceComponentMetrics(request);
       expect(App.ajax.send.getCall(0).args[0]).to.eql({
@@ -207,7 +240,20 @@ describe('App.WidgetMixin', function() {
     it("", function () {
       var request = {
         component_name: 'C1',
-        metric_paths: ['w1', 'w2'],
+        metric_paths: [
+          {
+            "metric_path": "w1",
+            "metric_type": "POINT_IN_TIME",
+            "id": "w1_POINT_IN_TIME",
+            "context": {}
+          },
+          {
+            "metric_path": "w2",
+            "metric_type": "POINT_IN_TIME",
+            "id": "w2_POINT_IN_TIME",
+            "context": {}
+          }
+        ],
         host_component_criteria: 'c1'
       };
       mixinObject.getHostComponentMetrics(request);
@@ -223,7 +269,7 @@ describe('App.WidgetMixin', function() {
     });
   });
 
-  describe("#calculateValues()", function() {
+  describe("#calculateValues()", function () {
     var mixinObject = mixinClass.create();
 
     beforeEach(function () {
@@ -234,7 +280,7 @@ describe('App.WidgetMixin', function() {
       mixinObject.extractExpressions.restore();
       this.mock.restore();
     });
-    it("value compute correctly", function() {
+    it("value compute correctly", function () {
       this.mock.returns({'${a}': 1});
       mixinObject.set('content.values', [{
         value: '${a}'
@@ -242,7 +288,7 @@ describe('App.WidgetMixin', function() {
       mixinObject.calculateValues();
       expect(mixinObject.get('content.values')[0].computedValue).to.equal('1');
     });
-    it("value not available", function() {
+    it("value not available", function () {
       this.mock.returns({});
       mixinObject.set('content.values', [{
         value: '${a}'
@@ -250,7 +296,7 @@ describe('App.WidgetMixin', function() {
       mixinObject.calculateValues();
       expect(mixinObject.get('content.values')[0].computedValue).to.be.empty;
     });
-    it("value is null", function() {
+    it("value is null", function () {
       this.mock.returns({'${a}': null});
       mixinObject.set('content.values', [{
         value: '${a}'
@@ -260,17 +306,17 @@ describe('App.WidgetMixin', function() {
     });
   });
 
-  describe("#computeExpression()", function() {
+  describe("#computeExpression()", function () {
     var mixinObject = mixinClass.create();
 
-    it("expression missing metrics", function() {
+    it("expression missing metrics", function () {
       var expressions = ['e.m1'];
       var metrics = [];
       expect(mixinObject.computeExpression(expressions, metrics)).to.eql({
         "${e.m1}": ""
       });
     });
-    it("Value is not correct mathematical expression", function() {
+    it("Value is not correct mathematical expression", function () {
       var expressions = ['e.m1'];
       var metrics = [{
         name: 'e.m1',
@@ -280,7 +326,7 @@ describe('App.WidgetMixin', function() {
         "${e.m1}": ""
       });
     });
-    it("correct expression", function() {
+    it("correct expression", function () {
       var expressions = ['e.m1+e.m1'];
       var metrics = [{
         name: 'e.m1',
@@ -292,7 +338,7 @@ describe('App.WidgetMixin', function() {
     });
   });
 
-  describe("#cloneWidget()", function() {
+  describe("#cloneWidget()", function () {
     var mixinObject = mixinClass.create();
 
     before(function () {
@@ -303,7 +349,7 @@ describe('App.WidgetMixin', function() {
       App.showConfirmationPopup.restore();
       mixinObject.postWidgetDefinition.restore();
     });
-    it("", function() {
+    it("", function () {
       var popup = mixinObject.cloneWidget();
       expect(App.showConfirmationPopup.calledOnce).to.be.true;
       popup.onPrimary();
@@ -311,7 +357,7 @@ describe('App.WidgetMixin', function() {
     });
   });
 
-  describe("#postWidgetDefinition()", function() {
+  describe("#postWidgetDefinition()", function () {
     var mixinObject = mixinClass.create();
 
     before(function () {
@@ -322,7 +368,7 @@ describe('App.WidgetMixin', function() {
       App.ajax.send.restore();
       mixinObject.collectWidgetData.restore();
     });
-    it("", function() {
+    it("", function () {
       mixinObject.postWidgetDefinition();
       expect(App.ajax.send.getCall(0).args[0]).to.eql({
         name: 'widgets.wizard.add',
@@ -337,7 +383,7 @@ describe('App.WidgetMixin', function() {
 });
 
 
-describe('App.WidgetLoadAggregator', function() {
+describe('App.WidgetLoadAggregator', function () {
   var aggregator = App.WidgetLoadAggregator;
 
   describe("#add()", function () {
@@ -411,7 +457,7 @@ describe('App.WidgetLoadAggregator', function() {
     });
   });
 
-  describe("#runRequests()", function() {
+  describe("#runRequests()", function () {
     var mock = {
       f1: function () {
         return {
@@ -421,7 +467,7 @@ describe('App.WidgetLoadAggregator', function() {
       }
     };
     beforeEach(function () {
-      sinon.stub(aggregator, 'groupRequests', function(requests){
+      sinon.stub(aggregator, 'groupRequests', function (requests) {
         return requests;
       });
       sinon.spy(mock, 'f1');
@@ -430,7 +476,7 @@ describe('App.WidgetLoadAggregator', function() {
       aggregator.groupRequests.restore();
       mock.f1.restore();
     });
-    it("", function() {
+    it("", function () {
       var requests = {
         'r1': {
           data: {