[fusion-commits] r2822 - in sandbox/robust_error_handling: layers/MapGuide lib text widgets

svn_fusion at osgeo.org svn_fusion at osgeo.org
Thu Nov 28 03:57:21 PST 2013


Author: jng
Date: 2013-11-28 03:57:21 -0800 (Thu, 28 Nov 2013)
New Revision: 2822

Modified:
   sandbox/robust_error_handling/layers/MapGuide/MapGuide.js
   sandbox/robust_error_handling/lib/ApplicationDefinition.js
   sandbox/robust_error_handling/lib/Error.js
   sandbox/robust_error_handling/lib/MGBroker.js
   sandbox/robust_error_handling/lib/Widget.js
   sandbox/robust_error_handling/lib/fusion.js
   sandbox/robust_error_handling/text/en.json
   sandbox/robust_error_handling/widgets/MapMetadata.js
Log:
#576: 
 - Add a new Fusion.DetailedError class that contains more detailed information (eg. stack traces) than a standard Fusion.Error does
 - Setup TraceKit in Fusion.initialize().TraceKit is the magic library that gives us much more robust error handling with more detailed errors. TraceKit's default subscriber is Fusion.reportError(). Errors that go through TraceKit's subscriber are wrapped into Fusion.DetailError objects before being sent to Fusion.reportError()
 - Add a new Fusion.reportFatalError() API that triggers TraceKit's error reporting resulting in Fusion.DetailedError objects being sent to Fusion.reportError(). Update the reportError() API docs to *discourage* use of this API for reporting fatal errors.
 - Update all instances of Fusion.reportError() on fatal errors to use Fusion.reportFatalError() instead.
 - Route all failures in MGBroker to Fusion.ajaxException(). Fusion.ajaxException() now uses detailed error reporting via TraceKit, so AJAX errors now not only contain the error response, but also the client-side stack trace that caused it as well. This is important as previously, use of browser developer tools was almost always required to get both pieces of information (server and client error details)

Modified: sandbox/robust_error_handling/layers/MapGuide/MapGuide.js
===================================================================
--- sandbox/robust_error_handling/layers/MapGuide/MapGuide.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/layers/MapGuide/MapGuide.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -186,7 +186,7 @@
         if (xhr.status == 200) {
             var o = Fusion.parseJSON(xhr.responseText);
             if (o.success === false) {
-                Fusion.reportError(o.message);
+                Fusion.reportFatalError(o.message);
             } else {
                 var version = o.siteVersion;
                 var bits = version.split('.');
@@ -704,9 +704,8 @@
     },
 
     reloadFailed: function(r) {
-      Fusion.reportError( new Fusion.Error(Fusion.Error.FATAL,
-        OpenLayers.i18n('mapLoadError', {'error':r.transport.responseText})));
-      this.mapWidget._removeWorker();
+        this.mapWidget._removeWorker();
+        Fusion.reportFatalError(OpenLayers.i18n('mapLoadError', {'error':r.transport.responseText}));
     },
 
     /**
@@ -1616,13 +1615,13 @@
     },
     
     checkPingResponse: function(xhr) {
-      if (xhr.responseText) {
-        var o = Fusion.parseJSON(xhr.responseText);
-        if (!o.success) {
-          Fusion.reportError(o.message);
-          clearInterval(this.keepAliveTimer);
+        if (xhr.responseText) {
+            var o = Fusion.parseJSON(xhr.responseText);
+            if (!o.success) {
+                clearInterval(this.keepAliveTimer);
+                Fusion.reportFatalError(o.message);
+            }
         }
-      }
     },
 
     getLinkParams: function() {

Modified: sandbox/robust_error_handling/lib/ApplicationDefinition.js
===================================================================
--- sandbox/robust_error_handling/lib/ApplicationDefinition.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/lib/ApplicationDefinition.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -139,7 +139,10 @@
     createSessionThenGetAppDef: function() {
       var sl = Fusion.getScriptLanguage();
       var scriptURL = 'layers/' + 'MapGuide' + '/' + sl + '/CreateSession.' + sl;
-      var options = {onSuccess: OpenLayers.Function.bind(this.createSessionThenGetAppDefCB, this)};
+      var options = {
+        onSuccess: OpenLayers.Function.bind(this.createSessionThenGetAppDefCB, this),
+        onFailure: OpenLayers.Function.bind(Fusion.ajaxException, Fusion)
+      };
       Fusion.ajaxRequest(scriptURL, options);
     },
 
@@ -194,8 +197,7 @@
                 }
             }
         } else {
-          Fusion.reportError(new Fusion.Error(Fusion.Error.FATAL,
-                        OpenLayers.i18n('appDefParseError')));
+            Fusion.reportFatalError(OpenLayers.i18n('appDefParseError'));
         }
 
         /* process WIDGET sets */
@@ -205,8 +207,7 @@
                 this.widgetSets.push(widgetSet);
             }
         } else {
-          Fusion.reportError(new Fusion.Error(Fusion.Error.FATAL,
-                      OpenLayers.i18n('widgetSetParseError')));
+            Fusion.reportFatalError(OpenLayers.i18n('widgetSetParseError'));
         }
 
         /* process extensions */

Modified: sandbox/robust_error_handling/lib/Error.js
===================================================================
--- sandbox/robust_error_handling/lib/Error.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/lib/Error.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -61,6 +61,25 @@
     }
 });
 
+Fusion.DetailedError = OpenLayers.Class({
+    message: null,
+    name: null,
+    incomplete: true,
+    partial: true,
+    stack: [],
+    url: null,
+    useragent: null,
+    initialize: function(o) {
+        this.message = o.message;
+        this.name = o.name || "Error";
+        this.incomplete = o.incomplete;
+        this.partial = o.partial;
+        this.stack = o.stack;
+        this.url = o.url;
+        this.useragent = o.useragent;
+    }
+});
+
 Fusion.Error.FATAL = 0;
 Fusion.Error.WARNING = 1;
 Fusion.Error.NOTICE = 2;

Modified: sandbox/robust_error_handling/lib/MGBroker.js
===================================================================
--- sandbox/robust_error_handling/lib/MGBroker.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/lib/MGBroker.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -79,6 +79,9 @@
         if (this.method) {
             r.options.method = this.method;
         }
+        if (!r.options.onException) {
+            r.options.onException = OpenLayers.Function.bind(Fusion.ajaxException, Fusion);
+        }
         var a = new OpenLayers.Ajax.Request( this.mapAgentURL, 
             OpenLayers.Util.extend({parameters:r.parameters, onComplete:f }, r.options));
         a.originalRequest = r;

Modified: sandbox/robust_error_handling/lib/Widget.js
===================================================================
--- sandbox/robust_error_handling/lib/Widget.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/lib/Widget.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -229,7 +229,7 @@
             return map.aMaps[i];
           }
         }
-        Fusion.reportError("Requested widgetLayerId not found:"+this.widgetLayerId);
+        Fusion.reportFatalError("Requested widgetLayerId not found:"+this.widgetLayerId);
         return null;
       } else {
         return this.getMap().aMaps[0];

Modified: sandbox/robust_error_handling/lib/fusion.js
===================================================================
--- sandbox/robust_error_handling/lib/fusion.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/lib/fusion.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -336,6 +336,8 @@
          *           
          */
         initialize: function(options) {
+            TraceKit.report.subscribe(OpenLayers.Function.bind(this.onTraceKitError, this));
+        
             options = options || {};
             var sessionIdParam = this.getQueryParam('Session');
             // Override the pre-created sessionId by user specified sessionId(if exist)
@@ -416,6 +418,10 @@
           OpenLayers.Lang[this.locale] = OpenLayers.Util.extend(OpenLayers.Lang[this.locale],Fusion.Strings[this.locale]);
         },
     
+        onTraceKitError: function(err) {
+            Fusion.reportError(new Fusion.DetailedError(err));
+        },
+    
         /**
          * Function: setLoadState
          *
@@ -441,11 +447,10 @@
                 case this.LOAD_COMPLETE:
                     //console.log('load complete');
                     if (this.applicationDefinition) {
-                      this.applicationDefinition.create();
-                      this.triggerEvent(Fusion.Event.FUSION_INITIALIZED);
+                        this.applicationDefinition.create();
+                        this.triggerEvent(Fusion.Event.FUSION_INITIALIZED);
                     } else {
-                      Fusion.reportError(new Fusion.Error(Fusion.Error.FATAL, 
-                                          'failed to create AppDef object'));
+                        Fusion.reportFatalError('failed to create AppDef object');
                     }
                     break;
             }
@@ -534,8 +539,7 @@
          * so we need to decide how to inform the user and fail gracefully.
          */
         scriptFailed: function(url) {
-            Fusion.reportError(new Fusion.Error(Fusion.Error.FATAL, 
-                              OpenLayers.i18n('scriptFailed',{'script':url})));
+            Fusion.reportFatalError(OpenLayers.i18n('scriptFailed',{'script':url}));
         },
     
         /**
@@ -739,12 +743,15 @@
          * e - {Exception}
          */
         ajaxException: function(r, e) {
-            this.reportError(new Fusion.Error(Fusion.Error.WARNING, 
-                OpenLayers.i18n('ajaxError', {'exception':e.message, 
+            try {
+                throw new Error(OpenLayers.i18n('ajaxError', {'exception':e.message, 
                                               'filename':e.fileName, 
                                               'line':e.lineNumber,
                                               'response': r.transport.responseText
-                                              })));
+                                              }));
+            } catch (e) {
+                TraceKit.report(e);
+            }
         },
     
          /**
@@ -822,8 +829,7 @@
                 if (msg == "") {
                     msg = OpenLayers.i18n('serverNotAvailable');
                 }
-                Fusion.reportError(new Fusion.Error(Fusion.Error.FATAL,
-                  OpenLayers.i18n('invalidXMLDocument', {'msg':msg, 'url':r.request.url})));
+                Fusion.reportFatalError(OpenLayers.i18n('invalidXMLDocument', {'msg':msg, 'url':r.request.url}));
                 return;
             }
 
@@ -1076,17 +1082,43 @@
         require: function(url) { this.queueScript(url); },
     
         /**
+         * Function: reportFatalError
+         *
+         * Triggers the <Fusion.Event.FUSION_ERROR> and passes along a <Fusion.DetailedError>
+         * object to the callback functions registered for this event.  Widgets
+         * call <Fusion.reportError> to inform the system of errors.
+         * Applications will typically register an event listener for the error
+         * event and do something to report the error to the user.  
+         * By default, errors are not reported since there is no listener
+         *
+         * Unlike reportError, errors reported through reportFatalError carry valuable information
+         * such as stack traces, which errors sent via reportError will not contain
+         *
+         * Parameters:
+         * msg - {String} The error message
+         */
+        reportFatalError: function(msg) {
+            try {
+                throw new Error(msg);
+            } catch (e) {
+                TraceKit.report(e);
+            }
+        },
+    
+        /**
          * Function: reportError
          *
          * Triggers the <Fusion.Event.FUSION_ERROR> and passes along the error
          * object to the callback functions registered for this event.  Widgets
-         * call MFusion.reportError> to inform the system of errors.
+         * call <Fusion.reportError> to inform the system of errors.
          * Applications will typically register an event listener for the error
          * event and do something to report the error to the user.  
          * By default, errors are not reported since there is no listener
          *
+         * For fatal errors, it is recommended to use reportFatalError instead
+         *
          * Parameters:
-         * o - {Object} the error object which is typically a string
+         * o - {Object} the error object which is typically a string or a <Fusion.Error> object
          */
         reportError: function(o) { this.triggerEvent(Fusion.Event.FUSION_ERROR, o); },
     
@@ -1499,7 +1531,8 @@
     window._FusionLocale = locale;
     
     if (!Fusion._singleFile) {
-        var coreScripts = [ 'lib/jxLib/jxlib.uncompressed.js', //JxLib has first dibs on any globals
+        var coreScripts = [ 'lib/TraceKit/TraceKit.js',
+                            'lib/jxLib/jxlib.uncompressed.js',
                             'lib/Proj4js/proj4js-combined.js',
                             'layers/MapGuide/php/csmap2proj4.js',
                             'lib/OpenLayers/OpenLayers.js',

Modified: sandbox/robust_error_handling/text/en.json
===================================================================
--- sandbox/robust_error_handling/text/en.json	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/text/en.json	2013-11-28 11:57:21 UTC (rev 2822)
@@ -4,7 +4,10 @@
 'configLoadError': 'Error loading fusion configuration file, initialization aborted.' +
                   'Make sure that you have copied config_dist.json to config.json ' +
                   'and have configured the settings for your system',
+'pingFailure': 'Failed to keep session alive: ${message}',
+'createSessionFailure': 'Failed to create session: ${message}',
 'ajaxError': 'Exception occurred in AJAX callback.\nMessage: ${exception}\nLocation: ${filename} (${line})\nResponse: ${response}',
+'detailedErrorTemplateHtml': '<h3>${name}</h3><br/>Error Details:<pre>${message}</pre><br/>Stack Trace:<br/><pre>${stacktrace}</pre><br/>Source: <pre>${source}</pre>',
 'importFailed': 'failed to import stylesheet: ${url}',
 'serverNotAvailable': '<h2>Server not available. Try to reload the application. If this problem persists, please contact the administrator</h2>',
 'invalidXMLDocument': 'xml2json: invalid XML document: ${msg} : ${url}',

Modified: sandbox/robust_error_handling/widgets/MapMetadata.js
===================================================================
--- sandbox/robust_error_handling/widgets/MapMetadata.js	2013-11-28 09:12:58 UTC (rev 2821)
+++ sandbox/robust_error_handling/widgets/MapMetadata.js	2013-11-28 11:57:21 UTC (rev 2822)
@@ -50,7 +50,7 @@
         if (json.MetadataId) {
           this.metadataId =  json.MetadataId[0];
         } else {
-          Fusion.reportError( new Fusion.Error(Fusion.Error.FATAL,"MetadataId is a required parameter for mapMetadata widget"));
+          Fusion.reportFatalError( "MetadataId is a required parameter for mapMetadata widget");
         }
         if (json.Content) {
           this.content = json.Content[0];



More information about the fusion-commits mailing list