You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sr...@apache.org on 2014/11/01 22:31:07 UTC
git commit: AMBARI-8100. Flume UI freezes in 1 minute on a 400 node
cluster (atkach via srimanth)
Repository: ambari
Updated Branches:
refs/heads/branch-1.7.0 3ddf4f1c5 -> 7106b5b48
AMBARI-8100. Flume UI freezes in 1 minute on a 400 node cluster (atkach via srimanth)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7106b5b4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7106b5b4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7106b5b4
Branch: refs/heads/branch-1.7.0
Commit: 7106b5b484b51575de8663e73d05cfab06b566d7
Parents: 3ddf4f1
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Sat Nov 1 14:09:31 2014 -0700
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Sat Nov 1 14:17:20 2014 -0700
----------------------------------------------------------------------
.../app/controllers/main/alerts_controller.js | 4 +-
ambari-web/app/data/service_graph_config.js | 4 +-
ambari-web/app/models/alert.js | 5 +-
ambari-web/app/utils/helper.js | 4 +-
.../app/views/main/service/info/summary.js | 79 +++++-
.../views/main/service/info/summary_test.js | 240 +++++++++++++++++--
6 files changed, 297 insertions(+), 39 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/7106b5b4/ambari-web/app/controllers/main/alerts_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts_controller.js b/ambari-web/app/controllers/main/alerts_controller.js
index 0ea7212..4535394 100644
--- a/ambari-web/app/controllers/main/alerts_controller.js
+++ b/ambari-web/app/controllers/main/alerts_controller.js
@@ -142,13 +142,15 @@ App.MainAlertsController = Em.Controller.extend({
if (json && json.alerts && json.alerts.detail) {
json.alerts.detail.forEach(function (_alert) {
alerts.pushObject(App.Alert.create({
+ id: _alert.description + "_" + _alert.host_name + "_" + _alert.serviceType,
title: _alert.description,
serviceType: _alert.service_name,
lastTime: _alert.status_time,
status: this.get('statusNumberMap')[_alert.status] || "4",
message: _alert.output,
hostName: _alert.host_name,
- lastCheck: _alert.last_status_time
+ lastCheck: _alert.last_status_time,
+ isLoaded: true
}));
}, this);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7106b5b4/ambari-web/app/data/service_graph_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/service_graph_config.js b/ambari-web/app/data/service_graph_config.js
index d845e51..1d93ddd 100644
--- a/ambari-web/app/data/service_graph_config.js
+++ b/ambari-web/app/data/service_graph_config.js
@@ -80,8 +80,8 @@ App.service_graph_config = {
'Flume_OutgoingSum',
'Flume_GarbageCollection',
'Flume_JVMHeapUsed',
- 'Flume_JVMThreadsRunnable',
- 'Flume_CPUUser'
+ 'Flume_JVMThreadsRunnable'
+ //'Flume_CPUUser'
],
'storm': [
http://git-wip-us.apache.org/repos/asf/ambari/blob/7106b5b4/ambari-web/app/models/alert.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alert.js b/ambari-web/app/models/alert.js
index 9a5281e..2886dff 100644
--- a/ambari-web/app/models/alert.js
+++ b/ambari-web/app/models/alert.js
@@ -128,10 +128,11 @@ App.Alert = Em.Object.extend({
}.property('date', 'status'),
makeTimeAtleastMinuteAgo: function(d){
- var diff = App.dateTime() - d.getTime();
+ var time = d.getTime();
+ var diff = App.dateTime() - time;
if (diff < 60000) {
diff = 60000 - diff;
- return new Date(d.getTime() - diff );
+ return new Date(time - diff);
}
return d;
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/7106b5b4/ambari-web/app/utils/helper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/helper.js b/ambari-web/app/utils/helper.js
index 90d67eb..5a25b8f 100644
--- a/ambari-web/app/utils/helper.js
+++ b/ambari-web/app/utils/helper.js
@@ -517,7 +517,7 @@ App.format = {
*/
App.popover = function (self, options) {
self.popover(options);
- self.on("remove DOMNodeRemoved", function () {
+ self.on("remove", function () {
$(this).trigger('mouseleave');
});
};
@@ -533,7 +533,7 @@ App.popover = function (self, options) {
App.tooltip = function (self, options) {
self.tooltip(options);
/* istanbul ignore next */
- self.on("remove DOMNodeRemoved", function () {
+ self.on("remove", function () {
$(this).trigger('mouseleave');
});
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7106b5b4/ambari-web/app/views/main/service/info/summary.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/info/summary.js b/ambari-web/app/views/main/service/info/summary.js
index 647ff3c..b70147b 100644
--- a/ambari-web/app/views/main/service/info/summary.js
+++ b/ambari-web/app/views/main/service/info/summary.js
@@ -38,6 +38,14 @@ App.MainServiceInfoSummaryView = Em.View.extend({
templateName: require('templates/main/service/info/summary'),
attributes:null,
/**
+ * alerts collection
+ */
+ alerts: [],
+ /**
+ * associative collection of alerts
+ */
+ alertsMap: {},
+ /**
* @property {String} templatePathPrefix - base path for custom templates
* if you want to add custom template, add <service_name>.hbs file to
* templates/main/service/info/summary folder.
@@ -82,9 +90,60 @@ App.MainServiceInfoSummaryView = Em.View.extend({
}.property('App.services.hasClient'),
alertsControllerBinding: 'App.router.mainAlertsController',
- alerts: function () {
- return this.get('alertsController.alerts');
- }.property('alertsController.alerts'),
+ /**
+ * observes changes to alerts collection
+ */
+ observeAlerts: function () {
+ var newAlerts = this.get('alertsController.alerts'),
+ currentAlerts = this.get('alerts'),
+ alertsMap;
+
+ if (currentAlerts.length === 0) {
+ alertsMap = {};
+ newAlerts.forEach(function (alert) {
+ alertsMap[alert.id] = alert;
+ currentAlerts.pushObject(alert);
+ }, this);
+ this.set('alertsMap', alertsMap);
+ } else if (newAlerts.length > 0) {
+ this.updateAlerts(newAlerts, currentAlerts);
+ } else {
+ currentAlerts.clear();
+ this.set('alertsMap', {});
+ }
+ }.observes('alertsController.alerts'),
+ /**
+ * update existing alerts according to new data
+ * @param newAlerts
+ * @param currentAlerts
+ */
+ updateAlerts: function (newAlerts, currentAlerts) {
+ var alertsMap = this.get('alertsMap');
+ var mutableFields = ['status', 'message', 'lastCheck', 'lastTime'];
+ // minimal time difference to apply changes to "lastTime" property
+ var minTimeDiff = 60000;
+ var curTime = App.dateTime();
+ currentAlerts.setEach('isLoaded', false);
+
+ newAlerts.forEach(function (alert) {
+ var currentAlert = alertsMap[alert.get('id')];
+ if (currentAlert) {
+ mutableFields.forEach(function (field) {
+ if (currentAlert.get(field) !== alert.get(field)) {
+ currentAlert.set(field, alert.get(field));
+ }
+ });
+ currentAlert.set('isLoaded', true);
+ } else {
+ alertsMap[alert.get('id')] = alert;
+ currentAlerts.pushObject(alert);
+ }
+ });
+ currentAlerts.filterProperty('isLoaded', false).slice(0).forEach(function (alert) {
+ delete alertsMap[alert.get('id')];
+ currentAlerts.removeObject(alert);
+ }, this);
+ },
noTemplateService: function () {
var serviceName = this.get("service.serviceName");
@@ -116,11 +175,13 @@ App.MainServiceInfoSummaryView = Em.View.extend({
if (service.get("id") == "ZOOKEEPER" || service.get("id") == "FLUME") {
var servers = service.get('hostComponents').filterProperty('isMaster');
if (servers.length > 0) {
- result = [{
- 'host': servers[0].get('displayName'),
- 'isComma': false,
- 'isAnd': false
- }];
+ result = [
+ {
+ 'host': servers[0].get('displayName'),
+ 'isComma': false,
+ 'isAnd': false
+ }
+ ];
}
if (servers.length > 1) {
result[0].isComma = true;
@@ -435,6 +496,8 @@ App.MainServiceInfoSummaryView = Em.View.extend({
},
willDestroyElement: function(){
this.get('alertsController').set('isUpdating', false);
+ this.get('alerts').clear();
+ this.set('alertsMap', {});
},
setAlertsWindowSize: function() {
http://git-wip-us.apache.org/repos/asf/ambari/blob/7106b5b4/ambari-web/test/views/main/service/info/summary_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/info/summary_test.js b/ambari-web/test/views/main/service/info/summary_test.js
index 7e30f29..e29e532 100644
--- a/ambari-web/test/views/main/service/info/summary_test.js
+++ b/ambari-web/test/views/main/service/info/summary_test.js
@@ -22,7 +22,7 @@ require('views/main/service/info/summary');
describe('App.MainServiceInfoSummaryView', function() {
- var mainServiceInfoSummaryView = App.MainServiceInfoSummaryView.create({
+ var view = App.MainServiceInfoSummaryView.create({
monitorsLiveTextView: Em.View.create(),
controller: Em.Object.create({
content: Em.Object.create({
@@ -30,16 +30,17 @@ describe('App.MainServiceInfoSummaryView', function() {
serviceName: 'HDFS',
hostComponents: []
})
- })
+ }),
+ alertsController: Em.Object.create()
});
describe('#servers', function () {
it('services shuldn\'t have servers except FLUME and ZOOKEEPER', function () {
- expect(mainServiceInfoSummaryView.get('servers')).to.be.empty;
+ expect(view.get('servers')).to.be.empty;
});
it('if one server exists then first server should have isComma and isAnd property false', function () {
- mainServiceInfoSummaryView.set('controller.content', Em.Object.create({
+ view.set('controller.content', Em.Object.create({
id: 'ZOOKEEPER',
serviceName: 'ZOOKEEPER',
hostComponents: [
@@ -49,12 +50,12 @@ describe('App.MainServiceInfoSummaryView', function() {
})
]
}));
- expect(mainServiceInfoSummaryView.get('servers').objectAt(0).isComma).to.equal(false);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(0).isAnd).to.equal(false);
+ expect(view.get('servers').objectAt(0).isComma).to.equal(false);
+ expect(view.get('servers').objectAt(0).isAnd).to.equal(false);
});
it('if more than one servers exist then first server should have isComma - true and isAnd - false', function () {
- mainServiceInfoSummaryView.set('controller.content', Em.Object.create({
+ view.set('controller.content', Em.Object.create({
id: 'ZOOKEEPER',
serviceName: 'ZOOKEEPER',
hostComponents: [
@@ -68,14 +69,14 @@ describe('App.MainServiceInfoSummaryView', function() {
})
]
}));
- expect(mainServiceInfoSummaryView.get('servers').objectAt(0).isComma).to.equal(true);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(0).isAnd).to.equal(false);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(1).isComma).to.equal(false);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(1).isAnd).to.equal(false);
+ expect(view.get('servers').objectAt(0).isComma).to.equal(true);
+ expect(view.get('servers').objectAt(0).isAnd).to.equal(false);
+ expect(view.get('servers').objectAt(1).isComma).to.equal(false);
+ expect(view.get('servers').objectAt(1).isAnd).to.equal(false);
});
it('if more than two servers exist then second server should have isComma - false and isAnd - true', function () {
- mainServiceInfoSummaryView.set('controller.content', Em.Object.create({
+ view.set('controller.content', Em.Object.create({
id: 'ZOOKEEPER',
serviceName: 'ZOOKEEPER',
hostComponents: [
@@ -93,12 +94,12 @@ describe('App.MainServiceInfoSummaryView', function() {
})
]
}));
- expect(mainServiceInfoSummaryView.get('servers').objectAt(0).isComma).to.equal(true);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(0).isAnd).to.equal(false);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(1).isComma).to.equal(false);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(1).isAnd).to.equal(true);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(2).isComma).to.equal(false);
- expect(mainServiceInfoSummaryView.get('servers').objectAt(2).isAnd).to.equal(false);
+ expect(view.get('servers').objectAt(0).isComma).to.equal(true);
+ expect(view.get('servers').objectAt(0).isAnd).to.equal(false);
+ expect(view.get('servers').objectAt(1).isComma).to.equal(false);
+ expect(view.get('servers').objectAt(1).isAnd).to.equal(true);
+ expect(view.get('servers').objectAt(2).isComma).to.equal(false);
+ expect(view.get('servers').objectAt(2).isAnd).to.equal(false);
});
});
@@ -107,21 +108,212 @@ describe('App.MainServiceInfoSummaryView', function() {
it("should return a single array with the items in the fom of '<name>.extend()' when the number of items is less than 4", function() {
var graphs = ['HDFS_SpaceUtilization'];
- expect(mainServiceInfoSummaryView.constructGraphObjects(graphs).length).to.equal(1);
- expect(mainServiceInfoSummaryView.constructGraphObjects(graphs)[0].length).to.equal(1);
+ expect(view.constructGraphObjects(graphs).length).to.equal(1);
+ expect(view.constructGraphObjects(graphs)[0].length).to.equal(1);
});
it("should return an array with arrays that are grouped into sizes of 4 or less when number of items is greater than 4", function() {
var graphs = ['HDFS_SpaceUtilization', 'YARN_AllocatedMemory', 'MapReduce_JobsStatus',
'HBASE_ClusterRequests', 'Flume_ChannelSizeMMA'];
- expect(mainServiceInfoSummaryView.constructGraphObjects(graphs).length).to.equal(2);
- expect(mainServiceInfoSummaryView.constructGraphObjects(graphs)[0].length).to.equal(4);
- expect(mainServiceInfoSummaryView.constructGraphObjects(graphs)[1].length).to.equal(1);
+ expect(view.constructGraphObjects(graphs).length).to.equal(2);
+ expect(view.constructGraphObjects(graphs)[0].length).to.equal(4);
+ expect(view.constructGraphObjects(graphs)[1].length).to.equal(1);
});
it("should return an empty array if the graphs array provided is empty", function() {
- expect(mainServiceInfoSummaryView.constructGraphObjects([])).to.be.empty;
+ expect(view.constructGraphObjects([])).to.be.empty;
+ });
+ });
+
+ describe("#observeAlerts()", function() {
+ it("No alerts loaded", function() {
+ var alerts = [];
+ view.set('alertsController.alerts', []);
+ view.set('alerts', alerts)
+ view.observeAlerts();
+
+ expect(alerts).to.be.empty;
+ expect(view.get('alertsMap')).to.be.empty;
+ });
+ it("One alert loaded", function() {
+ var alerts = [];
+ view.set('alertsController.alerts', [{
+ id: 1
+ }]);
+ view.set('alerts', alerts)
+ view.observeAlerts();
+
+ expect(alerts[0]).to.be.eql({
+ "id": 1
+ });
+ expect(alerts.length).to.be.equal(1);
+ expect(view.get('alertsMap')).to.be.eql({"1": {
+ "id": 1
+ }});
+ });
+ it("No new alerts", function() {
+ var alerts = [{id: 1}];
+ view.set('alertsController.alerts', []);
+ view.set('alerts', alerts)
+ view.set('alertsMap', {'1': {id: '1'}});
+ view.observeAlerts();
+
+ expect(alerts).to.be.empty;
+ expect(view.get('alertsMap')).to.be.empty;
+ });
+ before(function () {
+ sinon.stub(view, 'updateAlerts', Em.K);
+ });
+ after(function () {
+ view.updateAlerts.restore();
+ });
+ it("Alerts already exist", function() {
+ var alerts = [{id: 1}];
+ view.set('alertsController.alerts', [{
+ id: 1
+ }]);
+ view.set('alerts', alerts)
+ view.set('alertsMap', {'1': {id: '1'}});
+ view.observeAlerts();
+
+ expect(view.updateAlerts.calledWith(
+ [{
+ id: 1
+ }],
+ [{id: 1}]
+ )).to.be.true;
+ });
+ });
+
+ describe("#updateAlerts()", function() {
+ var currentAlerts = [];
+ var alertsMap = {};
+ var newAlerts = [];
+ it("Add new alert", function() {
+ newAlerts.clear();
+ currentAlerts.clear();
+ alertsMap = {};
+
+ newAlerts.pushObjects([
+ Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ }),
+ Em.Object.create({
+ id: '2',
+ status: '2',
+ isLoaded: true
+ })
+ ]);
+ var currentAlert = Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ });
+ alertsMap['1'] = currentAlert;
+ view.set('alertsMap', alertsMap);
+ currentAlerts.pushObject(currentAlert);
+
+ view.updateAlerts(newAlerts, currentAlerts);
+ expect(currentAlerts.length).to.be.equal(2);
+ expect(currentAlerts[1]).to.be.eql(Em.Object.create({
+ id: '2',
+ status: '2',
+ isLoaded: true
+ }));
+ expect(alertsMap).to.be.eql({
+ "1": Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ }),
+ "2": Em.Object.create({
+ id: '2',
+ status: '2',
+ isLoaded: true
+ })
+ });
+ });
+ it("Update properties of existing alert", function() {
+ newAlerts.clear();
+ currentAlerts.clear();
+ alertsMap = {};
+
+ newAlerts.pushObjects([
+ Em.Object.create({
+ id: '1',
+ status: '2',
+ isLoaded: true
+ })
+ ]);
+ var currentAlert = Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ });
+ alertsMap['1'] = currentAlert;
+ view.set('alertsMap', alertsMap);
+ currentAlerts.pushObject(currentAlert);
+
+ view.updateAlerts(newAlerts, currentAlerts);
+ expect(currentAlerts.length).to.be.equal(1);
+ expect(currentAlerts[0]).to.be.eql(Em.Object.create({
+ id: '1',
+ status: '2',
+ isLoaded: true
+ }));
+ expect(alertsMap).to.be.eql({
+ "1": Em.Object.create({
+ id: '1',
+ status: '2',
+ isLoaded: true
+ })
+ });
+ });
+ it("delete old alert", function() {
+ newAlerts.clear();
+ currentAlerts.clear();
+ alertsMap = {};
+
+ newAlerts.pushObjects([
+ Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ })
+ ]);
+ var currentAlert1 = Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ });
+ var currentAlert2 = Em.Object.create({
+ id: '2',
+ status: '2',
+ isLoaded: true
+ });
+ alertsMap["1"] = currentAlert1;
+ alertsMap["2"] = currentAlert2;
+ view.set('alertsMap', alertsMap);
+ currentAlerts.pushObjects([currentAlert1, currentAlert2]);
+
+ view.updateAlerts(newAlerts, currentAlerts);
+
+ expect(currentAlerts.length).to.be.equal(1);
+ expect(currentAlerts[0]).to.be.eql(Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ }));
+ expect(alertsMap).to.be.eql({
+ "1": Em.Object.create({
+ id: '1',
+ status: '1',
+ isLoaded: true
+ })
+ });
});
});
});
\ No newline at end of file