Jelajahi Sumber

AMBARI-16873 Optimize UI error saving. (atkach)

Andrii Tkach 9 tahun lalu
induk
melakukan
606535d1aa

+ 1 - 0
ambari-web/app/assets/test/tests.js

@@ -48,6 +48,7 @@ var files = [
   'test/controllers/global/configuration_controller_test',
   'test/controllers/global/configuration_controller_test',
   'test/controllers/global/wizard_watcher_controller_test',
   'test/controllers/global/wizard_watcher_controller_test',
   'test/controllers/global/user_settings_controller_test',
   'test/controllers/global/user_settings_controller_test',
+  'test/controllers/global/errors_handler_controller_test',
   'test/controllers/main/alert_definitions_controller_test',
   'test/controllers/main/alert_definitions_controller_test',
   'test/controllers/main/alerts/alert_definitions_actions_controller_test',
   'test/controllers/main/alerts/alert_definitions_actions_controller_test',
   'test/controllers/main/alerts/definitions_configs_controller_test',
   'test/controllers/main/alerts/definitions_configs_controller_test',

+ 1 - 0
ambari-web/app/controllers/global/cluster_controller.js

@@ -190,6 +190,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, {
       return;
       return;
     }
     }
     App.router.get('userSettingsController').getAllUserSettings();
     App.router.get('userSettingsController').getAllUserSettings();
+    App.router.get('errorsHandlerController').loadErrorLogs();
     var clusterUrl = this.getUrl('/data/clusters/cluster.json', '?fields=Clusters');
     var clusterUrl = this.getUrl('/data/clusters/cluster.json', '?fields=Clusters');
     var hostsController = App.router.get('mainHostController');
     var hostsController = App.router.get('mainHostController');
     hostsController.set('isCountersUpdating', true);
     hostsController.set('isCountersUpdating', true);

+ 66 - 15
ambari-web/app/controllers/global/errors_handler_controller.js

@@ -19,27 +19,78 @@
 var App = require('app');
 var App = require('app');
 
 
 App.ErrorsHandlerController = Em.Controller.extend(App.UserPref, {
 App.ErrorsHandlerController = Em.Controller.extend(App.UserPref, {
+
+  name: 'errorsHandlerController',
+
+  /**
+  * @const
+  */
+  ERROR_STORAGE_SIZE: 500000,
+
+  /**
+  * @const
+  */
+  MAX_TRACE_LENGTH: 1000,
+
   init: function () {
   init: function () {
     var oldError = window.onerror || Em.K;
     var oldError = window.onerror || Em.K;
     var self = this;
     var self = this;
     window.onerror = function (err, url, lineNumber, colNumber, Err) {
     window.onerror = function (err, url, lineNumber, colNumber, Err) {
       oldError.call(this, err, url, lineNumber, colNumber, Err);
       oldError.call(this, err, url, lineNumber, colNumber, Err);
-      var ls = localStorage.getObject('errors') || {};
-      if(Object.keys(localStorage.getObject('errors')).length > 25) {
-        delete ls[Object.keys(ls).sort()[0]];
-      }
-      var key = new Date().getTime();
-      var val = {
-        file: url,
-        line: lineNumber,
-        col: colNumber,
-        error: err,
-        stackTrace: Em.get(Err || {}, 'stack')
-      };
-      ls[key] = val;
-      localStorage.setObject('errors', ls);
-      self.postUserPref(key, val);
+      self.saveErrorLogs(err, url, lineNumber, colNumber, Err);
     };
     };
     return this._super();
     return this._super();
+  },
+
+  /**
+   * load logs from server
+   */
+  loadErrorLogs: function() {
+    this.getUserPref('errors');
+  },
+
+  /**
+  * @method getUserPrefSuccessCallback
+  * @param {object|null} data
+  */
+  getUserPrefSuccessCallback: function(data) {
+    if (data) {
+      localStorage.setObject('errors', data);
+    }
+  },
+
+  /**
+   * save error logs to localStorage and server
+   * @param {string} err
+   * @param {string} url
+   * @param {number} lineNumber
+   * @param {number} colNumber
+   * @param {Error} Err
+   */
+  saveErrorLogs: function(err, url, lineNumber, colNumber, Err) {
+    var ls = localStorage.getObject('errors') || {};
+    var key = new Date().getTime();
+    var stackTrace = Em.get(Err || {}, 'stack');
+
+    if (stackTrace) {
+      stackTrace = stackTrace.replace(/http:\/\/.*:8080\/javascripts/g, "").substr(0, this.MAX_TRACE_LENGTH);
+    }
+
+    var val = {
+      file: url,
+      line: lineNumber,
+      col: colNumber,
+      error: err,
+      stackTrace: stackTrace
+    };
+
+    //overwrite errors if storage full
+    if (JSON.stringify(ls).length > this.ERROR_STORAGE_SIZE) {
+      delete ls[Object.keys(ls).sort()[0]];
+    }
+
+    ls[key] = val;
+    localStorage.setObject('errors', ls);
+    this.postUserPref('errors', ls);
   }
   }
 });
 });

+ 69 - 0
ambari-web/test/controllers/global/errors_handler_controller_test.js

@@ -0,0 +1,69 @@
+/**
+ * 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.
+ */
+
+
+var App = require('app');
+
+require('controllers/global/errors_handler_controller');
+
+describe('App.ErrorsHandlerController', function () {
+  var controller;
+
+  beforeEach(function() {
+    controller = App.ErrorsHandlerController.create();
+  });
+
+  describe("#loadErrorLogs()", function () {
+
+    beforeEach(function() {
+      sinon.stub(controller, 'getUserPref');
+    });
+
+    afterEach(function() {
+      controller.getUserPref.restore();
+    });
+
+    it("getUserPref should be called", function() {
+      controller.loadErrorLogs();
+      expect(controller.getUserPref.calledWith('errors')).to.be.true;
+    });
+  });
+
+  describe("#saveErrorLogs()", function () {
+
+    beforeEach(function() {
+      sinon.stub(controller, 'postUserPref');
+    });
+
+    afterEach(function() {
+      controller.postUserPref.restore();
+    });
+
+    it("postUserPref should be called", function() {
+      controller.saveErrorLogs('err', 'url', 1, 2, {});
+      var args = controller.postUserPref.getCall(0).args;
+      expect(JSON.stringify(args[1][Object.keys(args[1])[0]])).to.be.equal(JSON.stringify({
+        "file": "url",
+        "line": 1,
+        "col": 2,
+        "error": "err"
+      }));
+      expect(args[0]).to.be.equal('errors');
+    });
+  });
+});