Bug 1120363 - Break up Telemetry sessions on environment changes. r=vladan

This commit is contained in:
Georg Fritzsche 2015-02-25 23:54:33 +01:00
parent 1772dadad4
commit 969e9e3b2d
3 changed files with 106 additions and 1 deletions

View File

@ -248,7 +248,7 @@ this.TelemetryEnvironment = {
return;
}
this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, "TelemetryEnvironment::");
this._configureLog();
this._log.trace("init");
this._shutdown = false;
this._startWatchingPrefs();
@ -273,12 +273,22 @@ this.TelemetryEnvironment = {
yield this._collectTask;
}),
_configureLog: function () {
if (this._log) {
return;
}
this._log = Log.repository.getLoggerWithMessagePrefix(
LOGGER_NAME, "TelemetryEnvironment::");
},
/**
* Register a listener for environment changes.
* It's fine to call this on an unitialized TelemetryEnvironment.
* @param name The name of the listener - good for debugging purposes.
* @param listener A JS callback function.
*/
registerChangeListener: function (name, listener) {
this._configureLog();
this._log.trace("registerChangeListener for " + name);
if (this._shutdown) {
this._log.warn("registerChangeListener - already shutdown")
@ -289,9 +299,11 @@ this.TelemetryEnvironment = {
/**
* Unregister from listening to environment changes.
* It's fine to call this on an unitialized TelemetryEnvironment.
* @param name The name of the listener to remove.
*/
unregisterChangeListener: function (name) {
this._configureLog();
this._log.trace("unregisterChangeListener for " + name);
if (this._shutdown) {
this._log.warn("registerChangeListener - already shutdown")

View File

@ -36,6 +36,9 @@ const REASON_SAVED_SESSION = "saved-session";
const REASON_IDLE_DAILY = "idle-daily";
const REASON_GATHER_PAYLOAD = "gather-payload";
const REASON_TEST_PING = "test-ping";
const REASON_ENVIRONMENT_CHANGE = "environment-change";
const ENVIRONMENT_CHANGE_LISTENER = "TelemetrySession::onEnvironmentChange";
const SEC_IN_ONE_DAY = 24 * 60 * 60;
const MS_IN_ONE_DAY = SEC_IN_ONE_DAY * 1000;
@ -110,6 +113,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
"resource://gre/modules/UITelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
"resource://gre/modules/UpdateChannel.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment",
"resource://gre/modules/TelemetryEnvironment.jsm");
function generateUUID() {
let str = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
@ -972,6 +977,9 @@ let Impl = {
Telemetry.asyncFetchTelemetryData(function () {});
this._rescheduleDailyTimer();
TelemetryEnvironment.registerChangeListener(ENVIRONMENT_CHANGE_LISTENER,
() => this._onEnvironmentChange());
deferred.resolve();
}.bind(this), testing ? TELEMETRY_TEST_DELAY : TELEMETRY_DELAY);
@ -1240,6 +1248,8 @@ let Impl = {
* can send pings or not, which is used for testing.
*/
shutdown: function(testing = false) {
TelemetryEnvironment.unregisterChangeListener(ENVIRONMENT_CHANGE_LISTENER);
if (this._dailyTimerId) {
Policy.clearDailyTimeout(this._dailyTimerId);
this._dailyTimerId = null;
@ -1294,6 +1304,18 @@ let Impl = {
return promise;
},
_onEnvironmentChange: function() {
this._log.trace("_onEnvironmentChange");
let payload = this.getSessionPayload(REASON_ENVIRONMENT_CHANGE, true);
let options = {
retentionDays: RETENTION_DAYS,
addClientId: true,
addEnvironment: true,
};
let promise = TelemetryPing.send(PING_TYPE_MAIN, payload, options);
},
_isClassicReason: function(reason) {
const classicReasons = [
REASON_SAVED_SESSION,

View File

@ -20,6 +20,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/TelemetryPing.jsm", this);
Cu.import("resource://gre/modules/TelemetrySession.jsm", this);
Cu.import("resource://gre/modules/TelemetryFile.jsm", this);
Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
Cu.import("resource://gre/modules/Task.jsm", this);
Cu.import("resource://gre/modules/Promise.jsm", this);
Cu.import("resource://gre/modules/Preferences.jsm");
@ -31,6 +32,7 @@ const PING_TYPE_MAIN = "main";
const REASON_SAVED_SESSION = "saved-session";
const REASON_TEST_PING = "test-ping";
const REASON_DAILY = "daily";
const REASON_ENVIRONMENT_CHANGE = "environment-change";
const PLATFORM_VERSION = "1.9.2";
const APP_VERSION = "1";
@ -112,6 +114,11 @@ function futureDate(date, offset) {
return new Date(date.getTime() + offset);
}
function fakeNow(date) {
let session = Cu.import("resource://gre/modules/TelemetrySession.jsm");
session.Policy.now = () => date;
}
function registerPingHandler(handler) {
gHttpServer.registerPrefixHandler("/submit/telemetry/",
wrapWithExceptionHandler(handler));
@ -824,6 +831,70 @@ add_task(function* test_dailyCollection() {
Assert.equal(ping.payload.keyedHistograms[KEYED_ID]["b"].sum, 1);
});
add_task(function* test_environmentChange() {
let now = new Date(2040, 1, 1, 12, 0, 0);
let nowDay = new Date(2040, 1, 1, 0, 0, 0);
let timerCallback = null;
let timerDelay = null;
gRequestIterator = Iterator(new Request());
fakeNow(now);
fakeDailyTimers(() => {}, () => {});
const PREF_TEST = "toolkit.telemetry.test.pref1";
Preferences.reset(PREF_TEST);
let prefsToWatch = {};
prefsToWatch[PREF_TEST] = TelemetryEnvironment.RECORD_PREF_VALUE;
// Setup.
yield TelemetrySession.setup();
TelemetryPing.setServer("http://localhost:" + gHttpServer.identity.primaryPort);
TelemetryEnvironment._watchPreferences(prefsToWatch);
// Set histograms to expected state.
const COUNT_ID = "TELEMETRY_TEST_COUNT";
const KEYED_ID = "TELEMETRY_TEST_KEYED_COUNT";
const count = Telemetry.getHistogramById(COUNT_ID);
const keyed = Telemetry.getKeyedHistogramById(KEYED_ID);
count.clear();
keyed.clear();
count.add(1);
keyed.add("a", 1);
keyed.add("b", 1);
// Trigger and collect environment-change ping.
Preferences.set(PREF_TEST, 1);
let request = yield gRequestIterator.next();
Assert.ok(!!request);
let ping = decodeRequestPayload(request);
Assert.equal(ping.type, PING_TYPE_MAIN);
Assert.equal(ping.environment.settings.userPrefs[PREF_TEST], 1);
Assert.equal(ping.payload.info.reason, REASON_ENVIRONMENT_CHANGE);
let subsessionStartDate = new Date(ping.payload.info.subsessionStartDate);
Assert.equal(subsessionStartDate.toISOString(), nowDay.toISOString());
Assert.equal(ping.payload.histograms[COUNT_ID].sum, 1);
Assert.equal(ping.payload.keyedHistograms[KEYED_ID]["a"].sum, 1);
// Trigger and collect another ping. The histograms should be reset.
Preferences.set(PREF_TEST, 2);
request = yield gRequestIterator.next();
Assert.ok(!!request);
ping = decodeRequestPayload(request);
Assert.equal(ping.type, PING_TYPE_MAIN);
Assert.equal(ping.environment.settings.userPrefs[PREF_TEST], 2);
Assert.equal(ping.payload.info.reason, REASON_ENVIRONMENT_CHANGE);
subsessionStartDate = new Date(ping.payload.info.subsessionStartDate);
Assert.equal(subsessionStartDate.toISOString(), nowDay.toISOString());
Assert.equal(ping.payload.histograms[COUNT_ID].sum, 0);
Assert.deepEqual(ping.payload.keyedHistograms[KEYED_ID], {});
});
// Checks that an expired histogram file is deleted when loaded.
add_task(function* test_runOldPingFile() {
let histogramsFile = getSavedPingFile("old-histograms.dat");