Bug 1214408 - Telemetry on SessionStore:update OOM;r=ttaubert

--HG--
extra : transplant_source : %3A%DB%3Cp%8Fj%24%CF%94%E9%5C%AA%17%0E%2C%03E%23%A2%98
This commit is contained in:
David Rajchenbach-Teller 2015-10-16 21:44:54 +02:00
Родитель 9f82ed620a
Коммит 8292b78498
5 изменённых файлов: 121 добавлений и 10 удалений

Просмотреть файл

@ -72,6 +72,9 @@ const MESSAGES = [
// 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
@ -85,6 +88,9 @@ const NOTAB_MESSAGES = new Set([
// For a description see above.
"SessionStore:update",
// For a description see above.
"SessionStore:error",
]);
// The list of messages we accept without an "epoch" parameter.
@ -95,6 +101,9 @@ const NOEPOCH_MESSAGES = new Set([
// 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
@ -106,6 +115,9 @@ const CLOSED_MESSAGES = new Set([
// For a description see above.
"SessionStore:update",
// For a description see above.
"SessionStore:error",
]);
// These are tab events that we listen to.
@ -808,6 +820,9 @@ var SessionStoreInternal = {
case "SessionStore:crashedTabRevived":
this._crashedBrowsers.delete(browser.permanentKey);
break;
case "SessionStore:error":
this.reportInternalError(data);
break;
default:
throw new Error(`received unknown message '${aMessage.name}'`);
break;
@ -3848,6 +3863,19 @@ var SessionStoreInternal = {
*/
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 (data.telemetry) {
for (let key of Object.keys(data.telemetry)) {
let histogram = Telemetry.getHistogramById(key);
histogram.add(data.telemetry[key]);
}
}
}
};

Просмотреть файл

@ -29,10 +29,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionHistory",
XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
"resource:///modules/sessionstore/SessionStorage.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsISyncMessageSender");
Cu.import("resource:///modules/sessionstore/FrameTree.jsm", this);
var gFrameTree = new FrameTree(this);
@ -692,12 +688,21 @@ var MessageQueue = {
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 && ex.result == Cr.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++;

Просмотреть файл

@ -211,3 +211,4 @@ skip-if = true
skip-if = os == "mac"
[browser_911547.js]
[browser_send_async_message_oom.js]

Просмотреть файл

@ -0,0 +1,71 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
const HISTOGRAM_NAME = "FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM";
/**
* Test that an OOM in sendAsyncMessage in a framescript will be reported
* to Telemetry.
*/
add_task(function* init() {
Services.telemetry.canRecordExtended = true;
});
function frameScript() {
// Make send[A]syncMessage("SessionStore:update", ...) simulate OOM.
// Other operations are unaffected.
let mm = docShell.sameTypeRootTreeItem.
QueryInterface(Ci.nsIDocShell).
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIContentFrameMessageManager);
let wrap = function(original) {
return function(name, ...args) {
if (name != "SessionStore:update") {
return original(name, ...args);
}
throw new Components.Exception("Simulated OOM", Cr.NS_ERROR_OUT_OF_MEMORY);
}
}
mm.sendAsyncMessage = wrap(mm.sendAsyncMessage);
mm.sendSyncMessage = wrap(mm.sendSyncMessage);
}
add_task(function*() {
// Capture original state.
let snapshot = Services.telemetry.getHistogramById(HISTOGRAM_NAME).snapshot();
// Open a browser, configure it to cause OOM.
let newTab = gBrowser.addTab("about:robots");
let browser = newTab.linkedBrowser;
yield ContentTask.spawn(browser, null, frameScript);
let promiseReported = new Promise(resolve => {
browser.messageManager.addMessageListener("SessionStore:error", resolve);
});
// Attempt to flush. This should fail.
let promiseFlushed = TabStateFlusher.flush(browser);
promiseFlushed.then(() => {throw new Error("Flush should have failed")});
// The frame script should report an error.
yield promiseReported;
// Give us some time to handle that error.
yield new Promise(resolve => setTimeout(resolve, 10));
// By now, Telemetry should have been updated.
let snapshot2 = Services.telemetry.getHistogramById(HISTOGRAM_NAME).snapshot();
gBrowser.removeTab(newTab);
Assert.ok(snapshot2.sum > snapshot.sum);
});
add_task(function* cleanup() {
Services.telemetry.canRecordExtended = false;
});

Просмотреть файл

@ -4352,6 +4352,12 @@
"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_TABLETMODE_PAGE_LOAD": {
"expires_in_version": "47",
"kind": "exponential",