Browse Source

AMBARI-11413 Ambari Web is sluggish, especially on Hosts page, with 1300 nodes in the cluster. (atkach)

Andrii Tkach 10 years ago
parent
commit
9b331fec79

+ 6 - 2
ambari-web/app/controllers/global/update_controller.js

@@ -469,7 +469,10 @@ App.UpdateController = Em.Controller.extend({
   },
   updateAlertDefinitions: function (callback) {
     var testUrl = '/data/alerts/alertDefinitions.json';
-    var realUrl = '/alert_definitions?fields=*';
+    var realUrl = '/alert_definitions?fields=' +
+      'AlertDefinition/component_name,AlertDefinition/description,AlertDefinition/enabled,AlertDefinition/id,' +
+      'AlertDefinition/ignore_host,AlertDefinition/interval,AlertDefinition/label,AlertDefinition/name,' +
+      'AlertDefinition/scope,AlertDefinition/service_name,AlertDefinition/source';
     var url = this.getUrl(testUrl, realUrl);
 
     App.HttpClient.get(url, App.alertDefinitionsMapper, {
@@ -504,7 +507,8 @@ App.UpdateController = Em.Controller.extend({
 
   updateAlertGroups: function (callback) {
     var testUrl = '/data/alerts/alertGroups.json';
-    var realUrl = '/alert_groups?fields=*';
+    var realUrl = '/alert_groups?fields=' +
+      'AlertGroup/default,AlertGroup/definitions,AlertGroup/id,AlertGroup/name,AlertGroup/targets';
     var url = this.getUrl(testUrl, realUrl);
 
     App.HttpClient.get(url, App.alertGroupsMapper, {

+ 17 - 8
ambari-web/app/controllers/main/charts/heatmap.js

@@ -23,6 +23,11 @@ App.MainChartsHeatmapController = Em.Controller.extend(App.WidgetSectionMixin, {
   racks: [],
   rackViews: [],
 
+  /**
+   * @type {boolean}
+   */
+  isLoaded: false,
+
   /**
    * Heatmap metrics that are available choices  on the page
    */
@@ -65,16 +70,20 @@ App.MainChartsHeatmapController = Em.Controller.extend(App.WidgetSectionMixin, {
   /**
    * This function is called from the binded view of the controller
    */
-  loadPageData: function() {
+  loadPageData: function () {
     var self = this;
-    this.resetPageData();
-    this.getAllHeatMaps().done(function(allHeatmapData){
-      allHeatmapData.items.forEach(function(_allHeatmapData) {
-        self.get('allHeatmaps').pushObject(_allHeatmapData.WidgetInfo);
+    this.loadRacks().done(function (data) {
+      self.set('isLoaded', true);
+      self.loadRacksSuccessCallback(data);
+      self.resetPageData();
+      self.getAllHeatMaps().done(function (allHeatmapData) {
+        allHeatmapData.items.forEach(function (_allHeatmapData) {
+          self.get('allHeatmaps').pushObject(_allHeatmapData.WidgetInfo);
+        });
+        var categories = self.categorizeByServiceName(self.get('allHeatmaps'));
+        self.set('heatmapCategories', categories);
+        self.getActiveWidgetLayout();
       });
-      var categories = self.categorizeByServiceName(self.get('allHeatmaps'));
-      self.set('heatmapCategories', categories);
-      self.getActiveWidgetLayout();
     });
   },
 

+ 44 - 46
ambari-web/app/mappers/component_config_mapper.js

@@ -35,47 +35,51 @@ App.componentConfigMapper = App.QuickDataMapper.create({
   map: function (json) {
     console.time('App.componentConfigMapper execution time');
     var hostComponents = [];
-    var serviceToHostComponentIdMap = {};
+    var newHostComponentsMap = {};
     var cacheServices = App.cache['services'];
-    var loadedServiceComponentsMap = this.buildServiceComponentMap(cacheServices);
+    var currentServiceComponentsMap = this.buildServiceComponentMap(cacheServices);
     var mapConfig = this.get('config');
     // We do not want to parse JSON if there is no need to
     var hostComponentJsonMap = {};
     var hostComponentJsonIds = [];
     var hostComponentJsonsToRemove = {};
-    json.items.forEach(function (item) {
-      item.host_components.forEach(function (host_component) {
-        host_component.id = host_component.HostRoles.component_name + '_' + host_component.HostRoles.host_name;
-        hostComponentJsonIds.push(host_component.id);
-        hostComponentJsonMap[host_component.id] = host_component;
+
+    if (json.items.length > 0 || this.get('model').find().someProperty('staleConfigs', true)) {
+      json.items.forEach(function (item) {
+        item.host_components.forEach(function (host_component) {
+          host_component.id = host_component.HostRoles.component_name + '_' + host_component.HostRoles.host_name;
+          hostComponentJsonIds.push(host_component.id);
+          hostComponentJsonMap[host_component.id] = host_component;
+        });
       });
-    });
-    this.get('model').find().forEach(function (hostComponent) {
-      var hostComponentJson = hostComponentJsonMap[hostComponent.get('id')];
-      if (!hostComponentJson &&
-        !App.StackServiceComponent.find().findProperty('componentName', hostComponent.get('componentName')).get('isMaster')) {
-        hostComponent.set('staleConfigs', false);
-      }
-      if (hostComponentJson!=null && hostComponent.get('staleConfigs') &&
+      this.get('model').find().forEach(function (hostComponent) {
+        var hostComponentJson = hostComponentJsonMap[hostComponent.get('id')];
+        if (!hostComponentJson && !hostComponent.get('isMaster')) {
+          hostComponent.set('staleConfigs', false);
+        }
+        if (hostComponentJson != null && hostComponent.get('staleConfigs') &&
           hostComponentJson.HostRoles.state == hostComponent.get('workStatus') &&
           hostComponentJson.HostRoles.maintenance_state == hostComponent.get('passiveState')) {
-        // A component already exists with correct stale_configs flag and other values - no need to load again
-        hostComponentJsonsToRemove[hostComponentJson.id] = hostComponentJson;
-      }
-    });
-    hostComponentJsonIds.forEach(function (hcId) {
-      if(!hostComponentJsonsToRemove[hcId]){
-        var host_component = hostComponentJsonMap[hcId];
-        var serviceName = host_component.HostRoles.service_name;
-        hostComponents.push(this.parseIt(host_component, mapConfig));
-        if (!serviceToHostComponentIdMap[serviceName]) {
-          serviceToHostComponentIdMap[serviceName] = [];
+          // A component already exists with correct stale_configs flag and other values - no need to load again
+          hostComponentJsonsToRemove[hostComponentJson.id] = hostComponentJson;
         }
-        serviceToHostComponentIdMap[serviceName].push(host_component.id);
-      }
-    }, this);
-    App.store.loadMany(this.get('model'), hostComponents);
-    this.addNewHostComponents(loadedServiceComponentsMap, serviceToHostComponentIdMap, cacheServices);
+      });
+      hostComponentJsonIds.forEach(function (hcId) {
+        if (!hostComponentJsonsToRemove[hcId]) {
+          var host_component = hostComponentJsonMap[hcId];
+          var serviceName = host_component.HostRoles.service_name;
+          hostComponents.push(this.parseIt(host_component, mapConfig));
+          if (!newHostComponentsMap[serviceName]) {
+            newHostComponentsMap[serviceName] = [];
+          }
+          if (!currentServiceComponentsMap[serviceName][host_component.id]) {
+            newHostComponentsMap[serviceName].push(host_component.id);
+          }
+        }
+      }, this);
+      App.store.loadMany(this.get('model'), hostComponents);
+      this.addNewHostComponents(newHostComponentsMap, cacheServices);
+    }
     console.timeEnd('App.componentConfigMapper execution time');
   },
 
@@ -101,25 +105,19 @@ App.componentConfigMapper = App.QuickDataMapper.create({
   /**
    * add only new host-components to every service
    * to update service - host-component relations in model
-   * @param loadedServiceComponentsMap
-   * @param serviceToHostComponentIdMap
-   * @param cacheServices
+   * @param {object} newHostComponentsMap
+   * @param {Array} cacheServices
    * @return {boolean}
    */
-  addNewHostComponents: function (loadedServiceComponentsMap, serviceToHostComponentIdMap, cacheServices) {
-    if (!loadedServiceComponentsMap || !serviceToHostComponentIdMap || !cacheServices) return false;
-
-    for (var serviceName in serviceToHostComponentIdMap) {
-      var loadedService = cacheServices.findProperty('ServiceInfo.service_name', serviceName);
-
-      if (serviceToHostComponentIdMap[serviceName] && loadedService) {
-        serviceToHostComponentIdMap[serviceName].forEach(function (componentId) {
-          if (!loadedServiceComponentsMap[serviceName][componentId]) {
-            loadedService.host_components.push(componentId)
-          }
+  addNewHostComponents: function (newHostComponentsMap, cacheServices) {
+    if (!newHostComponentsMap || !cacheServices) return false;
+    cacheServices.forEach(function (service) {
+      if (newHostComponentsMap[service.ServiceInfo.service_name]) {
+        newHostComponentsMap[service.ServiceInfo.service_name].forEach(function (componentId) {
+          service.host_components.push(componentId)
         });
       }
-    }
+    }, this);
     return true;
   }
 });

+ 14 - 10
ambari-web/app/mappers/hosts_mapper.js

@@ -87,9 +87,11 @@ App.hostsMapper = App.QuickDataMapper.create({
       var stackVersions = [];
       var componentsIdMap = {};
       var cacheServices = App.cache['services'];
-      var loadedServiceComponentsMap = App.get('componentConfigMapper').buildServiceComponentMap(cacheServices);
-      var serviceToHostComponentIdMap = {};
+      var currentServiceComponentsMap = App.get('componentConfigMapper').buildServiceComponentMap(cacheServices);
+      var newHostComponentsMap = {};
       var selectedHosts = App.db.getSelectedHosts('mainHostController');
+      var stackUpgradeSupport = App.get('supports.stackUpgrade');
+      var clusterName = App.get('clusterName');
 
       json.items.forEach(function (item, index) {
         item.host_components = item.host_components || [];
@@ -103,13 +105,15 @@ App.hostsMapper = App.QuickDataMapper.create({
           component.host_name = item.Hosts.host_name;
           components.push(component);
           componentsIdMap[component.id] = component;
-          if (!serviceToHostComponentIdMap[serviceName]) {
-            serviceToHostComponentIdMap[serviceName] = [];
+          if (!newHostComponentsMap[serviceName]) {
+            newHostComponentsMap[serviceName] = [];
+          }
+          if (!currentServiceComponentsMap[serviceName][component.id]) {
+            newHostComponentsMap[serviceName].push(component.id);
           }
-          serviceToHostComponentIdMap[serviceName].push(component.id);
         }, this);
 
-        if (App.get('supports.stackUpgrade')) {
+        if (stackUpgradeSupport) {
           var currentVersion = item.stack_versions.findProperty('HostStackVersions.state', 'CURRENT');
           var currentVersionNumber = currentVersion && currentVersion.repository_versions
             ? Em.get(currentVersion.repository_versions[0], 'RepositoryVersions.repository_version') : '';
@@ -123,10 +127,10 @@ App.hostsMapper = App.QuickDataMapper.create({
 
         var alertsSummary = item.alerts_summary;
         item.critical_warning_alerts_count = alertsSummary ? (alertsSummary.CRITICAL || 0) + (alertsSummary.WARNING || 0) : 0;
-        item.cluster_id = App.get('clusterName');
+        item.cluster_id = clusterName;
         item.index = index;
 
-        if (App.get('supports.stackUpgrade')) {
+        if (stackUpgradeSupport) {
           this.config = $.extend(this.config, {
             stack_versions_key: 'stack_versions',
             stack_versions_type: 'array',
@@ -158,7 +162,7 @@ App.hostsMapper = App.QuickDataMapper.create({
         if (componentsIdMap[component.get('id')]) componentsIdMap[component.get('id')].display_name_advanced = component.get('displayNameAdvanced');
       });
       App.store.commit();
-      if (App.get('supports.stackUpgrade')) {
+      if (stackUpgradeSupport) {
         App.store.loadMany(App.HostStackVersion, stackVersions);
       }
       App.store.loadMany(App.HostComponent, components);
@@ -168,7 +172,7 @@ App.hostsMapper = App.QuickDataMapper.create({
         App.router.set('mainHostController.filteredCount', itemTotal);
       }
       //bind host-components with service records
-      App.get('componentConfigMapper').addNewHostComponents(loadedServiceComponentsMap, serviceToHostComponentIdMap, cacheServices);
+      App.get('componentConfigMapper').addNewHostComponents(newHostComponentsMap, cacheServices);
     }
     console.timeEnd('App.hostsMapper execution time');
   }

+ 1 - 4
ambari-web/app/routes/main.js

@@ -142,10 +142,7 @@ module.exports = Em.Route.extend(App.RouterRedirections, {
         route: '/heatmap',
         connectOutlets: function (router, context) {
           router.get('mainController').dataLoading().done(function () {
-            router.get('mainChartsHeatmapController').loadRacks().done(function(data){
-              router.get('mainChartsHeatmapController').loadRacksSuccessCallback(data);
-              router.get('mainChartsController').connectOutlet('mainChartsHeatmap');
-            });
+            router.get('mainChartsController').connectOutlet('mainChartsHeatmap');
           });
         }
       }),

+ 29 - 27
ambari-web/app/templates/main/charts/heatmap.hbs

@@ -17,37 +17,39 @@
 }}
 
 <div class="heatmap">
+  {{#if isLoaded}}
+    <div class="container-fluid">
+      <div class="row-fluid">
+        <div class="span2 legend-column">
 
-  <div class="container-fluid">
-    <div class="row-fluid">
-      <div class="span2 legend-column">
+          {{view view.dropdownView}}
 
-        {{view view.dropdownView}}
-
-        {{#if controller.selectedMetric}}
-          <table class="legend">
-            {{#each slot in controller.selectedMetric.slotDefinitions}}
-              <tr>
-                <td>
-                  <div class="tile" {{bindAttr style="slot.cssStyle"}}></div>
-                </td>
-                <td>{{slot.label}}</td>
-              </tr>
-            {{/each}}
-          </table>
-          {{t common.maximum}}:
-          <div id="inputMaximum" class="control-group">
-            {{view Ember.TextField type="text" maxlength="8" valueBinding="controller.inputMaximum" class="span6"}}
-            {{controller.selectedMetric.units}}
+          {{#if controller.selectedMetric}}
+            <table class="legend">
+              {{#each slot in controller.selectedMetric.slotDefinitions}}
+                <tr>
+                  <td>
+                    <div class="tile" {{bindAttr style="slot.cssStyle"}}></div>
+                  </td>
+                  <td>{{slot.label}}</td>
+                </tr>
+              {{/each}}
+            </table>
+            {{t common.maximum}}:
+            <div id="inputMaximum" class="control-group">
+              {{view Ember.TextField type="text" maxlength="8" valueBinding="controller.inputMaximum" class="span6"}}
+              {{controller.selectedMetric.units}}
+            </div>
+          {{/if}}
+        </div>
+        {{#if controller.activeWidget}}
+          <div class="active-widget" {{bindAttr id="activeWidget.id"}}>
+            {{view activeWidget.viewClass contentBinding="activeWidget" racksBinding = "racks" idBinding="activeWidget.id"}}
           </div>
         {{/if}}
       </div>
-      {{#if controller.activeWidget}}
-        <div class="active-widget" {{bindAttr id="activeWidget.id"}}>
-          {{view activeWidget.viewClass contentBinding="activeWidget" racksBinding = "racks" idBinding="activeWidget.id"}}
-        </div>
-      {{/if}}
     </div>
-  </div>
-
+  {{else}}
+    <div class="spinner"></div>
+  {{/if}}
 </div>

+ 1 - 1
ambari-web/app/utils/ajax/ajax.js

@@ -464,7 +464,7 @@ var urls = {
     'testInProduction': true
   },
   'background_operations.get_by_request': {
-    'real': '/clusters/{clusterName}/requests/{requestId}?fields=*,tasks/Tasks/request_id,tasks/Tasks/command,tasks/Tasks/command_detail,tasks/Tasks/start_time,tasks/Tasks/end_time,tasks/Tasks/exit_code,tasks/Tasks/host_name,tasks/Tasks/id,tasks/Tasks/role,tasks/Tasks/status&minimal_response=true',
+    'real': '/clusters/{clusterName}/requests/{requestId}?fields=*,tasks/Tasks/request_id,tasks/Tasks/command,tasks/Tasks/command_detail,tasks/Tasks/host_name,tasks/Tasks/id,tasks/Tasks/role,tasks/Tasks/status&minimal_response=true',
     'mock': '/data/background_operations/task_by_request{requestId}.json',
     'testInProduction': true
   },

+ 10 - 1
ambari-web/app/views/common/sort_view.js

@@ -239,11 +239,20 @@ var serverWrapperView = Em.View.extend({
    */
   sort: function (property, order) {
     var status = order ? 'sorting_desc' : 'sorting_asc';
+    var self = this;
 
     this.resetSort();
     this.get('childViews').findProperty('name', property.get('name')).set('status', status);
     this.saveSortStatuses();
-    this.get('parentView').refresh();
+    if (!this.get('parentView.filteringComplete')) {
+      clearTimeout(this.get('parentView.timeOut'));
+      this.set('parentView.timeOut', setTimeout(function () {
+        self.sort(property, order);
+      }, this.get('parentView.filterWaitingTime')));
+    } else {
+      clearTimeout(this.get('parentView.timeOut'));
+      this.get('parentView').refresh();
+    }
   },
 
   /**

+ 0 - 1
ambari-web/app/views/main/charts/heatmap.js

@@ -20,7 +20,6 @@ var App = require('app');
 App.MainChartsHeatmapView = Em.View.extend({
   templateName: require('templates/main/charts/heatmap'),
   didInsertElement: function () {
-    this._super();
     // set default metric
     this.get('controller').loadPageData();
     $("#heatmapDetailsBlock").hide();