diff --git a/browser/devtools/framework/gDevTools.jsm b/browser/devtools/framework/gDevTools.jsm index 056ed6c2881d..efb9014cdbcc 100644 --- a/browser/devtools/framework/gDevTools.jsm +++ b/browser/devtools/framework/gDevTools.jsm @@ -27,6 +27,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient", "resource://gre/modules/devtools/dbg-client.jsm"); const EventEmitter = devtools.require("devtools/toolkit/event-emitter"); +const Telemetry = devtools.require("devtools/shared/telemetry"); + +const TABS_OPEN_PEAK_HISTOGRAM = "DEVTOOLS_TABS_OPEN_PEAK_EXPONENTIAL"; +const TABS_OPEN_AVG_HISTOGRAM = "DEVTOOLS_TABS_OPEN_AVERAGE_EXPONENTIAL"; +const TABS_PINNED_PEAK_HISTOGRAM = "DEVTOOLS_TABS_PINNED_PEAK_EXPONENTIAL"; +const TABS_PINNED_AVG_HISTOGRAM = "DEVTOOLS_TABS_PINNED_AVERAGE_EXPONENTIAL"; + const FORBIDDEN_IDS = new Set(["toolbox", ""]); const MAX_ORDINAL = 99; @@ -467,6 +474,19 @@ DevTools.prototype = { return toolbox.destroy().then(() => true); }, + _pingTelemetry: function() { + let mean = function(arr) { + let total = arr.reduce((a, b) => a + b); + return Math.ceil(total / arr.length); + }; + + let tabStats = gDevToolsBrowser._tabStats; + this._telemetry.log(TABS_OPEN_PEAK_HISTOGRAM, tabStats.peakOpen); + this._telemetry.log(TABS_OPEN_AVG_HISTOGRAM, mean(tabStats.histOpen)); + this._telemetry.log(TABS_PINNED_PEAK_HISTOGRAM, tabStats.peakPinned); + this._telemetry.log(TABS_PINNED_AVG_HISTOGRAM, mean(tabStats.histPinned)); + }, + /** * Called to tear down a tools provider. */ @@ -487,6 +507,9 @@ DevTools.prototype = { this.unregisterTool(key, true); } + this._pingTelemetry(); + this._telemetry = null; + // Cleaning down the toolboxes: i.e. // for (let [target, toolbox] of this._toolboxes) toolbox.destroy(); // Is taken care of by the gDevToolsBrowser.forgetBrowserWindow @@ -522,6 +545,13 @@ let gDevToolsBrowser = { */ _trackedBrowserWindows: new Set(), + _tabStats: { + peakOpen: 0, + peakPinned: 0, + histOpen: [], + histPinned: [] + }, + /** * This function is for the benefit of Tools:DevToolbox in * browser/base/content/browser-sets.inc and should not be used outside @@ -812,9 +842,12 @@ let gDevToolsBrowser = { broadcaster.removeAttribute("key"); } - let tabContainer = win.document.getElementById("tabbrowser-tabs") - tabContainer.addEventListener("TabSelect", - gDevToolsBrowser._updateMenuCheckbox, false); + let tabContainer = win.document.getElementById("tabbrowser-tabs"); + tabContainer.addEventListener("TabSelect", this, false); + tabContainer.addEventListener("TabOpen", this, false); + tabContainer.addEventListener("TabClose", this, false); + tabContainer.addEventListener("TabPinned", this, false); + tabContainer.addEventListener("TabUnpinned", this, false); }, /** @@ -1246,9 +1279,40 @@ let gDevToolsBrowser = { } } - let tabContainer = win.document.getElementById("tabbrowser-tabs") - tabContainer.removeEventListener("TabSelect", - gDevToolsBrowser._updateMenuCheckbox, false); + let tabContainer = win.document.getElementById("tabbrowser-tabs"); + tabContainer.removeEventListener("TabSelect", this, false); + tabContainer.removeEventListener("TabOpen", this, false); + tabContainer.removeEventListener("TabClose", this, false); + tabContainer.removeEventListener("TabPinned", this, false); + tabContainer.removeEventListener("TabUnpinned", this, false); + }, + + handleEvent: function(event) { + switch (event.type) { + case "TabOpen": + case "TabClose": + case "TabPinned": + case "TabUnpinned": + let open = 0; + let pinned = 0; + + for (let win of this._trackedBrowserWindows) { + let tabContainer = win.gBrowser.tabContainer; + let numPinnedTabs = tabContainer.tabbrowser._numPinnedTabs; + let numTabs = tabContainer.itemCount - numPinnedTabs; + + open += numTabs; + pinned += numPinnedTabs; + } + + this._tabStats.histOpen.push(open); + this._tabStats.histPinned.push(pinned); + this._tabStats.peakOpen = Math.max(open, this._tabStats.peakOpen); + this._tabStats.peakPinned = Math.max(pinned, this._tabStats.peakPinned); + break; + case "TabSelect": + gDevToolsBrowser._updateMenuCheckbox(); + } }, /** diff --git a/browser/devtools/framework/toolbox.js b/browser/devtools/framework/toolbox.js index 374240a44562..b1649ba764f0 100644 --- a/browser/devtools/framework/toolbox.js +++ b/browser/devtools/framework/toolbox.js @@ -10,6 +10,9 @@ const SPLITCONSOLE_ENABLED_PREF = "devtools.toolbox.splitconsoleEnabled"; const SPLITCONSOLE_HEIGHT_PREF = "devtools.toolbox.splitconsoleHeight"; const MIN_ZOOM = 0.5; const MAX_ZOOM = 2; +const OS_HISTOGRAM = "DEVTOOLS_OS_ENUMERATED_PER_USER"; +const OS_IS_64_BITS = "DEVTOOLS_OS_IS_64_BITS_PER_USER"; +const SCREENSIZE_HISTOGRAM = "DEVTOOLS_SCREEN_RESOLUTION_ENUMERATED_PER_USER"; let {Cc, Ci, Cu} = require("chrome"); let {Promise: promise} = require("resource://gre/modules/Promise.jsm"); @@ -334,7 +337,7 @@ Toolbox.prototype = { let buttonsPromise = this._buildButtons(); - this._telemetry.toolOpened("toolbox"); + this._pingTelemetry(); this.selectTool(this._defaultToolId).then(panel => { @@ -359,7 +362,7 @@ Toolbox.prototype = { // Load the toolbox-level actor fronts and utilities now this._target.makeRemote().then(() => { iframe.setAttribute("src", this._URL); - iframe.setAttribute("aria-label", toolboxStrings("toolbox.label")) + iframe.setAttribute("aria-label", toolboxStrings("toolbox.label")); let domHelper = new DOMHelpers(iframe.contentWindow); domHelper.onceDOMReady(domReady); }); @@ -368,6 +371,17 @@ Toolbox.prototype = { }).then(null, console.error.bind(console)); }, + _pingTelemetry: function() { + this._telemetry.toolOpened("toolbox"); + + this._telemetry.logOncePerBrowserVersion(OS_HISTOGRAM, + this._getOsCpu()); + this._telemetry.logOncePerBrowserVersion(OS_IS_64_BITS, + this._getIs64Bits()); + this._telemetry.logOncePerBrowserVersion(SCREENSIZE_HISTOGRAM, + this._getScreenDimensions()); + }, + /** * Because our panels are lazy loaded this is a good place to watch for * "pref-changed" events. @@ -1575,6 +1589,68 @@ Toolbox.prototype = { return this.doc.getElementById("toolbox-notificationbox"); }, + _getScreenDimensions: function() { + let width = {}; + let height = {}; + + Cc["@mozilla.org/gfx/screenmanager;1"].getService(Ci.nsIScreenManager) + .primaryScreen.GetRect({}, {}, width, height); + let dims = width.value + "x" + height.value; + + if (width.value < 800 || height.value < 600) return 0; + if (dims === "800x600") return 1; + if (dims === "1024x768") return 2; + if (dims === "1280x800") return 3; + if (dims === "1280x1024") return 4; + if (dims === "1366x768") return 5; + if (dims === "1440x900") return 6; + if (dims === "1920x1080") return 7; + if (dims === "2560×1600") return 8; + if (dims === "2560×1600") return 9; + if (dims === "2880x1800") return 10; + if (width.value > 2880 || height.value > 1800) return 12; + + return 11; // Other dimension such as a VM. + }, + + _getOsCpu: function() { + let oscpu = Cc["@mozilla.org/network/protocol;1?name=http"] + .getService(Ci.nsIHttpProtocolHandler).oscpu; + + if (oscpu.contains("NT 5.1") || oscpu.contains("NT 5.2")) return 0; + if (oscpu.contains("NT 6.0")) return 1; + if (oscpu.contains("NT 6.1")) return 2; + if (oscpu.contains("NT 6.2")) return 3; + if (oscpu.contains("NT 6.3")) return 4; + if (oscpu.contains("OS X")) return 5; + if (oscpu.contains("Linux")) return 6; + + return 10; // Other OS. + }, + + /** + * Check if we are running a 32 or 64-bit version of Firefox. + * @return {Integer} + * 0, 1, or 2 where 0=false, 1=true and null=Unknown (probably + * running SPARC, Alpha or ARM). + */ + _getIs64Bits: function() { + let appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); + + let processor = appInfo.XPCOMABI.split("-")[0]; + + switch (processor) { + case "x86": + return 0; + case "x86_64": + case "ia_64": + case "ppc": + return 1; + } + + return 2; // SPARC, Alpha or ARM. + }, + /** * Destroy the current host, and remove event listeners from its frame. * diff --git a/browser/devtools/shared/test/browser_telemetry_toolbox.js b/browser/devtools/shared/test/browser_telemetry_toolbox.js index fbd7cdfdacb4..438feab42aa2 100644 --- a/browser/devtools/shared/test/browser_telemetry_toolbox.js +++ b/browser/devtools/shared/test/browser_telemetry_toolbox.js @@ -28,9 +28,12 @@ function checkResults() { checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_BOOLEAN", [0,3,0]); checkTelemetry("DEVTOOLS_INSPECTOR_OPENED_PER_USER_FLAG", [0,1,0]); checkTelemetry("DEVTOOLS_INSPECTOR_TIME_ACTIVE_SECONDS", null, "hasentries"); + checkTelemetry("DEVTOOLS_OS_ENUMERATED_PER_USER", null, "hasentries"); + checkTelemetry("DEVTOOLS_OS_IS_64_BITS_PER_USER", null, "hasentries"); checkTelemetry("DEVTOOLS_RULEVIEW_OPENED_BOOLEAN", [0,3,0]); checkTelemetry("DEVTOOLS_RULEVIEW_OPENED_PER_USER_FLAG", [0,1,0]); checkTelemetry("DEVTOOLS_RULEVIEW_TIME_ACTIVE_SECONDS", null, "hasentries"); + checkTelemetry("DEVTOOLS_SCREEN_RESOLUTION_ENUMERATED_PER_USER", null, "hasentries"); checkTelemetry("DEVTOOLS_TOOLBOX_OPENED_BOOLEAN", [0,3,0]); checkTelemetry("DEVTOOLS_TOOLBOX_OPENED_PER_USER_FLAG", [0,1,0]); checkTelemetry("DEVTOOLS_TOOLBOX_TIME_ACTIVE_SECONDS", null, "hasentries"); diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index b67188a6acfd..548c95d75000 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -6466,6 +6466,52 @@ "kind": "boolean", "description": "Was WebIDE's debug button used during this runtime connection?" }, + "DEVTOOLS_OS_ENUMERATED_PER_USER": { + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 8, + "description": "OS of DevTools user (0:Windows XP, 1:Windows Vista, 2:Windows 7, 3:Windows 8, 4:Windows 8.1, 5:OSX, 6:Linux 7:other)" + }, + "DEVTOOLS_OS_IS_64_BITS_PER_USER": { + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 3, + "description": "OS bit size of DevTools user (0:32bit, 1:64bit, 2:Unknown)" + }, + "DEVTOOLS_SCREEN_RESOLUTION_ENUMERATED_PER_USER": { + "expires_in_version": "never", + "kind": "enumerated", + "n_values": 13, + "description": "Screen resolution of DevTools user (0:lower, 1:800x600, 2:1024x768, 3:1280x800, 4:1280x1024, 5:1366x768, 6:1440x900, 7:1920x1080, 8:2560×1600, 9:2560×1600, 10:2880x1800, 11:other, 12:higher)" + }, + "DEVTOOLS_TABS_OPEN_PEAK_EXPONENTIAL": { + "expires_in_version": "never", + "kind": "exponential", + "high": "101", + "n_buckets": "100", + "description": "The peak number of open tabs in all windows for a session for devtools users." + }, + "DEVTOOLS_TABS_OPEN_AVERAGE_EXPONENTIAL": { + "expires_in_version": "never", + "kind": "exponential", + "high": "101", + "n_buckets": "100", + "description": "The mean number of open tabs in all windows for a session for devtools users." + }, + "DEVTOOLS_TABS_PINNED_PEAK_EXPONENTIAL": { + "expires_in_version": "never", + "kind": "exponential", + "high": "101", + "n_buckets": "100", + "description": "The peak number of pinned tabs (app tabs) in all windows for a session for devtools users." + }, + "DEVTOOLS_TABS_PINNED_AVERAGE_EXPONENTIAL": { + "expires_in_version": "never", + "kind": "exponential", + "high": "101", + "n_buckets": "100", + "description": "The mean number of pinned tabs (app tabs) in all windows for a session for devtools users." + }, "BROWSER_IS_USER_DEFAULT": { "expires_in_version": "never", "kind": "boolean",