Bug 1214408 - Telemetry on SessionStore:update OOM;r?ttaubert draft
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Thu, 15 Oct 2015 17:33:45 +0200
changeset 301183 b6a6d0320d7eca092ddd3d560aabc05ab8f22936
parent 296070 001942e4617b2324bfa6cdfb1155581cbc3f0cc4
child 510197 0bbaffa6aed28eafa47ccb73825c1a25c173be05
push id6416
push userdteller@mozilla.com
push dateThu, 15 Oct 2015 21:52:10 +0000
reviewersttaubert
bugs1214408
milestone44.0a1
Bug 1214408 - Telemetry on SessionStore:update OOM;r?ttaubert
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/content/content-sessionStore.js
toolkit/components/telemetry/Histograms.json
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -64,50 +64,62 @@ const MESSAGES = [
   // consider restoring another tab in the queue. The document has
   // been restored, and forms have been filled. We trigger
   // SSTabRestored at this time.
   "SessionStore:restoreTabContentComplete",
 
   // A crashed tab was revived by navigating to a different page. Remove its
   // browser from the list of crashed browsers to stop ignoring its messages.
   "SessionStore:crashedTabRevived",
+
+  // The content script encountered an error.
+  "SessionStore:error",
 ];
 
 // The list of messages we accept from <xul:browser>s that have no tab
 // assigned. Those are for example the ones that preload about:newtab pages.
 const NOTAB_MESSAGES = new Set([
   // For a description see above.
   "SessionStore:setupSyncHandler",
 
   // For a description see above.
   "SessionStore:crashedTabRevived",
 
   // For a description see above.
   "SessionStore:update",
+
+  // For a description see above.
+  "SessionStore:error",
 ]);
 
 // The list of messages we accept without an "epoch" parameter.
 // See getCurrentEpoch() and friends to find out what an "epoch" is.
 const NOEPOCH_MESSAGES = new Set([
   // For a description see above.
   "SessionStore:setupSyncHandler",
 
   // For a description see above.
   "SessionStore:crashedTabRevived",
+
+  // For a description see above.
+  "SessionStore:error",
 ]);
 
 // The list of messages we want to receive even during the short period after a
 // frame has been removed from the DOM and before its frame script has finished
 // unloading.
 const CLOSED_MESSAGES = new Set([
   // For a description see above.
   "SessionStore:crashedTabRevived",
 
   // For a description see above.
   "SessionStore:update",
+
+  // For a description see above.
+  "SessionStore:error",
 ]);
 
 // These are tab events that we listen to.
 const TAB_EVENTS = [
   "TabOpen", "TabClose", "TabSelect", "TabShow", "TabHide", "TabPinned",
   "TabUnpinned"
 ];
 
@@ -774,16 +786,19 @@ var SessionStoreInternal = {
         SessionStoreInternal._resetLocalTabRestoringState(tab);
         SessionStoreInternal.restoreNextTab();
 
         this._sendTabRestoredNotification(tab);
         break;
       case "SessionStore:crashedTabRevived":
         this._crashedBrowsers.delete(browser.permanentKey);
         break;
+      case "SessionStore:error":
+        SessionStoreInternal.reportInternalError(data);
+        break;
       default:
         throw new Error(`received unknown message '${aMessage.name}'`);
         break;
     }
   },
 
   /**
    * Record telemetry measurements stored in an object.
@@ -3805,16 +3820,28 @@ var SessionStoreInternal = {
 
   /**
    * Resets the epoch for a given <browser>. We need to this every time we
    * receive a hint that a new docShell has been loaded into the browser as
    * the frame script starts out with epoch=0.
    */
   resetEpoch(browser) {
     this._browserEpochs.delete(browser.permanentKey);
+  },
+
+  /**
+   * Handle an error report from a content process.
+   */
+  reportInternalError(data) {
+    // For the moment, we only report errors through Telemetry.
+    if (error.telemetry) {
+      for (let histogram of Object.keys(error.telemetry)) {
+        Telemetry.getHistogramById(histogram).add(error.telemetry[histogram]);
+      }
+    }
   }
 };
 
 /**
  * Priority queue that keeps track of a list of tabs to restore and returns
  * the tab we should restore next, based on priority rules. We decide between
  * pinned, visible and hidden tabs in that and FIFO order. Hidden tabs are only
  * restored with restore_hidden_tabs=true.
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -702,22 +702,34 @@ var MessageQueue = {
       data[key] = this._data.get(key)();
     }
 
     durationMs = Date.now() - durationMs;
     let telemetry = {
       FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_LONGEST_OP_MS: durationMs
     }
 
-    // Send all data to the parent process.
-    sendMessage("SessionStore:update", {
-      id: this._id, data, telemetry, flushID,
-      isFinal: options.isFinal || false,
-      epoch: gCurrentEpoch
-    });
+    try {
+      // Send all data to the parent process.
+      sendMessage("SessionStore:update", {
+        id: this._id, data, telemetry, flushID,
+        isFinal: options.isFinal || false,
+        epoch: gCurrentEpoch
+      });
+    } catch (ex if
+      (ex == Components.result.NS_ERROR_OUT_OF_MEMORY)
+    ||(ex && typeof ex == "object" && ex.result == Components.result.NS_ERROR_OUT_OF_MEMORY)
+    ) {
+      let telemetry = {
+        FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM: 1
+      }
+      sendMessage("SessionStore:error"), {
+        telemetry
+      });
+    }
 
     // Increase our unique message ID.
     this._id++;
   },
 
   /**
    * This function is used to make the message queue flush all queue data that
    * hasn't been sent to the parent process, yet.
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -4294,16 +4294,22 @@
     "alert_emails": ["session-restore-telemetry-alerts@mozilla.com"],
     "expires_in_version": "default",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Session restore: Time spent blocking the main thread while restoring a window state (ms)"
   },
+  "FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM": {
+    "alert_emails": ["session-restore-telemetry-alerts@mozilla.com"],
+    "expires_in_version": "default",
+    "kind": "count",
+    "description": "Count of messages sent by SessionRestore from child frames to the parent and that cannot be transmitted as they eat up too much memory."
+  },
   "FX_TABLET_MODE_USED_DURING_SESSION": {
     "expires_in_version": "46",
     "kind": "count",
     "description": "Windows 10+ only: The number of times tablet-mode is used during a session"
   },
   "FX_TOUCH_USED": {
     "expires_in_version": "46",
     "kind": "count",