Bug 1500062 - Add error logging middleware to new aboutdebugging;r=ladybenko,daisuke
authorJulian Descottes <jdescottes@mozilla.com>
Wed, 24 Oct 2018 17:24:56 +0000
changeset 491175 3a7ba1fe0277d580a678b86ab92d4496d4fe6681
parent 491174 798b3777f30f4170fb094e1acce33eb70dcbd44a
child 491176 cc08f0f9cd01231b0b55f77cfc26b2b18c9d23bb
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersladybenko, daisuke
bugs1500062
milestone65.0a1
Bug 1500062 - Add error logging middleware to new aboutdebugging;r=ladybenko,daisuke Differential Revision: https://phabricator.services.mozilla.com/D9089
devtools/client/aboutdebugging-new/src/actions/debug-targets.js
devtools/client/aboutdebugging-new/src/actions/runtimes.js
devtools/client/aboutdebugging-new/src/actions/ui.js
devtools/client/aboutdebugging-new/src/create-store.js
devtools/client/aboutdebugging-new/src/middleware/error-logging.js
devtools/client/aboutdebugging-new/src/middleware/moz.build
--- a/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
+++ b/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
@@ -123,17 +123,17 @@ function requestTabs() {
 
     const client = getCurrentClient(getState().runtimes);
 
     try {
       const { tabs } = await client.listTabs({ favicons: true });
 
       dispatch({ type: REQUEST_TABS_SUCCESS, tabs });
     } catch (e) {
-      dispatch({ type: REQUEST_TABS_FAILURE, error: e.message });
+      dispatch({ type: REQUEST_TABS_FAILURE, error: e });
     }
   };
 }
 
 function requestExtensions() {
   return async (dispatch, getState) => {
     dispatch({ type: REQUEST_EXTENSIONS_START });
 
@@ -146,17 +146,17 @@ function requestExtensions() {
       const temporaryExtensions = extensions.filter(e => e.temporarilyInstalled);
 
       dispatch({
         type: REQUEST_EXTENSIONS_SUCCESS,
         installedExtensions,
         temporaryExtensions,
       });
     } catch (e) {
-      dispatch({ type: REQUEST_EXTENSIONS_FAILURE, error: e.message });
+      dispatch({ type: REQUEST_EXTENSIONS_FAILURE, error: e });
     }
   };
 }
 
 function requestWorkers() {
   return async (dispatch, getState) => {
     dispatch({ type: REQUEST_WORKERS_START });
 
@@ -171,17 +171,17 @@ function requestWorkers() {
 
       dispatch({
         type: REQUEST_WORKERS_SUCCESS,
         otherWorkers,
         serviceWorkers,
         sharedWorkers,
       });
     } catch (e) {
-      dispatch({ type: REQUEST_WORKERS_FAILURE, error: e.message });
+      dispatch({ type: REQUEST_WORKERS_FAILURE, error: e });
     }
   };
 }
 
 function startServiceWorker(actor) {
   return async (_, getState) => {
     const client = getCurrentClient(getState().runtimes);
 
--- a/devtools/client/aboutdebugging-new/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging-new/src/actions/runtimes.js
@@ -109,17 +109,17 @@ function connectRuntime(id) {
         type: CONNECT_RUNTIME_SUCCESS,
         runtime: {
           id,
           runtimeDetails,
           type: runtime.type,
         },
       });
     } catch (e) {
-      dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: CONNECT_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function disconnectRuntime(id) {
   return async (dispatch, getState) => {
     dispatch({ type: DISCONNECT_RUNTIME_START });
     try {
@@ -132,17 +132,17 @@ function disconnectRuntime(id) {
       dispatch({
         type: DISCONNECT_RUNTIME_SUCCESS,
         runtime: {
           id,
           type: runtime.type,
         },
       });
     } catch (e) {
-      dispatch({ type: DISCONNECT_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: DISCONNECT_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function updateConnectionPromptSetting(connectionPromptEnabled) {
   return async (dispatch, getState) => {
     dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_START });
     try {
@@ -153,18 +153,17 @@ function updateConnectionPromptSetting(c
                                         connectionPromptEnabled);
       // Re-get actual value from the runtime.
       connectionPromptEnabled =
         await preferenceFront.getBoolPref(RUNTIME_PREFERENCE.CONNECTION_PROMPT);
 
       dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
                  runtime, connectionPromptEnabled });
     } catch (e) {
-      dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_FAILURE,
-                 error: e.message });
+      dispatch({ type: UPDATE_CONNECTION_PROMPT_SETTING_FAILURE, error: e });
     }
   };
 }
 
 function watchRuntime(id) {
   return async (dispatch, getState) => {
     dispatch({ type: WATCH_RUNTIME_START });
 
@@ -185,17 +184,17 @@ function watchRuntime(id) {
       if (isSupportedDebugTarget(runtime.type, DEBUG_TARGETS.TAB)) {
         dispatch(Actions.requestTabs());
       }
 
       if (isSupportedDebugTarget(runtime.type, DEBUG_TARGETS.WORKER)) {
         dispatch(Actions.requestWorkers());
       }
     } catch (e) {
-      dispatch({ type: WATCH_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: WATCH_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function unwatchRuntime(id) {
   return async (dispatch, getState) => {
     const runtime = findRuntimeById(id, getState().runtimes);
 
@@ -204,17 +203,17 @@ function unwatchRuntime(id) {
     try {
       if (id === RUNTIMES.THIS_FIREFOX) {
         // THIS_FIREFOX connects and disconnects on the fly when opening the page.
         await dispatch(disconnectRuntime(RUNTIMES.THIS_FIREFOX));
       }
 
       dispatch({ type: UNWATCH_RUNTIME_SUCCESS });
     } catch (e) {
-      dispatch({ type: UNWATCH_RUNTIME_FAILURE, error: e.message });
+      dispatch({ type: UNWATCH_RUNTIME_FAILURE, error: e });
     }
   };
 }
 
 function updateUSBRuntimes(runtimes) {
   return async (dispatch, getState) => {
     const currentRuntime = getCurrentRuntime(getState().runtimes);
 
--- a/devtools/client/aboutdebugging-new/src/actions/ui.js
+++ b/devtools/client/aboutdebugging-new/src/actions/ui.js
@@ -79,30 +79,30 @@ function updateNetworkLocations(location
 function installAdbAddon() {
   return async (dispatch, getState) => {
     dispatch({ type: ADB_ADDON_INSTALL_START });
 
     try {
       await adbAddon.install();
       dispatch({ type: ADB_ADDON_INSTALL_SUCCESS });
     } catch (e) {
-      dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e.message });
+      dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e });
     }
   };
 }
 
 function uninstallAdbAddon() {
   return async (dispatch, getState) => {
     dispatch({ type: ADB_ADDON_UNINSTALL_START });
 
     try {
       await adbAddon.uninstall();
       dispatch({ type: ADB_ADDON_UNINSTALL_SUCCESS });
     } catch (e) {
-      dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e.message });
+      dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e });
     }
   };
 }
 
 module.exports = {
   addNetworkLocation,
   installAdbAddon,
   removeNetworkLocation,
--- a/devtools/client/aboutdebugging-new/src/create-store.js
+++ b/devtools/client/aboutdebugging-new/src/create-store.js
@@ -9,16 +9,17 @@ const Services = require("Services");
 const { applyMiddleware, createStore } = require("devtools/client/shared/vendor/redux");
 const { thunk } = require("devtools/client/shared/redux/middleware/thunk.js");
 
 const rootReducer = require("./reducers/index");
 const { DebugTargetsState } = require("./reducers/debug-targets-state");
 const { RuntimesState } = require("./reducers/runtimes-state");
 const { UiState } = require("./reducers/ui-state");
 const debugTargetListenerMiddleware = require("./middleware/debug-target-listener");
+const errorLoggingMiddleware = require("./middleware/error-logging");
 const extensionComponentDataMiddleware = require("./middleware/extension-component-data");
 const tabComponentDataMiddleware = require("./middleware/tab-component-data");
 const workerComponentDataMiddleware = require("./middleware/worker-component-data");
 const { getDebugTargetCollapsibilities } = require("./modules/debug-target-collapsibilities");
 const { getNetworkLocations } = require("./modules/network-locations");
 
 const { PREFERENCES } = require("./constants");
 
@@ -26,16 +27,17 @@ function configureStore() {
   const initialState = {
     debugTargets: new DebugTargetsState(),
     runtimes: new RuntimesState(),
     ui: getUiState(),
   };
 
   const middleware = applyMiddleware(thunk,
                                      debugTargetListenerMiddleware,
+                                     errorLoggingMiddleware,
                                      extensionComponentDataMiddleware,
                                      tabComponentDataMiddleware,
                                      workerComponentDataMiddleware);
 
   return createStore(rootReducer, initialState, middleware);
 }
 
 function getUiState() {
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/middleware/error-logging.js
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/**
+ * Error logging middleware that will forward all actions that contain an error property
+ * to the console.
+ */
+function errorLoggingMiddleware() {
+  return next => action => {
+    if (action.error) {
+      const { error } = action;
+      if (error.message) {
+        console.error(`[ACTION FAILED] ${action.type}: ${error.message}`);
+      } else if (typeof error === "string") {
+        // All failure actions should dispatch an error object instead of a message.
+        // We allow some flexibility to still provide some error logging.
+        console.error(`[ACTION FAILED] ${action.type}: ${error}`);
+        console.error(`[ACTION FAILED] ${action.type} should dispatch the error object!`);
+      }
+
+      if (error.stack) {
+        console.error(error.stack);
+      }
+    }
+
+    return next(action);
+  };
+}
+
+module.exports = errorLoggingMiddleware;
--- a/devtools/client/aboutdebugging-new/src/middleware/moz.build
+++ b/devtools/client/aboutdebugging-new/src/middleware/moz.build
@@ -1,10 +1,11 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DevToolsModules(
     'debug-target-listener.js',
+    'error-logging.js',
     'extension-component-data.js',
     'tab-component-data.js',
     'worker-component-data.js',
 )