Bug 1271304 - Measure the tabs/window open events and max number of tab/window per subsession. r=Gijs, r=gfritzsche, data-review=bsmedberg

MozReview-Commit-ID: 6vYfoEb8VvB
This commit is contained in:
Alessio Placitelli 2016-05-12 09:30:00 +02:00
parent e40bdbb8df
commit 0f0b2b22da
6 changed files with 238 additions and 0 deletions

View File

@ -102,6 +102,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "SelfSupportBackend",
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore", XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm"); "resource:///modules/sessionstore/SessionStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUsageTelemetry",
"resource:///modules/BrowserUsageTelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry", XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
"resource:///modules/BrowserUITelemetry.jsm"); "resource:///modules/BrowserUITelemetry.jsm");
@ -781,6 +784,7 @@ BrowserGlue.prototype = {
NewTabMessages.init(); NewTabMessages.init();
SessionStore.init(); SessionStore.init();
BrowserUsageTelemetry.init();
BrowserUITelemetry.init(); BrowserUITelemetry.init();
ContentSearch.init(); ContentSearch.init();
FormValidationHandler.init(); FormValidationHandler.init();
@ -1174,6 +1178,7 @@ BrowserGlue.prototype = {
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e); Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
} }
BrowserUsageTelemetry.uninit();
SelfSupportBackend.uninit(); SelfSupportBackend.uninit();
NewTabMessages.uninit(); NewTabMessages.uninit();

View File

@ -0,0 +1,175 @@
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
/* 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";
this.EXPORTED_SYMBOLS = ["BrowserUsageTelemetry"];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
// Observed topic names.
const WINDOWS_RESTORED_TOPIC = "sessionstore-windows-restored";
const TELEMETRY_SUBSESSIONSPLIT_TOPIC = "internal-telemetry-after-subsession-split";
const DOMWINDOW_OPENED_TOPIC = "domwindowopened";
const DOMWINDOW_CLOSED_TOPIC = "domwindowclosed";
// Probe names.
const MAX_TAB_COUNT_SCALAR_NAME = "browser.engagement.max_concurrent_tab_count";
const MAX_WINDOW_COUNT_SCALAR_NAME = "browser.engagement.max_concurrent_window_count";
const TAB_OPEN_EVENT_COUNT_SCALAR_NAME = "browser.engagement.tab_open_event_count";
const WINDOW_OPEN_EVENT_COUNT_SCALAR_NAME = "browser.engagement.window_open_event_count";
function getOpenTabsAndWinsCounts() {
let tabCount = 0;
let winCount = 0;
let browserEnum = Services.wm.getEnumerator("navigator:browser");
while (browserEnum.hasMoreElements()) {
let win = browserEnum.getNext();
winCount++;
tabCount += win.gBrowser.tabs.length;
}
return { tabCount, winCount };
}
let BrowserUsageTelemetry = {
init() {
Services.obs.addObserver(this, WINDOWS_RESTORED_TOPIC, false);
},
/**
* Handle subsession splits in the parent process.
*/
afterSubsessionSplit() {
// Scalars just got cleared due to a subsession split. We need to set the maximum
// concurrent tab and window counts so that they reflect the correct value for the
// new subsession.
const counts = getOpenTabsAndWinsCounts();
Services.telemetry.scalarSetMaximum(MAX_TAB_COUNT_SCALAR_NAME, counts.tabCount);
Services.telemetry.scalarSetMaximum(MAX_WINDOW_COUNT_SCALAR_NAME, counts.winCount);
},
uninit() {
Services.obs.removeObserver(this, DOMWINDOW_OPENED_TOPIC, false);
Services.obs.removeObserver(this, DOMWINDOW_CLOSED_TOPIC, false);
Services.obs.removeObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC, false);
Services.obs.removeObserver(this, WINDOWS_RESTORED_TOPIC, false);
},
observe(subject, topic, data) {
switch(topic) {
case WINDOWS_RESTORED_TOPIC:
this._setupAfterRestore();
break;
case DOMWINDOW_OPENED_TOPIC:
this._onWindowOpen(subject);
break;
case DOMWINDOW_CLOSED_TOPIC:
this._unregisterWindow(subject);
break;
case TELEMETRY_SUBSESSIONSPLIT_TOPIC:
this.afterSubsessionSplit();
break;
}
},
handleEvent(event) {
switch(event.type) {
case "TabOpen":
this._onTabOpen();
break;
}
},
/**
* This gets called shortly after the SessionStore has finished restoring
* windows and tabs. It counts the open tabs and adds listeners to all the
* windows.
*/
_setupAfterRestore() {
// Make sure to catch new chrome windows and subsession splits.
Services.obs.addObserver(this, DOMWINDOW_OPENED_TOPIC, false);
Services.obs.addObserver(this, DOMWINDOW_CLOSED_TOPIC, false);
Services.obs.addObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC, false);
// Attach the tabopen handlers to the existing Windows.
let browserEnum = Services.wm.getEnumerator("navigator:browser");
while (browserEnum.hasMoreElements()) {
this._registerWindow(browserEnum.getNext());
}
// Get the initial tab and windows max counts.
const counts = getOpenTabsAndWinsCounts();
Services.telemetry.scalarSetMaximum(MAX_TAB_COUNT_SCALAR_NAME, counts.tabCount);
Services.telemetry.scalarSetMaximum(MAX_WINDOW_COUNT_SCALAR_NAME, counts.winCount);
},
/**
* Adds listeners to a single chrome window.
*/
_registerWindow(win) {
win.addEventListener("TabOpen", this, true);
},
/**
* Removes listeners from a single chrome window.
*/
_unregisterWindow(win) {
// Ignore non-browser windows.
if (!(win instanceof Ci.nsIDOMWindow) ||
win.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
win.removeEventListener("TabOpen", this, true);
},
/**
* Updates the tab counts.
* @param {Number} [newTabCount=0] The count of the opened tabs across all windows. This
* is computed manually if not provided.
*/
_onTabOpen(tabCount = 0) {
// Use the provided tab count if available. Otherwise, go on and compute it.
tabCount = tabCount || getOpenTabsAndWinsCounts().tabCount;
// Update the "tab opened" count and its maximum.
Services.telemetry.scalarAdd(TAB_OPEN_EVENT_COUNT_SCALAR_NAME, 1);
Services.telemetry.scalarSetMaximum(MAX_TAB_COUNT_SCALAR_NAME, tabCount);
},
/**
* Tracks the window count and registers the listeners for the tab count.
* @param{Object} win The window object.
*/
_onWindowOpen(win) {
// Make sure to have a |nsIDOMWindow|.
if (!(win instanceof Ci.nsIDOMWindow)) {
return;
}
let onLoad = () => {
win.removeEventListener("load", onLoad, false);
// Ignore non browser windows.
if (win.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
this._registerWindow(win);
// Track the window open event and check the maximum.
const counts = getOpenTabsAndWinsCounts();
Services.telemetry.scalarAdd(WINDOW_OPEN_EVENT_COUNT_SCALAR_NAME, 1);
Services.telemetry.scalarSetMaximum(MAX_WINDOW_COUNT_SCALAR_NAME, counts.winCount);
// We won't receive the "TabOpen" event for the first tab within a new window.
// Account for that.
this._onTabOpen(counts.tabCount);
};
win.addEventListener("load", onLoad, false);
},
};

View File

@ -14,6 +14,7 @@ EXTRA_JS_MODULES += [
'AboutHome.jsm', 'AboutHome.jsm',
'AboutNewTab.jsm', 'AboutNewTab.jsm',
'BrowserUITelemetry.jsm', 'BrowserUITelemetry.jsm',
'BrowserUsageTelemetry.jsm',
'CaptivePortalWatcher.jsm', 'CaptivePortalWatcher.jsm',
'CastingApps.jsm', 'CastingApps.jsm',
'Chat.jsm', 'Chat.jsm',

View File

@ -70,3 +70,54 @@ telemetry.test:
notification_emails: notification_emails:
- telemetry-client-dev@mozilla.com - telemetry-client-dev@mozilla.com
release_channel_collection: opt-out release_channel_collection: opt-out
# The following section contains the browser engagement scalars.
browser.engagement:
max_concurrent_tab_count:
bug_numbers:
- 1271304
description: >
The count of maximum number of tabs open during a subsession,
across all windows, including tabs in private windows and restored
at startup.
expires: "55"
kind: uint
notification_emails:
- rweiss@mozilla.com
release_channel_collection: opt-out
tab_open_event_count:
bug_numbers:
- 1271304
description: >
The count of tab open events per subsession, across all windows, after the
session has been restored. This includes tab open events from private windows.
expires: "55"
kind: uint
notification_emails:
- rweiss@mozilla.com
release_channel_collection: opt-out
max_concurrent_window_count:
bug_numbers:
- 1271304
description: >
The count of maximum number of browser windows open during a subsession. This
includes private windows and the ones opened when starting the browser.
expires: "55"
kind: uint
notification_emails:
- rweiss@mozilla.com
release_channel_collection: opt-out
window_open_event_count:
bug_numbers:
- 1271304
description: >
The count of browser window open events per subsession, after the session
has been restored. The count includes the private windows.
expires: "55"
kind: uint
notification_emails:
- rweiss@mozilla.com
release_channel_collection: opt-out

View File

@ -1351,6 +1351,10 @@ var Impl = {
// Persist session data to disk (don't wait until it completes). // Persist session data to disk (don't wait until it completes).
let sessionData = this._getSessionDataObject(); let sessionData = this._getSessionDataObject();
TelemetryStorage.saveSessionData(sessionData); TelemetryStorage.saveSessionData(sessionData);
// Notify that there was a subsession split in the parent process. This is an
// internal topic and is only meant for internal Telemetry usage.
Services.obs.notifyObservers(null, "internal-telemetry-after-subsession-split", null);
} }
} }

View File

@ -15,6 +15,8 @@ This ping is triggered by different scenarios, which is documented by the ``reas
Most reasons lead to a session split, initiating a new *subsession*. We reset important measurements for those subsessions. Most reasons lead to a session split, initiating a new *subsession*. We reset important measurements for those subsessions.
After a new subsession split, the ``internal-telemetry-after-subsession-split`` topic is notified to all the observers. *This is an internal topic and is only meant for internal Telemetry usage.*
*Note:* ``saved-session`` is sent with a different ping type (``saved-session``, not ``main``), but otherwise has the same format as discussed here. *Note:* ``saved-session`` is sent with a different ping type (``saved-session``, not ``main``), but otherwise has the same format as discussed here.
Structure:: Structure::