Explorar el Código

AMBARI-4077 Optimize Alert mapper processing. (atkach)

atkach hace 11 años
padre
commit
5629ad9831

+ 65 - 106
ambari-web/app/mappers/alerts_mapper.js

@@ -17,130 +17,89 @@
  */
 
 
+var previousAlertsResponse = [];
+var stringUtils = require('utils/string_utils');
+
+/**
+ * Fields, which are not displayed and used only to compute date property, listed below:
+ * last_hard_state_change
+ * last_hard_state
+ * last_time_ok
+ * last_time_warning
+ * last_time_unknown
+ * last_time_critical
+ */
 App.alertsMapper = App.QuickDataMapper.create({
   model: App.Alert,
-  config:{
-    $alert_id:'' ,
+  config: {
+    id: 'id',
     title: "service_description",
     service_type: "service_type",
-    date: "last_hard_state_change",
+    last_time: "last_time",
     status: "current_state",
     message: "plugin_output",
     host_name: "host_name",
     current_attempt: "current_attempt",
-    last_hard_state_change: "last_hard_state_change",
-    last_hard_state: "last_hard_state",
-    last_time_ok: "last_time_ok",
-    last_time_warning: "last_time_warning",
-    last_time_unknown: "last_time_unknown",
-    last_time_critical: "last_time_critical",
     is_flapping: "is_flapping",
     last_check: "last_check"
   },
   map: function (json) {
-    if (!this.get('model')) {
-      return;
-    }
-    if (json && json.items && json.items.length>0 && json.items[0].HostRoles && json.items[0].HostRoles.nagios_alerts) {
-      var alerts = json.items[0].HostRoles.nagios_alerts.alerts;
-      if (App.Alert.find().content.length > 0) {
-        this.update(alerts);
-      } else {
-        var result = [];
-        alerts.forEach(function(item){
-          var applyConfig = jQuery.extend({}, this.config);
-          if (item.current_state && item.last_hard_state && item.current_state != item.last_hard_state) {
-            switch (item.current_state) {
-              case "0":
-                applyConfig['date'] = 'last_time_ok';
-                break;
-              case "1":
-                applyConfig['date'] = 'last_time_warning';
-                break;
-              case "2":
-                applyConfig['date'] = 'last_time_critical';
-                break;
-              case "3":
-                applyConfig['date'] = 'last_time_unknown';
-                break;
-            }
-          }
-          result.push(this.parseIt(item, applyConfig));
-        }, this);
-        App.store.loadMany(this.get('model'), result);
+    console.time('App.alertsMapper execution time');
+    if (json && json.items && json.items.length > 0 && json.items[0].HostRoles && json.items[0].HostRoles.nagios_alerts) {
+      if (json.items[0].HostRoles.nagios_alerts.alerts.length === 0) {
+        //Clear Alerts model when NAGIOS stopped or doesn't have alerts anymore
+        App.Alert.find().clear();
+        console.log("NAGIOS stopped: all alerts deleted");
+        return;
       }
-    }
-  },
-  update: function(alerts){
-    var alertsList = App.Alert.find();
-    var titleToAlertMap = {};
-    alertsList.forEach(function(alert){
-      titleToAlertMap[alert.get('serviceType') + alert.get('title') + alert.get('hostName')] = alert;
-    });
-    var newRecords = [];
-    alerts.forEach(function(item){
-      var existAlert = titleToAlertMap[item.service_type + item.service_description + item.host_name];
-      if (existAlert == null) {
-        var applyConfig = jQuery.extend({}, this.config);
-        if (item.current_state && item.last_hard_state && item.current_state != item.last_hard_state) {
-          switch (item.current_state) {
-            case "0":
-              applyConfig['date'] = 'last_time_ok';
-              break;
-            case "1":
-              applyConfig['date'] = 'last_time_warning';
-              break;
-            case "2":
-              applyConfig['date'] = 'last_time_critical';
-              break;
-            case "3":
-              applyConfig['date'] = 'last_time_unknown';
-              break;
-          }
+      var alerts = json.items[0].HostRoles.nagios_alerts.alerts;
+      var alertsMap = {};
+      var addAlerts = [];
+      var mutableFields = ['last_time', 'status', 'message', 'current_attempt', 'is_flapping', 'last_check'];
+
+      alerts.forEach(function (item) {
+        //id consists of combination of serviceType, title and hostName
+        item.id = item.service_type + item.service_description + item.host_name;
+        item.last_time = this.computeLastTime(item);
+        var parsedItem = this.parseIt(item, this.config);
+        alertsMap[item.id] = parsedItem;
+        if (!previousAlertsResponse[item.id]) {
+          addAlerts.push(parsedItem);
         }
-        newRecords.push(this.parseIt(item, applyConfig));
-      } else {
-        // update record
-        existAlert.set('serviceType', item.service_type);
-        if (item.current_state && item.last_hard_state && item.current_state != item.last_hard_state) {
-          switch (item.current_state) {
-            case "0":
-              existAlert.set('date', DS.attr.transforms.date.from(item.last_time_ok));
-              break;
-            case "1":
-              existAlert.set('date', DS.attr.transforms.date.from(item.last_time_warning));
-              break;
-            case "2":
-              existAlert.set('date', DS.attr.transforms.date.from(item.last_time_critical));
-              break;
-            case "3":
-              existAlert.set('date', DS.attr.transforms.date.from(item.last_time_unknown));
-              break;
-            default:
-              existAlert.set('date', DS.attr.transforms.date.from(item.last_hard_state_change));
-              break;
+      }, this);
+
+      this.get('model').find().forEach(function (alertRecord) {
+        var existAlert = alertsMap[alertRecord.get('id')];
+        if (existAlert) {
+          existAlert = this.getDiscrepancies(existAlert, previousAlertsResponse[alertRecord.get('id')], mutableFields);
+          if (existAlert) {
+            for (var i in existAlert) {
+              alertRecord.set(stringUtils.underScoreToCamelCase(i), existAlert[i]);
+            }
           }
-        }else{
-          existAlert.set('date', DS.attr.transforms.date.from(item.last_hard_state_change));
+        } else {
+          this.deleteRecord(alertRecord);
         }
-        existAlert.set('status', item.current_state);
-        existAlert.set('message', item.plugin_output);
-        existAlert.set('lastHardStateChange', item.last_hard_state_change);
-        existAlert.set('lastHardState', item.last_hard_state);
-        existAlert.set('lastTimeOk', item.last_time_ok);
-        existAlert.set('lastTimeWarning', item.last_time_warning);
-        existAlert.set('lastTimeUnknown', item.last_time_unknown);
-        existAlert.set('lastTimeCritical', item.last_time_critical);
-        existAlert.set('lastCheck', item.last_check);
-        existAlert.set('isFlapping', item.is_flapping);
-        delete titleToAlertMap[item.service_type + item.service_description + item.host_name];
+      }, this);
+
+      if (addAlerts.length > 0) {
+        App.store.loadMany(this.get('model'), addAlerts);
       }
-    }, this);
-    for ( var e in titleToAlertMap) {
-      titleToAlertMap[e].deleteRecord();
+      previousAlertsResponse = alertsMap;
     }
-    if (newRecords.length > 0) {
-      App.store.loadMany(this.get('model'), newRecords); // Add new records
+    console.timeEnd('App.alertsMapper execution time');
+  },
+  computeLastTime: function (item) {
+    var dateMap = {
+      '0': 'last_time_ok',
+      '1': 'last_time_warning',
+      '2': 'last_time_critical',
+      '3': 'last_time_unknown'
+    };
+    if (item.current_state && item.last_hard_state && item.current_state != item.last_hard_state) {
+      return item[dateMap[item.current_state]] || item['last_hard_state_change'];
+    } else {
+      return item['last_hard_state_change'];
     }
   }
 });

+ 25 - 0
ambari-web/app/mappers/server_data_mapper.js

@@ -134,6 +134,31 @@ App.QuickDataMapper = App.ServerDataMapper.extend({
     item.get('stateManager').transitionTo('loading');
     console.log('Record with id:' + item.get('id') + ' was deleted from model');
   },
+  /**
+   * check mutable fields whether they have been changed and if positive
+   * return host object only with properties, that contains new value
+   * @param current
+   * @param previous
+   * @param fields
+   * @return {*}
+   */
+  getDiscrepancies: function (current, previous, fields) {
+    var result = {};
+    if (previous) {
+      fields.forEach(function (field) {
+        if (Array.isArray(current[field])) {
+          if (JSON.stringify(current[field]) !== JSON.stringify(previous[field])) {
+            result[field] = current[field];
+            result.isLoadNeeded = true;
+          }
+        } else {
+          if (current[field] != previous[field]) result[field] = current[field];
+        }
+      });
+      return result;
+    }
+    return current;
+  },
 
   calculateState: function (json) {
 //    var stateEqual = (json.desired_status != json.work_status);

+ 0 - 25
ambari-web/app/mappers/service_metrics_mapper.js

@@ -299,31 +299,6 @@ App.serviceMetricsMapper = App.QuickDataMapper.create({
       }
     }, this)
   },
-  /**
-   * check mutable fields whether they have been changed and if positive
-   * return host object only with properties, that contains new value
-   * @param current
-   * @param previous
-   * @param fields
-   * @return {*}
-   */
-  getDiscrepancies: function (current, previous, fields) {
-    var result = {};
-    if (previous) {
-      fields.forEach(function (field) {
-        if (Array.isArray(current[field])) {
-          if (JSON.stringify(current[field]) !== JSON.stringify(previous[field])) {
-            result[field] = current[field];
-            result.isLoadNeeded = true;
-          }
-        } else {
-          if (current[field] != previous[field]) result[field] = current[field];
-        }
-      });
-      return result;
-    }
-    return current;
-  },
   /**
    * Map quick links to services:OOZIE,GANGLIA,NAGIOS,HUE
    * @param finalJson

+ 6 - 10
ambari-web/app/models/alert.js

@@ -21,30 +21,26 @@ var App = require('app');
 App.AlertStatus = {
   negative: 'corrupt',
   positive: 'ok'
-}
+};
 
 /**
  * Defines structure for App.Alert class. Keys mentioned here are for JSON data
  * which comes back from NAGIOS server.
  */
 App.Alert = DS.Model.extend({
-  alertId: DS.attr('string'),
-  primaryKey: 'alertId',
   title: DS.attr('string'),//service_description in ajax response
   serviceType: DS.attr('string'),
-  date: DS.attr('date'),
   status: DS.attr('string'),//current_state in ajax response
   message: DS.attr('string'),//plugin_output in ajax response
   hostName: DS.attr('string'),
   currentAttempt: DS.attr('string'),
-  lastHardStateChange: DS.attr('number'),
-  lastHardState: DS.attr('number'),
-  lastTimeOk: DS.attr('number'),
-  lastTimeWarning: DS.attr('number'),
-  lastTimeUnknown: DS.attr('number'),
-  lastTimeCritical: DS.attr('number'),
   isFlapping: DS.attr('number'),
   lastCheck: DS.attr('number'),
+  lastTime: DS.attr('number'),
+
+  date: function () {
+    return DS.attr.transforms.date.from(this.get('lastTime'));
+  }.property('lastTime'),
 
   /**
    * Used to show correct icon in UI