You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2016/04/13 16:20:54 UTC

ambari git commit: AMBARI-15855.Create a new alert type that is based on timeseries metrics (UI Task) (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk 10f824bee -> b4adae5cc


AMBARI-15855.Create a new alert type that is based on timeseries metrics (UI Task) (onechiporenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b4adae5c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b4adae5c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b4adae5c

Branch: refs/heads/trunk
Commit: b4adae5cc5912cab6d6992efb944138487823ca3
Parents: 10f824b
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Wed Apr 13 12:48:45 2016 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Wed Apr 13 17:20:20 2016 +0300

----------------------------------------------------------------------
 .../alerts/definition_configs_controller.js     |  74 ++++++++++++
 .../app/mappers/alert_definitions_mapper.js     |  20 ++++
 .../app/models/alerts/alert_definition.js       |  11 +-
 ambari-web/test/controllers/installer_test.js   |  12 --
 .../mappers/alert_definitions_mapper_test.js    | 114 ++++++++++++++++++-
 5 files changed, 215 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b4adae5c/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts/definition_configs_controller.js b/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
index 82263f7..9dc4f92 100644
--- a/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
+++ b/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
@@ -161,6 +161,9 @@ App.MainAlertDefinitionConfigsController = Em.Controller.extend({
       case 'RECOVERY':
       	configs = this.renderWebConfigs();
       	break;
+      case 'AMS':
+      	configs = this.renderAmsConfigs();
+      	break;
       default:
     }
 
@@ -312,6 +315,74 @@ App.MainAlertDefinitionConfigsController = Em.Controller.extend({
     return result;
   },
 
+  renderAmsConfigs: function () {
+    var result = [];
+    var alertDefinition = this.get('content');
+    var isWizard = this.get('isWizard');
+    var units = this.get('content.reporting').findProperty('type','units') ?
+      this.get('content.reporting').findProperty('type','units').get('text'): null;
+    if (this.get('isWizard')) {
+      result = result.concat(this.renderCommonWizardConfigs());
+    }
+
+    result = result.concat([
+      App.AlertConfigProperties.Description.create({
+        value: isWizard ? '' : alertDefinition.get('description')
+      }),
+      App.AlertConfigProperties.Interval.create({
+        value: isWizard ? '' : alertDefinition.get('interval')
+      }),
+      App.AlertConfigProperties.Interval.create({
+        value: isWizard ? '' : alertDefinition.get('ams.interval'),
+        label: 'AMS Interval',
+        apiProperty: 'source.ams.interval'
+      }),
+      App.AlertConfigProperty.create({
+        value: isWizard ? '' : alertDefinition.get('ams.value'),
+        label: 'AMS Value',
+        displayType: 'textField',
+        apiProperty: 'source.ams.value',
+        isValid: function () {
+          return (this.get('value') || '').trim().length > 0;
+        }.property('value')
+      }),
+      App.AlertConfigProperties.Parameter.create({
+        value: isWizard ? '' : alertDefinition.get('ams.minimalValue'),
+        label: 'AMS Minimal Value',
+        apiProperty: 'source.ams.minimal_value'
+      }),
+      App.AlertConfigProperties.Thresholds.OkThreshold.create({
+        label: 'Thresholds',
+        showInputForValue: false,
+        text: isWizard ? '' : this.getThresholdsProperty('ok', 'text'),
+        value: isWizard ? '' : this.getThresholdsProperty('ok', 'value')
+      }),
+      App.AlertConfigProperties.Thresholds.WarningThreshold.create(App.AlertConfigProperties.Thresholds.PercentageMixin, {
+        text: isWizard ? '' : this.getThresholdsProperty('warning', 'text'),
+        value: isWizard ? '' : this.getThresholdsProperty('warning', 'value'),
+        valueMetric: units
+      }),
+      App.AlertConfigProperties.Thresholds.CriticalThreshold.create(App.AlertConfigProperties.Thresholds.PercentageMixin, {
+        text: isWizard ? '' : this.getThresholdsProperty('critical', 'text'),
+        value: isWizard ? '' : this.getThresholdsProperty('critical', 'value'),
+        valueMetric: units
+      }),
+      App.AlertConfigProperties.Parameter.create({
+        value: alertDefinition.get('uri.connectionTimeout'),
+        name: 'connection_timeout',
+        label: 'Connection Timeout',
+        displayType: 'parameter',
+        apiProperty: 'source.uri.connection_timeout',
+        units: 'Seconds',
+        isValid: function () {
+          var value = this.get('value');
+          return numericUtils.isPositiveNumber(value);
+        }.property('value')
+      })
+    ]);
+    return result;
+  },
+
   /**
    * Render config properties for script-type alert definition
    * @method renderScriptConfigs
@@ -581,6 +652,9 @@ App.MainAlertDefinitionConfigsController = Em.Controller.extend({
     if (Em.get(propertiesToUpdate, 'AlertDefinition/source.uri.id')) {
       delete propertiesToUpdate['AlertDefinition/source'].uri.id;
     }
+    if (Em.get(propertiesToUpdate, 'AlertDefinition/source.ams.id')) {
+      delete propertiesToUpdate['AlertDefinition/source'].ams.id;
+    }
 
     // `source.parameters` is an array and should be updated separately from other configs
     if (this.get('content.parameters.length')) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b4adae5c/ambari-web/app/mappers/alert_definitions_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/alert_definitions_mapper.js b/ambari-web/app/mappers/alert_definitions_mapper.js
index 64c8c16..0b5e3a7 100644
--- a/ambari-web/app/mappers/alert_definitions_mapper.js
+++ b/ambari-web/app/mappers/alert_definitions_mapper.js
@@ -23,6 +23,7 @@ App.alertDefinitionsMapper = App.QuickDataMapper.create({
   reportModel: App.AlertReportDefinition,
   metricsSourceModel: App.AlertMetricsSourceDefinition,
   metricsUriModel: App.AlertMetricsUriDefinition,
+  metricsAmsModel: App.AlertMetricsAmsDefinition,
   parameterModel: App.AlertDefinitionParameter,
 
   config: {
@@ -77,6 +78,13 @@ App.alertDefinitionsMapper = App.QuickDataMapper.create({
     connection_timeout: 'AlertDefinition.source.uri.connection_timeout'
   },
 
+  amsConfig: {
+    id: 'AlertDefinition.source.ams.id',
+    value: 'AlertDefinition.source.ams.value',
+    minimal_value: 'AlertDefinition.source.ams.minimum_value',
+    interval: 'AlertDefinition.source.ams.interval'
+  },
+
   map: function (json) {
     console.time('App.alertDefinitionsMapper execution time');
     if (json && json.items) {
@@ -86,6 +94,7 @@ App.alertDefinitionsMapper = App.QuickDataMapper.create({
           alertReportDefinitions = [],
           alertMetricsSourceDefinitions = [],
           alertMetricsUriDefinitions = [],
+          alertMetricsAmsDefinitions = [],
           alertGroupsMap = App.cache.previousAlertGroupsMap,
           existingAlertDefinitions = App.AlertDefinition.find(),
           existingAlertDefinitionsMap = existingAlertDefinitions.toArray().toMapByProperty('id'),
@@ -207,6 +216,16 @@ App.alertDefinitionsMapper = App.QuickDataMapper.create({
           case 'RECOVERY':
             alertDefinitions.push($.extend(alertDefinition, this.parseIt(item, this.get('uriConfig'))));
             break;
+          case 'AMS':
+            // map App.AlertMetricsUriDefinition
+            alertDefinition.uri_id = item.AlertDefinition.id + 'uri';
+            alertDefinition.ams_id = item.AlertDefinition.id + 'ams';
+            item.AlertDefinition.source.uri.id = alertDefinition.uri_id;
+            item.AlertDefinition.source.ams.id = alertDefinition.ams_id;
+            alertMetricsUriDefinitions.push(this.parseIt(item, this.get('uriConfig')));
+            alertMetricsAmsDefinitions.push(this.parseIt(item, this.get('amsConfig')));
+            alertDefinitions.push(alertDefinition);
+            break;
           default:
             console.error('Incorrect Alert Definition type:', item.AlertDefinition);
         }
@@ -222,6 +241,7 @@ App.alertDefinitionsMapper = App.QuickDataMapper.create({
       App.store.loadMany(this.get('metricsSourceModel'), alertMetricsSourceDefinitions);
       this.setMetricsSourcePropertyLists(this.get('metricsSourceModel'), alertMetricsSourceDefinitions);
       App.store.loadMany(this.get('metricsUriModel'), alertMetricsUriDefinitions);
+      App.store.loadMany(this.get('metricsAmsModel'), alertMetricsAmsDefinitions);
       // this loadMany takes too much time
       App.store.loadMany(this.get('model'), alertDefinitions);
       this.setAlertDefinitionsRawSourceData(rawSourceData);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b4adae5c/ambari-web/app/models/alerts/alert_definition.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alerts/alert_definition.js b/ambari-web/app/models/alerts/alert_definition.js
index 5cdec61..245771e 100644
--- a/ambari-web/app/models/alerts/alert_definition.js
+++ b/ambari-web/app/models/alerts/alert_definition.js
@@ -56,6 +56,7 @@ App.AlertDefinition = DS.Model.extend({
   //relates only METRIC-type alert definition
   jmx: DS.belongsTo('App.AlertMetricsSourceDefinition'),
   ganglia: DS.belongsTo('App.AlertMetricsSourceDefinition'),
+  ams: DS.belongsTo('App.AlertMetricsAmsDefinition'),
   //relates only PORT-type alert definition
   defaultPort: DS.attr('number'),
   portUri: DS.attr('string'),
@@ -234,7 +235,8 @@ App.AlertDefinition = DS.Model.extend({
     'PORT': 'icon-signin',
     'AGGREGATE': 'icon-plus',
     'SERVER': 'icon-desktop',
-    'RECOVERY': 'icon-desktop'
+    'RECOVERY': 'icon-desktop',
+    'AMS': 'icon-rocket'
   },
 
   /**
@@ -311,8 +313,15 @@ App.AlertMetricsUriDefinition = DS.Model.extend({
   connectionTimeout: DS.attr('number')
 });
 
+App.AlertMetricsAmsDefinition = DS.Model.extend({
+  value: DS.attr('string'),
+  minimalValue: DS.attr('number'),
+  interval: DS.attr('number')
+});
+
 App.AlertDefinition.FIXTURES = [];
 App.AlertReportDefinition.FIXTURES = [];
 App.AlertMetricsSourceDefinition.FIXTURES = [];
 App.AlertMetricsUriDefinition.FIXTURES = [];
+App.AlertMetricsAmsDefinition.FIXTURES = [];
 App.AlertDefinitionParameter.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/ambari/blob/b4adae5c/ambari-web/test/controllers/installer_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/installer_test.js b/ambari-web/test/controllers/installer_test.js
index 85f5613..303c8a4 100644
--- a/ambari-web/test/controllers/installer_test.js
+++ b/ambari-web/test/controllers/installer_test.js
@@ -41,18 +41,6 @@ describe('App.InstallerController', function () {
     });
   });
 
-  describe('#loadStacksVersionsDefinitionsSuccessCallback', function() {
-    beforeEach(function () {
-      sinon.stub(App.store, 'commit', Em.K);
-    });
-    afterEach(function () {
-      App.store.commit.restore();
-    });
-    it ('Correct data', function() {
-      installerController.set('loadStacksRequestsCounter', 1);
-    });
-  });
-
   describe('#getCluster', function() {
     it ('Should return merged clusterStatusTemplate', function() {
       installerController.set('clusterStatusTemplate', {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b4adae5c/ambari-web/test/mappers/alert_definitions_mapper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mappers/alert_definitions_mapper_test.js b/ambari-web/test/mappers/alert_definitions_mapper_test.js
index 564bf1d..1c3ff60 100644
--- a/ambari-web/test/mappers/alert_definitions_mapper_test.js
+++ b/ambari-web/test/mappers/alert_definitions_mapper_test.js
@@ -100,6 +100,7 @@ describe('App.alertDefinitionsMapper', function () {
                 "https" : "{{yarn-site/yarn.resourcemanager.webapp.https.address}}",
                 "https_property" : "{{yarn-site/yarn.http.policy}}",
                 "https_property_value" : "HTTPS_ONLY",
+                "connection_timeout" : 5.0,
                 "default_port" : 0.0
               }
             }
@@ -191,6 +192,59 @@ describe('App.alertDefinitionsMapper', function () {
               "uri" : "{{zookeeper-env/clientPort}}"
             }
           }
+        },
+        {
+          "AlertDefinition" : {
+            "component_name" : "NAMENODE",
+            "description" : "This service-level alert is triggered if the NN heap usage deviation has grown beyond the specified threshold within a given time interval.",
+            "enabled" : true,
+            "help_url" : null,
+            "id" : 6,
+            "ignore_host" : false,
+            "interval" : 1,
+            "label" : "NameNode Heap Usage (Hourly)",
+            "name" : "namenode_free_heap_size_deviation_percentage",
+            "repeat_tolerance" : 1,
+            "repeat_tolerance_enabled" : true,
+            "scope" : "SERVICE",
+            "service_name" : "HDFS",
+            "source" : {
+              "ams" : {
+                "metric_list" : [
+                  "jvm.JvmMetrics.MemHeapUsedM",
+                  "jvm.JvmMetrics.MemHeapMaxM"
+                ],
+                "value" : "{1} - {0}",
+                "interval" : 60.0,
+                "compute" : "sample_standard_deviation_percentage",
+                "app_id" : "NAMENODE",
+                "minimum_value" : 1.0
+              },
+              "reporting" : {
+                "ok" : {
+                  "text" : "The sample standard deviation percentage is {0}%"
+                },
+                "warning" : {
+                  "text" : "The sample standard deviation percentage is {0}%",
+                  "value" : 20.0
+                },
+                "critical" : {
+                  "text" : "The sample standard deviation percentage is {0}%",
+                  "value" : 50.0
+                },
+                "units" : "%"
+              },
+              "type" : "AMS",
+              "uri" : {
+                "http" : "{{ams-site/timeline.metrics.service.webapp.address}}",
+                "https" : "{{ams-site/timeline.metrics.service.webapp.address}}",
+                "https_property" : "{{ams-site/timeline.metrics.service.http.policy}}",
+                "https_property_value" : "HTTPS_ONLY",
+                "default_port" : 0.0,
+                "connection_timeout" : 5.0
+              }
+            }
+          }
         }
       ]
     };
@@ -202,7 +256,8 @@ describe('App.alertDefinitionsMapper', function () {
         'parameterModel': {},
         'reportModel': {},
         'metricsSourceModel': {},
-        'metricsUriModel': {}
+        'metricsUriModel': {},
+        'metricsAmsModel': {}
       });
 
       sinon.stub(App.alertDefinitionsMapper, 'deleteRecord', Em.K);
@@ -230,7 +285,8 @@ describe('App.alertDefinitionsMapper', function () {
 
         'reportModel': App.AlertReportDefinition,
         'metricsSourceModel': App.AlertMetricsSourceDefinition,
-        'metricsUriModel': App.AlertMetricsUriDefinition
+        'metricsUriModel': App.AlertMetricsUriDefinition,
+        'metricsAmsModel': App.AlertMetricsAmsDefinition
       });
 
       App.alertDefinitionsMapper.deleteRecord.restore();
@@ -320,7 +376,8 @@ describe('App.alertDefinitionsMapper', function () {
           "http":"{{yarn-site/yarn.resourcemanager.webapp.address}}",
           "https":"{{yarn-site/yarn.resourcemanager.webapp.https.address}}",
           "https_property":"{{yarn-site/yarn.http.policy}}",
-          "https_property_value":"HTTPS_ONLY"
+          "https_property_value":"HTTPS_ONLY",
+          "connection_timeout" : 5.0
         }];
 
       beforeEach(function () {
@@ -433,6 +490,57 @@ describe('App.alertDefinitionsMapper', function () {
 
     });
 
+    describe('should parse AMS alertDefinitions', function () {
+
+      var data = {items: [json.items[5]]};
+      var expected = [
+        {
+          "id" : 6,
+          "interval" : 1,
+          "label" : "NameNode Heap Usage (Hourly)",
+          "name" : "namenode_free_heap_size_deviation_percentage",
+          "repeat_tolerance" : 1,
+          "repeat_tolerance_enabled" : true,
+          "scope" : "SERVICE",
+          "service_name" : "HDFS",
+          "component_name" : "NAMENODE",
+        }
+      ];
+
+      var expectedMetricsUri = [{
+        "id":"6uri",
+        "http" : "{{ams-site/timeline.metrics.service.webapp.address}}",
+        "https" : "{{ams-site/timeline.metrics.service.webapp.address}}",
+        "https_property" : "{{ams-site/timeline.metrics.service.http.policy}}",
+        "https_property_value" : "HTTPS_ONLY",
+        "connection_timeout" : 5.0
+      }];
+
+      var expectedAms = [{
+        "id": "6ams",
+        "value": "{1} - {0}",
+        "minimal_value": 1,
+        "interval": 60
+      }];
+
+      beforeEach(function () {
+        App.alertDefinitionsMapper.map(data);
+      });
+
+      it('should map definition', function () {
+        testHelpers.nestedExpect(expected, App.alertDefinitionsMapper.get('model.content'));
+      });
+
+      it('parse metrics uri', function() {
+        testHelpers.nestedExpect(expectedMetricsUri, App.alertDefinitionsMapper.get('metricsUriModel.content'));
+      });
+
+      it('parse ams parameters', function () {
+        testHelpers.nestedExpect(expectedAms, App.alertDefinitionsMapper.get('metricsAmsModel.content'));
+      });
+
+    });
+
     /*eslint-disable mocha-cleanup/complexity-it */
     it('should set groups from App.cache.previousAlertGroupsMap', function () {