Bug 949775 - UITelemetry should drop events on the floor if telemetry is disabled. r=mfinkle
☠☠ backed out by 23dffe2643bc ☠ ☠
authorRichard Newman <rnewman@mozilla.com>
Tue, 17 Dec 2013 21:47:58 -0800
changeset 161018 837203a4e0768cf31088280f0d43191593f7c677
parent 161017 de09aa9a5c09104432e49ff233c76dfcbbcc7aff
child 161019 9c9c3e3e7bc25ba3beb7f0e55a7ea7ae57749900
push id3372
push usercbook@mozilla.com
push dateWed, 18 Dec 2013 12:06:28 +0000
treeherderb2g-inbound@0758d09c0962 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs949775
milestone29.0a1
Bug 949775 - UITelemetry should drop events on the floor if telemetry is disabled. r=mfinkle
toolkit/components/telemetry/UITelemetry.jsm
toolkit/components/telemetry/moz.build
--- a/toolkit/components/telemetry/UITelemetry.jsm
+++ b/toolkit/components/telemetry/UITelemetry.jsm
@@ -1,31 +1,83 @@
 /* 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";
 
 const Cu = Components.utils;
 
+const PREF_BRANCH = "toolkit.telemetry.";
+#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
+const PREF_ENABLED = PREF_BRANCH + "enabledPreRelease";
+#else
+const PREF_ENABLED = PREF_BRANCH + "enabled";
+#endif
+
 this.EXPORTED_SYMBOLS = [
   "UITelemetry",
 ];
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 /**
  * UITelemetry is a helper JSM used to record UI specific telemetry events.
  *
  * It implements nsIUITelemetryObserver, defined in nsIAndroidBridge.idl.
  */
 this.UITelemetry = Object.freeze({
+  _enabled: undefined,
   _activeSessions: {},
   _measurements: [],
 
+  // Lazily decide whether telemetry is enabled.
+  get enabled() {
+    if (this._enabled !== undefined) {
+      return this._enabled;
+    }
+
+    // Set an observer to watch for changes at runtime.
+    Services.prefs.addObserver(PREF_ENABLED, this, false);
+    Services.obs.addObserver(this, "profile-before-change", false);
+
+    // Pick up the current value.
+    try {
+      this._enabled = Services.prefs.getBoolPref(PREF_ENABLED);
+    } catch (e) {
+      this._enabled = false;
+    }
+
+    return this._enabled;
+  },
+
+  observe: function(aSubject, aTopic, aData) {
+    if (aTopic == "profile-before-change") {
+      Services.obs.removeObserver(this, "profile-before-change");
+      Services.prefs.removeObserver(PREF_ENABLED, this);
+      this._enabled = undefined;
+      return;
+    }
+
+    if (aTopic == "nsPref:changed") {
+      switch (aData) {
+        case PREF_ENABLED:
+          let on = Services.prefs.getBoolPref(PREF_ENABLED);
+          this._enabled = on;
+
+          // Wipe ourselves if we were just disabled.
+          if (!on) {
+            this._activeSessions = {};
+            this._measurements = [];
+          }
+          break;
+      }
+    }
+  },
+
   /**
    * This exists exclusively for testing -- our events are not intended to
    * be retrieved via an XPCOM interface.
    */
   get wrappedJSObject() {
     return this;
   },
 
@@ -41,16 +93,20 @@ this.UITelemetry = Object.freeze({
    * method.
    *
    * Optionally provide a string 'extras', which will be recorded as part of
    * the event.
    *
    * All extant sessions will be recorded by name for each event.
    */
   addEvent: function(aAction, aMethod, aTimestamp, aExtras) {
+    if (!this.enabled) {
+      return;
+    }
+
     let sessions = Object.keys(this._activeSessions);
     let aEvent = {
       type: "event",
       action: aAction,
       method: aMethod,
       sessions: sessions,
       timestamp: aTimestamp,
     };
@@ -61,27 +117,35 @@ this.UITelemetry = Object.freeze({
 
     this._recordEvent(aEvent);
   },
 
   /**
    * Begins tracking a session by storing a timestamp for session start.
    */
   startSession: function(aName, aTimestamp) {
+    if (!this.enabled) {
+      return;
+    }
+
     if (this._activeSessions[aName]) {
       // Do not overwrite a previous event start if it already exists.
       return;
     }
     this._activeSessions[aName] = aTimestamp;
   },
 
   /**
    * Tracks the end of a session with a timestamp.
    */
   stopSession: function(aName, aReason, aTimestamp) {
+    if (!this.enabled) {
+      return;
+    }
+
     let sessionStart = this._activeSessions[aName];
     delete this._activeSessions[aName];
 
     if (!sessionStart) {
       Services.console.logStringMessage("UITelemetry error: no session [" + aName + "] to stop!");
       return;
     }
 
@@ -102,16 +166,20 @@ this.UITelemetry = Object.freeze({
 
   /**
    * Called by TelemetryPing to populate the simple measurement
    * blob. This function will iterate over all functions added
    * via addSimpleMeasureFunction and return an object with the
    * results of those functions.
    */
   getSimpleMeasures: function() {
+    if (!this.enabled) {
+      return {};
+    }
+
     let result = {};
     for (let name in this._simpleMeasureFunctions) {
       result[name] = this._simpleMeasureFunctions[name]();
     }
     return result;
   },
 
   /**
@@ -119,27 +187,35 @@ this.UITelemetry = Object.freeze({
    * for simple measures during a Telemetry ping. aName is a unique
    * identifier used as they key for the simple measurement in the
    * object that getSimpleMeasures returns.
    *
    * This function throws an exception if aName already has a function
    * registered for it.
    */
   addSimpleMeasureFunction: function(aName, aFunction) {
+    if (!this.enabled) {
+      return;
+    }
+
     if (aName in this._simpleMeasureFunctions) {
       throw new Error("A simple measurement function is already registered for " + aName);
     }
 
     if (!aFunction || typeof aFunction !== 'function') {
       throw new Error("addSimpleMeasureFunction called with non-function argument.");
     }
 
     this._simpleMeasureFunctions[aName] = aFunction;
   },
 
   removeSimpleMeasureFunction: function(aName) {
     delete this._simpleMeasureFunctions[aName];
   },
 
-  getUIMeasurements: function getUIMeasurements() {
+  getUIMeasurements: function() {
+    if (!this.enabled) {
+      return [];
+    }
+
     return this._measurements.slice();
   }
 });
--- a/toolkit/components/telemetry/moz.build
+++ b/toolkit/components/telemetry/moz.build
@@ -30,16 +30,19 @@ EXTRA_COMPONENTS += [
 EXTRA_PP_COMPONENTS += [
     'TelemetryPing.js',
 ]
 
 EXTRA_JS_MODULES += [
     'TelemetryFile.jsm',
     'TelemetryStopwatch.jsm',
     'ThirdPartyCookieProbe.jsm',
+]
+
+EXTRA_PP_JS_MODULES += [
     'UITelemetry.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')