Bug 841028: Add last build ID to telemetry system info if build ID has changed. r=froydnj
☠☠ backed out by 828162ad3ab0 ☠ ☠
authorIrving Reid <irving@mozilla.com>
Thu, 14 Mar 2013 16:02:36 -0400
changeset 136043 3614febde426849e3c1972e9be90bb66191cd569
parent 136042 d4a5a1e1e8e9187ec190091702039d35c433dbce
child 136044 7d2ea731f5a5309583451dc519c6bedb1e692ddd
push id336
push userakeybl@mozilla.com
push dateMon, 17 Jun 2013 22:53:19 +0000
treeherdermozilla-release@574a39cdf657 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs841028
milestone22.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 841028: Add last build ID to telemetry system info if build ID has changed. r=froydnj
toolkit/components/telemetry/TelemetryPing.js
toolkit/components/telemetry/tests/unit/test_TelemetryPingBuildID.js
toolkit/components/telemetry/tests/unit/xpcshell.ini
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -18,22 +18,25 @@ Cu.import("resource://gre/modules/ctypes
 
 // When modifying the payload in incompatible ways, please bump this version number
 const PAYLOAD_VERSION = 1;
 
 // 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 PREF_SERVER = "toolkit.telemetry.server";
+const PREF_BRANCH = "toolkit.telemetry.";
+const PREF_SERVER = PREF_BRANCH + "server";
 #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
-const PREF_ENABLED = "toolkit.telemetry.enabledPreRelease";
+const PREF_ENABLED = PREF_BRANCH + "enabledPreRelease";
 #else
-const PREF_ENABLED = "toolkit.telemetry.enabled";
+const PREF_ENABLED = PREF_BRANCH + "enabled";
 #endif
+const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID";
+
 // Do not gather data more than once a minute
 const TELEMETRY_INTERVAL = 60000;
 // Delay before intializing telemetry (ms)
 const TELEMETRY_DELAY = 60000;
 // Delete ping files that have been lying around for longer than this.
 const MAX_PING_FILE_AGE = 7 * 24 * 60 * 60 * 1000; // 1 week
 // Constants from prio.h for nsIFileOutputStream.init
 const PR_WRONLY = 0x2;
@@ -233,16 +236,19 @@ TelemetryPing.prototype = {
   _doLoadSaveNotifications: false,
   _startupIO : {},
   _hashID: Ci.nsICryptoHash.SHA256,
   // The number of outstanding saved pings that we have issued loading
   // requests for.
   _pingsLoaded: 0,
   // The number of those requests that have actually completed.
   _pingLoadsCompleted: 0,
+  // The previous build ID, if this is the first run with a new build.
+  // Undefined if this is not the first run, or the previous build ID is unknown.
+  _previousBuildID: undefined,
 
   /**
    * When reflecting a histogram into JS, Telemetry hands us an object
    * with the following properties:
    * 
    * - min, max, histogram_type, sum, sum_squares_{lo,hi}: simple integers;
    * - log_sum, log_sum_squares: doubles;
    * - counts: array of counts for histogram buckets;
@@ -361,16 +367,19 @@ TelemetryPing.prototype = {
       appVersion: ai.version,
       appName: ai.name,
       appBuildID: ai.appBuildID,
       appUpdateChannel: UpdateChannel.get(),
       platformBuildID: ai.platformBuildID,
       revision: HISTOGRAMS_FILE_VERSION,
       locale: getLocale()
     };
+    if (this._previousBuildID) {
+      ret.previousBuildID = this._previousBuildID;
+    }
 
     // sysinfo fields are not always available, get what we can.
     let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
     let fields = ["cpucount", "memsize", "arch", "version", "kernel_version",
                   "device", "manufacturer", "hardware",
                   "hasMMX", "hasSSE", "hasSSE2", "hasSSE3",
                   "hasSSSE3", "hasSSE4A", "hasSSE4_1", "hasSSE4_2",
                   "hasEDSP", "hasARMv6", "hasARMv7", "hasNEON", "isWow64"];
@@ -739,28 +748,39 @@ TelemetryPing.prototype = {
       // 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.canRecord = false;
       return;
     }
 #endif
     let enabled = false; 
+    let previousBuildID = undefined;
     try {
       enabled = Services.prefs.getBoolPref(PREF_ENABLED);
       this._server = Services.prefs.getCharPref(PREF_SERVER);
+      previousBuildID = Services.prefs.getCharPref(PREF_PREVIOUS_BUILDID);
     } catch (e) {
       // Prerequesite prefs aren't set
     }
     if (!enabled) {
       // Turn off local telemetry if telemetry is disabled.
       // This may change once about:telemetry is added.
       Telemetry.canRecord = false;
       return;
     }
+    // Record old value and update build ID preference if this is the first run with a new ID.
+    // If there is no previousBuildID preference, this.previousBuildID remains undefined
+    // so no value is sent in the telemetry metadata.
+    let thisBuildID = Services.appinfo.appBuildID;
+    if (previousBuildID != thisBuildID) {
+      this._previousBuildID = previousBuildID;
+      Services.prefs.setCharPref(PREF_PREVIOUS_BUILDID, thisBuildID);
+    }
+
     Services.obs.addObserver(this, "profile-before-change", false);
     Services.obs.addObserver(this, "sessionstore-windows-restored", false);
     Services.obs.addObserver(this, "quit-application-granted", false);
     Services.obs.addObserver(this, "xul-window-visible", false);
     this._hasWindowRestoredObserver = true;
     this._hasXulWindowVisibleObserver = true;
 
     // Delay full telemetry initialization to give the browser time to
new file mode 100644
--- /dev/null
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryPingBuildID.js
@@ -0,0 +1,73 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/
+*/
+/* Test inclusion of previous build ID in telemetry pings when build ID changes.
+ * bug 841028
+ *
+ * Cases to cover:
+ * 1) Run with no "previousBuildID" stored in prefs:
+ *     -> no previousBuildID in telemetry system info, new value set in prefs.
+ * 2) previousBuildID in prefs, equal to current build ID:
+ *     -> no previousBuildID in telemetry, prefs not updated.
+ * 3) previousBuildID in prefs, not equal to current build ID:
+ *     -> previousBuildID in telemetry, new value set in prefs.
+ */
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+// Get the TelemetryPing definitions directly so we can test it without going through xpcom.
+Services.scriptloader.loadSubScript("resource://gre/components/TelemetryPing.js");
+
+// Force the Telemetry enabled preference so that TelemetryPing.setup() doesn't exit early.
+Services.prefs.setBoolPref(PREF_ENABLED, true);
+
+// Set up our dummy AppInfo object so we can control the appBuildID.
+Cu.import("resource://testing-common/AppInfo.jsm");
+updateAppInfo();
+
+// Check that when run with no previous build ID stored, we update the pref but do not
+// put anything into the metadata.
+function testFirstRun() {
+  let ping = new TelemetryPing();
+  ping.setup();
+  let metadata = ping.getMetadata();
+  do_check_false("previousBuildID" in metadata);
+  let appBuildID = getAppInfo().appBuildID;
+  let buildIDPref = Services.prefs.getCharPref(PREF_PREVIOUS_BUILDID);
+  do_check_eq(appBuildID, buildIDPref);
+}
+
+// Check that a subsequent run with the same build ID does not put prev build ID in
+// metadata. Assumes testFirstRun() has already been called to set the previousBuildID pref.
+function testSecondRun() {
+  let ping = new TelemetryPing();
+  ping.setup();
+  let metadata = ping.getMetadata();
+  do_check_false("previousBuildID" in metadata);
+}
+
+
+// Set up telemetry with a different app build ID and check that the old build ID
+// is returned in the metadata and the pref is updated to the new build ID.
+// Assumes testFirstRun() has been called to set the previousBuildID pref.
+const NEW_BUILD_ID = "20130314";
+function testNewBuild() {
+  let info = getAppInfo();
+  let oldBuildID = info.appBuildID;
+  info.appBuildID = NEW_BUILD_ID;
+  let ping = new TelemetryPing();
+  ping.setup();
+  let metadata = ping.getMetadata();
+  do_check_eq(metadata.previousBuildID, oldBuildID);
+  let buildIDPref = Services.prefs.getCharPref(PREF_PREVIOUS_BUILDID);
+  do_check_eq(NEW_BUILD_ID, buildIDPref);
+}
+
+
+function run_test() {
+  // Make sure we have a profile directory.
+  do_get_profile();
+  testFirstRun();
+  testSecondRun();
+  testNewBuild();
+}
--- a/toolkit/components/telemetry/tests/unit/xpcshell.ini
+++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini
@@ -3,8 +3,9 @@ head =
 tail = 
 
 [test_nsITelemetry.js]
 [test_TelemetryPing.js]
 # Bug 676989: test fails consistently on Android
 # fail-if = os == "android"
 [test_TelemetryPing_idle.js]
 [test_TelemetryStopwatch.js]
+[test_TelemetryPingBuildID.js]