Bug 1148500 - Part 3 (Fx 40): Honor toolkit.telemetry.unified pref in Telemetry modules. r=dexter
authorGeorg Fritzsche <georg.fritzsche@googlemail.com>
Thu, 30 Apr 2015 14:00:58 +0200
changeset 273200 b2c68526576dfb6df05812b5432175b070ce6105
parent 273199 0df0d478d39641db7e3b3a567397f37ca270b09e
child 273201 01ff4e0d37ae8cf8b00a23ad856ed5a2abcd1445
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdexter
bugs1148500
milestone40.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 1148500 - Part 3 (Fx 40): Honor toolkit.telemetry.unified pref in Telemetry modules. r=dexter
toolkit/components/telemetry/TelemetryController.jsm
toolkit/components/telemetry/TelemetrySession.jsm
--- a/toolkit/components/telemetry/TelemetryController.jsm
+++ b/toolkit/components/telemetry/TelemetryController.jsm
@@ -30,16 +30,21 @@ const PREF_BRANCH_LOG = PREF_BRANCH + "l
 const PREF_SERVER = PREF_BRANCH + "server";
 const PREF_ENABLED = PREF_BRANCH + "enabled";
 const PREF_LOG_LEVEL = PREF_BRANCH_LOG + "level";
 const PREF_LOG_DUMP = PREF_BRANCH_LOG + "dump";
 const PREF_CACHED_CLIENTID = PREF_BRANCH + "cachedClientID";
 const PREF_FHR_ENABLED = "datareporting.healthreport.service.enabled";
 const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
 const PREF_SESSIONS_BRANCH = "datareporting.sessions.";
+const PREF_UNIFIED = PREF_BRANCH + "unified";
+
+// Whether the FHR/Telemetry unification features are enabled.
+// Changing this pref requires a restart.
+const IS_UNIFIED_TELEMETRY = Preferences.get(PREF_UNIFIED, false);
 
 const PING_FORMAT_VERSION = 4;
 
 // Delay before intializing telemetry (ms)
 const TELEMETRY_DELAY = 60000;
 // Delay before initializing telemetry if we're testing (ms)
 const TELEMETRY_TEST_DELAY = 100;
 // The number of days to keep pings serialised on the disk in case of failures.
@@ -811,35 +816,31 @@ 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);
+
     // Enable base Telemetry recording, if needed.
-#if !defined(MOZ_WIDGET_ANDROID)
-    Telemetry.canRecordBase = Preferences.get(PREF_FHR_ENABLED, false);
-#else
-    // FHR recording is always "enabled" on Android (data upload is not).
-    Telemetry.canRecordBase = true;
-#endif
+    Telemetry.canRecordBase = enabled || IS_UNIFIED_TELEMETRY;
 
 #ifdef MOZILLA_OFFICIAL
     if (!Telemetry.isOfficialTelemetry && !this._testMode) {
       // We can't send data; no point in initializing observers etc.
       // Only do this for official builds so that e.g. developer builds
       // still enable Telemetry based on prefs.
       Telemetry.canRecordExtended = false;
       this._log.config("enableTelemetryRecording - Can't send data, disabling extended Telemetry recording.");
     }
 #endif
 
-    let enabled = Preferences.get(PREF_ENABLED, false);
     this._server = Preferences.get(PREF_SERVER, undefined);
     if (!enabled || !Telemetry.canRecordBase) {
       // Turn off extended telemetry recording if disabled by preferences or if base/telemetry
       // telemetry recording is off.
       Telemetry.canRecordExtended = false;
       this._log.config("enableTelemetryRecording - Disabling extended Telemetry recording.");
     }
 
@@ -869,26 +870,23 @@ let Impl = {
 
     if (this._initialized && !this._testMode) {
       this._log.error("setupTelemetry - already initialized");
       return Promise.resolve();
     }
 
     // Only initialize the session recorder if FHR is enabled.
     // TODO: move this after the |enableTelemetryRecording| block and drop the
-    // PREF_FHR_ENABLED check after bug 1137252 lands.
-    if (!this._sessionRecorder && Preferences.get(PREF_FHR_ENABLED, true)) {
+    // PREF_FHR_ENABLED check once we permanently switch over to unified Telemetry.
+    if (!this._sessionRecorder &&
+        (Preferences.get(PREF_FHR_ENABLED, true) || IS_UNIFIED_TELEMETRY)) {
       this._sessionRecorder = new SessionRecorder(PREF_SESSIONS_BRANCH);
       this._sessionRecorder.onStartup();
     }
 
-    // Initialize some probes that are kept in their own modules
-    this._thirdPartyCookies = new ThirdPartyCookieProbe();
-    this._thirdPartyCookies.init();
-
     if (!this.enableTelemetryRecording()) {
       this._log.config("setupChromeProcess - Telemetry recording is disabled, skipping Chrome process setup.");
       return Promise.resolve();
     }
 
     // For very short session durations, we may never load the client
     // id from disk.
     // We try to cache it in prefs to avoid this, even though this may
@@ -1026,21 +1024,23 @@ let Impl = {
 
   get clientID() {
     return this._clientID;
   },
 
   /**
    * Check if pings can be sent to the server. If FHR is not allowed to upload,
    * pings are not sent to the server (Telemetry is a sub-feature of FHR).
+   * If unified telemetry is off, don't send pings if Telemetry is disabled.
    * @return {Boolean} True if pings can be send to the servers, false otherwise.
    */
   _canSend: function() {
     return (Telemetry.isOfficialTelemetry || this._testMode) &&
-           Preferences.get(PREF_FHR_UPLOAD_ENABLED, false);
+           Preferences.get(PREF_FHR_UPLOAD_ENABLED, false) &&
+           (IS_UNIFIED_TELEMETRY || Preferences.get(PREF_ENABLED));
   },
 
   /**
    * Get an object describing the current state of this module for AsyncShutdown diagnostics.
    */
   _getState: function() {
     return {
       initialized: this._initialized,
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -55,25 +55,31 @@ const MIN_SUBSESSION_LENGTH_MS = 10 * 60
 
 const LOGGER_NAME = "Toolkit.Telemetry";
 const LOGGER_PREFIX = "TelemetrySession::";
 
 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";
+
 
 const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload";
 const MESSAGE_TELEMETRY_GET_CHILD_PAYLOAD = "Telemetry:GetChildPayload";
 
 const DATAREPORTING_DIRECTORY = "datareporting";
 const ABORTED_SESSION_FILE_NAME = "aborted-session-ping";
 
 const SESSION_STATE_FILE_NAME = "session-state.json";
 
+// Whether the FHR/Telemetry unification features are enabled.
+// Changing this pref requires a restart.
+const IS_UNIFIED_TELEMETRY = Preferences.get(PREF_UNIFIED, false);
+
 // Maximum number of content payloads that we are willing to store.
 const MAX_NUM_CONTENT_PAYLOADS = 10;
 
 // Do not gather data more than once a minute
 const TELEMETRY_INTERVAL = 60000;
 // Delay before intializing telemetry (ms)
 const TELEMETRY_DELAY = 60000;
 // Delay before initializing telemetry if we're testing (ms)
@@ -1334,22 +1340,18 @@ let Impl = {
 
   /**
    * Get the current session's payload using the provided
    * simpleMeasurements and info, which are typically obtained by a call
    * to |this.getSimpleMeasurements| and |this.getMetadata|,
    * respectively.
    */
   assemblePayloadWithMeasurements: function(simpleMeasurements, info, reason, clearSubsession) {
-#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
-    const isSubsession = !this._isClassicReason(reason);
-#else
-    const isSubsession = false;
-    clearSubsession = false;
-#endif
+    const isSubsession = IS_UNIFIED_TELEMETRY && !this._isClassicReason(reason);
+    clearSubsession = IS_UNIFIED_TELEMETRY && clearSubsession;
     this._log.trace("assemblePayloadWithMeasurements - reason: " + reason +
                     ", submitting subsession data: " + isSubsession);
 
     // Payload common to chrome and content processes.
     let payloadObj = {
       ver: PAYLOAD_VERSION,
       simpleMeasurements: simpleMeasurements,
       histograms: this.getHistograms(isSubsession, clearSubsession),
@@ -1476,16 +1478,21 @@ let Impl = {
       return this._delayedInitTaskDeferred.promise;
     }
 
     if (this._initialized && !testing) {
       this._log.error("setupChromeProcess - already initialized");
       return Promise.resolve();
     }
 
+    if (!Telemetry.canRecordBase && !testing) {
+      this._log.config("setupChromeProcess - Telemetry recording is disabled, skipping Chrome process setup.");
+      return Promise.resolve();
+    }
+
     // Generate a unique id once per session so the server can cope with duplicate
     // submissions, orphaning and other oddities. The id is shared across subsessions.
     this._sessionId = Policy.generateSessionUUID();
     this.startNewSubsession();
     // startNewSubsession sets |_subsessionStartDate| to the current date/time. Use
     // the very same value for |_sessionStartDate|.
     this._sessionStartDate = this._subsessionStartDate;
 
@@ -1498,21 +1505,16 @@ let Impl = {
     let previousBuildId = Preferences.get(PREF_PREVIOUS_BUILDID, null);
     let thisBuildID = Services.appinfo.appBuildID;
     // If there is no previousBuildId preference, we send null to the server.
     if (previousBuildId != thisBuildID) {
       this._previousBuildId = previousBuildId;
       Preferences.set(PREF_PREVIOUS_BUILDID, thisBuildID);
     }
 
-    if (!Telemetry.canRecordBase && !testing) {
-      this._log.config("setupChromeProcess - Telemetry recording is disabled, skipping Chrome process setup.");
-      return Promise.resolve();
-    }
-
     TelemetryController.shutdown.addBlocker("TelemetrySession: shutting down",
                                       () => this.shutdownChromeProcess(),
                                       () => this._getState());
 
     Services.obs.addObserver(this, "sessionstore-windows-restored", false);
 #ifdef MOZ_WIDGET_ANDROID
     Services.obs.addObserver(this, "application-background", false);
 #endif
@@ -1536,33 +1538,36 @@ let Impl = {
           yield this._saveSessionData(this._getSessionDataObject()).catch(() =>
             this._log.error("setupChromeProcess - Could not write session data to disk."));
         }
         this.attachObservers();
         this.gatherMemory();
 
         Telemetry.asyncFetchTelemetryData(function () {});
 
-#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
-        // Check for a previously written aborted session ping.
-        yield this._checkAbortedSessionPing();
+        if (IS_UNIFIED_TELEMETRY) {
+          // Check for a previously written aborted session ping.
+          yield this._checkAbortedSessionPing();
 
-        TelemetryEnvironment.registerChangeListener(ENVIRONMENT_CHANGE_LISTENER,
-                                                    (reason, data) => this._onEnvironmentChange(reason, data));
-        // Write the first aborted-session ping as early as possible. Just do that
-        // if we are not testing, since calling Telemetry.reset() will make a previous
-        // aborted ping a pending ping.
-        if (!testing) {
-          yield this._saveAbortedSessionPing();
+          // Write the first aborted-session ping as early as possible. Just do that
+          // if we are not testing, since calling Telemetry.reset() will make a previous
+          // aborted ping a pending ping.
+          if (!testing) {
+            yield this._saveAbortedSessionPing();
+          }
+
+          TelemetryEnvironment.registerChangeListener(ENVIRONMENT_CHANGE_LISTENER,
+                                 (reason, data) => this._onEnvironmentChange(reason, data));
+
+          // Start the scheduler.
+          // We skip this if unified telemetry is off, so we don't
+          // trigger the new unified ping types.
+          TelemetryScheduler.init();
         }
 
-        // Start the scheduler.
-        TelemetryScheduler.init();
-#endif
-
         this._delayedInitTaskDeferred.resolve();
       } catch (e) {
         this._delayedInitTaskDeferred.reject(e);
       } finally {
         this._delayedInitTask = null;
         this._delayedInitTaskDeferred = null;
       }
     }.bind(this), testing ? TELEMETRY_TEST_DELAY : TELEMETRY_DELAY);
@@ -1658,33 +1663,33 @@ let Impl = {
   },
 
   /**
    * Save both the "saved-session" and the "shutdown" pings to disk.
    */
   savePendingPings: function savePendingPings() {
     this._log.trace("savePendingPings");
 
-#ifndef MOZ_WIDGET_ANDROID
+    if (!IS_UNIFIED_TELEMETRY) {
+      return this.savePendingPingsClassic();
+    }
+
     let options = {
       retentionDays: RETENTION_DAYS,
       addClientId: true,
       addEnvironment: true,
       overwrite: true,
     };
 
     let shutdownPayload = this.getSessionPayload(REASON_SHUTDOWN, false);
     // Make sure we try to save the pending pings, even though we failed saving the shutdown
     // ping.
     return TelemetryController.addPendingPing(getPingType(shutdownPayload), shutdownPayload, options)
                         .then(() => this.savePendingPingsClassic(),
                               () => this.savePendingPingsClassic());
-#else
-    return this.savePendingPingsClassic();
-#endif
   },
 
   /**
    * Save the "saved-session" ping and make TelemetryController save all the pending pings to disk.
    */
   savePendingPingsClassic: function savePendingPingsClassic() {
     this._log.trace("savePendingPingsClassic");
     let payload = this.getSessionPayload(REASON_SAVED_SESSION, false);
@@ -1864,35 +1869,39 @@ let Impl = {
    * This tells TelemetrySession to uninitialize and save any pending pings.
    * @param testing Optional. If true, always saves the ping whether Telemetry
    *                can send pings or not, which is used for testing.
    */
   shutdownChromeProcess: function(testing = false) {
     this._log.trace("shutdownChromeProcess - testing: " + testing);
 
     let cleanup = () => {
-#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
-      TelemetryEnvironment.unregisterChangeListener(ENVIRONMENT_CHANGE_LISTENER);
-      TelemetryScheduler.shutdown();
-#endif
+      if (IS_UNIFIED_TELEMETRY) {
+        TelemetryEnvironment.unregisterChangeListener(ENVIRONMENT_CHANGE_LISTENER);
+        TelemetryScheduler.shutdown();
+      }
       this.uninstall();
 
       let reset = () => {
         this._initStarted = false;
         this._initialized = false;
       };
 
       if (Telemetry.isOfficialTelemetry || testing) {
-        return this.savePendingPings()
-                .then(() => this._stateSaveSerializer.flushTasks())
-#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
-                .then(() => this._abortedSessionSerializer
-                                .enqueueTask(() => this._removeAbortedSessionPing()))
-#endif
-                .then(reset);
+        return Task.spawn(function*() {
+          yield this.savePendingPings();
+          yield this._stateSaveSerializer.flushTasks();
+
+          if (IS_UNIFIED_TELEMETRY) {
+            yield this._abortedSessionSerializer
+                      .enqueueTask(() => this._removeAbortedSessionPing());
+          }
+
+          reset();
+        }.bind(this));
       }
 
       reset();
       return Promise.resolve();
     };
 
     // We can be in one the following states here:
     // 1) setupChromeProcess was never called
@@ -1928,23 +1937,21 @@ let Impl = {
 
     let options = {
       retentionDays: RETENTION_DAYS,
       addClientId: true,
       addEnvironment: true,
     };
 
     let promise = TelemetryController.submitExternalPing(getPingType(payload), payload, options);
-#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
     // If required, also save the payload as an aborted session.
-    if (saveAsAborted) {
+    if (saveAsAborted && IS_UNIFIED_TELEMETRY) {
       let abortedPromise = this._saveAbortedSessionPing(payload);
       promise = promise.then(() => abortedPromise);
     }
-#endif
     return promise;
   },
 
   /**
    * Loads session data from the session data file.
    * @return {Promise<boolean>} A promise which is resolved with a true argument when
    *                            loading has completed, with false otherwise.
    */