Bug 1183632 - Don't generate child Telemetry payloads for the thumbnail service in non-e10s. r=dexter
authorGeorg Fritzsche <georg.fritzsche@googlemail.com>
Tue, 28 Jul 2015 18:05:35 +0200
changeset 255030 060139fdfbfd15e233796451de65839449863126
parent 255029 f017050afdf21ed44cdf5128a08e5973a226ab8e
child 255031 daf25286f46125c4f254d18fb6d32a915ad4dbd1
push id29127
push userkwierso@gmail.com
push dateWed, 29 Jul 2015 00:53:00 +0000
treeherdermozilla-central@a828e099f0af [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdexter
bugs1183632
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1183632 - Don't generate child Telemetry payloads for the thumbnail service in non-e10s. r=dexter
toolkit/components/telemetry/TelemetryController.jsm
toolkit/components/telemetry/TelemetrySession.jsm
toolkit/components/telemetry/TelemetryUtils.jsm
toolkit/components/telemetry/tests/unit/test_ChildHistograms.js
--- a/toolkit/components/telemetry/TelemetryController.jsm
+++ b/toolkit/components/telemetry/TelemetryController.jsm
@@ -588,19 +588,30 @@ let Impl = {
   },
 
   /**
    * Perform telemetry initialization for either chrome or content process.
    * @return {Boolean} True if Telemetry is allowed to record at least base (FHR) data,
    *                   false otherwise.
    */
   enableTelemetryRecording: function enableTelemetryRecording() {
-    const enabled = Preferences.get(PREF_ENABLED, false);
+    // The thumbnail service also runs in a content process, even with e10s off.
+    // We need to check if e10s is on so we don't submit child payloads for it.
+    // We still need xpcshell child tests to work, so we skip this if test mode is enabled.
+    if (Utils.isContentProcess && !this._testMode && !Services.appinfo.browserTabsRemoteAutostart) {
+      this._log.config("enableTelemetryRecording - not enabling Telemetry for non-e10s child process");
+      Telemetry.canRecordBase = false;
+      Telemetry.canRecordExtended = false;
+      return false;
+    }
 
-    // Enable base Telemetry recording, if needed.
+    // Configure base Telemetry recording.
+    // Unified Telemetry makes it opt-out unless the unifedOptin pref is set.
+    // If extended Telemetry is enabled, base recording is always on as well.
+    const enabled = Preferences.get(PREF_ENABLED, false);
     Telemetry.canRecordBase = enabled || (IS_UNIFIED_TELEMETRY && !IS_UNIFIED_OPTIN);
 
 #ifdef MOZILLA_OFFICIAL
     // Enable extended telemetry if:
     //  * the telemetry preference is set and
     //  * this is an official build or we are in test-mode
     // We only do the latter check for official builds so that e.g. developer builds
     // still enable Telemetry based on prefs.
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -22,23 +22,16 @@ Cu.import("resource://gre/modules/Task.j
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://gre/modules/TelemetrySend.jsm", this);
 Cu.import("resource://gre/modules/TelemetryUtils.jsm", this);
 
 const Utils = TelemetryUtils;
 
 const myScope = this;
 
-const IS_CONTENT_PROCESS = (function() {
-  // We cannot use Services.appinfo here because in telemetry xpcshell tests,
-  // appinfo is initially unavailable, and becomes available only later on.
-  let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
-  return runtime.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
-})();
-
 // When modifying the payload in incompatible ways, please bump this version number
 const PAYLOAD_VERSION = 4;
 const PING_TYPE_MAIN = "main";
 const PING_TYPE_SAVED_SESSION = "saved-session";
 
 const REASON_ABORTED_SESSION = "aborted-session";
 const REASON_DAILY = "daily";
 const REASON_SAVED_SESSION = "saved-session";
@@ -53,17 +46,17 @@ const ENVIRONMENT_CHANGE_LISTENER = "Tel
 const MS_IN_ONE_HOUR  = 60 * 60 * 1000;
 const MIN_SUBSESSION_LENGTH_MS = 10 * 60 * 1000;
 
 // This is the HG changeset of the Histogram.json file, used to associate
 // submitted ping data with its histogram definition (bug 832007)
 #expand const HISTOGRAMS_FILE_VERSION = "__HISTOGRAMS_FILE_VERSION__";
 
 const LOGGER_NAME = "Toolkit.Telemetry";
-const LOGGER_PREFIX = "TelemetrySession" + (IS_CONTENT_PROCESS ? "#content::" : "::");
+const LOGGER_PREFIX = "TelemetrySession" + (Utils.isContentProcess ? "#content::" : "::");
 
 const PREF_BRANCH = "toolkit.telemetry.";
 const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID";
 const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
 const PREF_ASYNC_PLUGIN_INIT = "dom.ipc.plugins.asyncInit";
 const PREF_UNIFIED = PREF_BRANCH + "unified";
 
 
@@ -744,16 +737,22 @@ this.TelemetrySession = Object.freeze({
    * Used only for testing purposes.
    */
   setup: function() {
     return Impl.setupChromeProcess(true);
   },
   /**
    * Used only for testing purposes.
    */
+  setupContent: function() {
+    return Impl.setupContentProcess(true);
+  },
+  /**
+   * Used only for testing purposes.
+   */
   uninstall: function() {
     try {
       Impl.uninstall();
     } catch (ex) {
       // Ignore errors
     }
   },
   /**
@@ -848,17 +847,17 @@ let Impl = {
     var appTimestamps = {};
     try {
       let o = {};
       Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", o);
       appTimestamps = o.TelemetryTimestamps.get();
     } catch (ex) {}
 
     // Only submit this if the extended set is enabled.
-    if (!IS_CONTENT_PROCESS && Telemetry.canRecordExtended) {
+    if (!Utils.isContentProcess && Telemetry.canRecordExtended) {
       try {
         ret.addonManager = AddonManagerPrivate.getSimpleMeasures();
         ret.UITelemetry = UITelemetry.getSimpleMeasures();
       } catch (ex) {}
     }
 
     if (si.process) {
       for each (let field in Object.keys(si)) {
@@ -877,17 +876,17 @@ let Impl = {
 
     ret.js = Cu.getJSEngineTelemetryValue();
 
     let maximalNumberOfConcurrentThreads = Telemetry.maximalNumberOfConcurrentThreads;
     if (maximalNumberOfConcurrentThreads) {
       ret.maximalNumberOfConcurrentThreads = maximalNumberOfConcurrentThreads;
     }
 
-    if (IS_CONTENT_PROCESS) {
+    if (Utils.isContentProcess) {
       return ret;
     }
 
     // Measurements specific to chrome process
 
     // Update debuggerAttached flag
     let debugService = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
     let isDebuggerAttached = debugService.isDebuggerAttached;
@@ -1301,17 +1300,17 @@ let Impl = {
 
     // Add extended set measurements common to chrome & content processes
     if (Telemetry.canRecordExtended) {
       payloadObj.chromeHangs = Telemetry.chromeHangs;
       payloadObj.threadHangStats = this.getThreadHangStats(Telemetry.threadHangStats);
       payloadObj.log = TelemetryLog.entries();
     }
 
-    if (IS_CONTENT_PROCESS) {
+    if (Utils.isContentProcess) {
       return payloadObj;
     }
 
     // Additional payload for chrome process.
     payloadObj.info = info;
 
     // Add extended set measurements for chrome process.
     if (Telemetry.canRecordExtended) {
@@ -1359,20 +1358,20 @@ let Impl = {
     clearSubsession = false;
     const isSubsession = false;
 #else
     const isSubsession = !this._isClassicReason(reason);
 #endif
 
     let measurements =
       this.getSimpleMeasurements(reason == REASON_SAVED_SESSION, isSubsession, clearSubsession);
-    let info = !IS_CONTENT_PROCESS ? this.getMetadata(reason) : null;
+    let info = !Utils.isContentProcess ? this.getMetadata(reason) : null;
     let payload = this.assemblePayloadWithMeasurements(measurements, info, reason, clearSubsession);
 
-    if (!IS_CONTENT_PROCESS && clearSubsession) {
+    if (!Utils.isContentProcess && clearSubsession) {
       this.startNewSubsession();
       // Persist session data to disk (don't wait until it completes).
       let sessionData = this._getSessionDataObject();
       this._stateSaveSerializer.enqueueTask(() => this._saveSessionData(sessionData));
     }
 
     return payload;
   },
@@ -1523,34 +1522,35 @@ let Impl = {
 
     this._delayedInitTask.arm();
     return this._delayedInitTaskDeferred.promise;
   },
 
   /**
    * Initializes telemetry for a content process.
    */
-  setupContentProcess: function setupContentProcess() {
+  setupContentProcess: function setupContentProcess(testing) {
     this._log.trace("setupContentProcess");
 
     if (!Telemetry.canRecordBase) {
+      this._log.trace("setupContentProcess - base recording is disabled, not initializing");
       return;
     }
 
     Services.obs.addObserver(this, "content-child-shutdown", false);
     cpml.addMessageListener(MESSAGE_TELEMETRY_GET_CHILD_PAYLOAD, this);
 
     this.gatherStartupHistograms();
 
     let delayedTask = new DeferredTask(function* () {
       this._initialized = true;
 
       this.attachObservers();
       this.gatherMemory();
-    }.bind(this), TELEMETRY_DELAY);
+    }.bind(this), testing ? TELEMETRY_TEST_DELAY : TELEMETRY_DELAY);
 
     delayedTask.arm();
   },
 
   getFlashVersion: function getFlashVersion() {
     this._log.trace("getFlashVersion");
     let host = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
     let tags = host.getPluginTags();
--- a/toolkit/components/telemetry/TelemetryUtils.jsm
+++ b/toolkit/components/telemetry/TelemetryUtils.jsm
@@ -7,18 +7,32 @@
 this.EXPORTED_SYMBOLS = [
   "TelemetryUtils"
 ];
 
 const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
 const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
 
+const IS_CONTENT_PROCESS = (function() {
+  // We cannot use Services.appinfo here because in telemetry xpcshell tests,
+  // appinfo is initially unavailable, and becomes available only later on.
+  let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
+  return runtime.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
+})();
+
 this.TelemetryUtils = {
   /**
+   * True if this is a content process.
+   */
+  get isContentProcess() {
+    return IS_CONTENT_PROCESS;
+  },
+
+  /**
    * Turn a millisecond timestamp into a day timestamp.
    *
    * @param aMsec A number of milliseconds since Unix epoch.
    * @return The number of whole days since Unix epoch.
    */
   millisecondsToDays: function(aMsec) {
     return Math.floor(aMsec / MILLISECONDS_PER_DAY);
   },
--- a/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js
+++ b/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js
@@ -1,16 +1,18 @@
 
 Cu.import("resource://gre/modules/TelemetryController.jsm", this);
 Cu.import("resource://gre/modules/TelemetrySession.jsm", this);
 Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
 
 const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
 
 const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload";
+const MESSAGE_TELEMETRY_GET_CHILD_PAYLOAD = "Telemetry:GetChildPayload";
+const MESSAGE_CHILD_TEST_DONE = "ChildTest:Done";
 
 const PLATFORM_VERSION = "1.9.2";
 const APP_VERSION = "1";
 const APP_ID = "xpcshell@tests.mozilla.org";
 const APP_NAME = "XPCShell";
 
 function run_child_test() {
   // Setup histograms with some fixed values.
@@ -53,34 +55,42 @@ function check_histogram_values(payload)
                "Keyed flag test histogram should have the right value.");
   Assert.equal(kh["TELEMETRY_TEST_KEYED_FLAG"]["b"].sum, 1,
                "Keyed flag test histogram should have the right value.");
 }
 
 add_task(function*() {
   if (!runningInParent) {
     TelemetryController.setupContent();
+    TelemetrySession.setupContent();
     run_child_test();
+    dump("... done with child test\n");
+    do_send_remote_message(MESSAGE_CHILD_TEST_DONE);
+    dump("... waiting for child payload collection\n");
+    yield do_await_remote_message(MESSAGE_TELEMETRY_GET_CHILD_PAYLOAD);
     return;
   }
 
   // Setup.
   do_get_profile(true);
   loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
   Services.prefs.setBoolPref("toolkit.telemetry.enabled", true);
   yield TelemetryController.setup();
   yield TelemetrySession.setup();
 
-  // Run test in child and wait until it is finished.
-  yield run_test_in_child("test_ChildHistograms.js");
+  // Run test in child, don't wait for it to finish.
+  let childPromise = run_test_in_child("test_ChildHistograms.js");
+  yield do_await_remote_message(MESSAGE_CHILD_TEST_DONE);
 
   // Gather payload from child.
+  dump("... requesting child payloads\n");
   let promiseMessage = do_await_remote_message(MESSAGE_TELEMETRY_PAYLOAD);
   TelemetrySession.requestChildPayloads();
   yield promiseMessage;
+  dump("... received child payload\n");
 
   // Check child payload.
   const payload = TelemetrySession.getPayload("test-ping");
   Assert.ok("childPayloads" in payload, "Should have child payloads.");
   Assert.equal(payload.childPayloads.length, 1, "Should have received one child payload so far.");
   Assert.ok("histograms" in payload.childPayloads[0], "Child payload should have histograms.");
   Assert.ok("keyedHistograms" in payload.childPayloads[0], "Child payload should have keyed histograms.");
   check_histogram_values(payload.childPayloads[0]);