Bug 1122047 - Part 1 - Sketch out Telemetry environment module. r=vladan

This commit is contained in:
Georg Fritzsche 2015-01-25 23:17:37 +01:00
parent d2b38031e3
commit 2cce430264
6 changed files with 211 additions and 1 deletions

View File

@ -0,0 +1,127 @@
/* 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";
this.EXPORTED_SYMBOLS = [
"TelemetryEnvironment",
];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Log.jsm");
const LOGGER_NAME = "Toolkit.Telemetry";
this.TelemetryEnvironment = {
_shutdown: true,
// A map of (sync) listeners that will be called on environment changes.
_changeListeners: new Map(),
// Async task for collecting the environment data.
_collectTask: null,
_doNotify: false,
/**
* Initialize TelemetryEnvironment.
*/
init: function () {
if (!this._shutdown) {
this._log.error("init - Already initialized");
return;
}
this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, "TelemetryEnvironment::");
this._log.trace("init");
this._shutdown = false;
},
/**
* Shutdown TelemetryEnvironment.
* @return Promise<> that is resolved when shutdown is finished.
*/
shutdown: Task.async(function* () {
if (this._shutdown) {
this._log.error("shutdown - Already shut down");
throw new Error("Already shut down");
}
this._log.trace("shutdown");
this._shutdown = true;
this._changeListeners.clear();
yield this._collectTask;
}),
/**
* Register a listener for environment changes.
* @param name The name of the listener - good for debugging purposes.
* @param listener A JS callback function.
*/
registerChangeListener: function (name, listener) {
this._log.trace("registerChangeListener for " + name);
if (this._shutdown) {
this._log.warn("registerChangeListener - already shutdown")
return;
}
this._changeListeners.set(name, listener);
},
/**
* Unregister from listening to environment changes.
* @param name The name of the listener to remove.
*/
unregisterChangeListener: function (name) {
this._log.trace("unregisterChangeListener for " + name);
if (this._shutdown) {
this._log.warn("registerChangeListener - already shutdown")
return;
}
this._changeListeners.delete(name);
},
/**
* Get the environment data in object form.
* @return Promise<Object> Resolved with the data on success, otherwise rejected.
*/
getEnvironmentData: function() {
if (this._shutdown) {
this._log.error("getEnvironmentData - Already shut down");
return Promise.reject("Already shutdown");
}
this._log.trace("getEnvironmentData");
if (this._collectTask) {
return this._collectTask;
}
this._collectTask = this._doGetEnvironmentData();
let clear = () => this._collectTask = null;
this._collectTask.then(clear, clear);
return this._collectTask;
},
_doGetEnvironmentData: Task.async(function* () {
this._log.trace("getEnvironmentData");
return {};
}),
_onEnvironmentChange: function (what) {
this._log.trace("_onEnvironmentChange for " + what);
if (this._shutdown) {
this._log.trace("_onEnvironmentChange - Already shut down.");
return;
}
for (let [name, listener] of this._changeListeners) {
try {
this._log.debug("_onEnvironmentChange - calling " + name);
listener();
} catch (e) {
this._log.warning("_onEnvironmentChange - listener " + name + " caught error", e);
}
}
},
};

View File

@ -46,6 +46,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "TelemetryLog",
"resource://gre/modules/TelemetryLog.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ThirdPartyCookieProbe",
"resource://gre/modules/ThirdPartyCookieProbe.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment",
"resource://gre/modules/TelemetryEnvironment.jsm");
/**
* Setup Telemetry logging. This function also gets called when loggin related
@ -346,6 +348,8 @@ let Impl = {
let delayedTask = new DeferredTask(function* () {
this._initialized = true;
yield TelemetryEnvironment.init();
yield TelemetryFile.loadSavedPings();
// If we have any TelemetryPings lying around, we'll be aggressive
// and try to send them all off ASAP.
@ -375,10 +379,17 @@ let Impl = {
}.bind(this), testing ? TELEMETRY_TEST_DELAY : TELEMETRY_DELAY);
AsyncShutdown.sendTelemetry.addBlocker("TelemetryPing: shutting down",
() => this.shutdown());
delayedTask.arm();
return deferred.promise;
},
shutdown: function() {
return TelemetryEnvironment.shutdown();
},
/**
* This observer drives telemetry.
*/

View File

@ -965,7 +965,7 @@ let Impl = {
}
AsyncShutdown.sendTelemetry.addBlocker(
"Telemetry: shutting down",
"TelemetrySession: shutting down",
function condition(){
this.uninstall();
if (Telemetry.canSend) {

View File

@ -28,6 +28,7 @@ EXTRA_COMPONENTS += [
]
EXTRA_JS_MODULES += [
'TelemetryEnvironment.jsm',
'TelemetryFile.jsm',
'TelemetryLog.jsm',
'TelemetryStopwatch.jsm',

View File

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
function run_test() {
do_test_pending();
do_get_profile();
run_next_test();
}
function isRejected(promise) {
return new Promise((resolve, reject) => {
promise.then(() => resolve(false), () => resolve(true));
});
}
add_task(function* test_initAndShutdown() {
// Check that init and shutdown work properly.
TelemetryEnvironment.init();
yield TelemetryEnvironment.shutdown();
TelemetryEnvironment.init();
yield TelemetryEnvironment.shutdown();
// A double init should be silently handled.
TelemetryEnvironment.init();
TelemetryEnvironment.init();
// getEnvironmentData should return a sane result.
let data = yield TelemetryEnvironment.getEnvironmentData();
Assert.ok(!!data);
// The change listener registration should silently fail after shutdown.
yield TelemetryEnvironment.shutdown();
TelemetryEnvironment.registerChangeListener("foo", () => {});
TelemetryEnvironment.unregisterChangeListener("foo");
// Other calls after shutdown should reject.
Assert.ok(yield isRejected(TelemetryEnvironment.shutdown()));
Assert.ok(yield isRejected(TelemetryEnvironment.getEnvironmentData()));
});
add_task(function* test_changeNotify() {
TelemetryEnvironment.init();
// Register some listeners
let results = new Array(4).fill(false);
for (let i=0; i<results.length; ++i) {
let k = i;
TelemetryEnvironment.registerChangeListener("test"+k, () => results[k] = true);
}
// Trigger environment change notifications.
// TODO: test with proper environment changes, not directly.
TelemetryEnvironment._onEnvironmentChange("foo");
Assert.ok(results.every(val => val), "All change listeners should have been notified.");
results.fill(false);
TelemetryEnvironment._onEnvironmentChange("bar");
Assert.ok(results.every(val => val), "All change listeners should have been notified.");
// Unregister listeners
for (let i=0; i<4; ++i) {
TelemetryEnvironment.unregisterChangeListener("test"+i);
}
});
add_task(function*() {
do_test_finished();
});

View File

@ -4,6 +4,7 @@ tail =
skip-if = toolkit == 'gonk'
[test_nsITelemetry.js]
[test_TelemetryEnvironment.js]
[test_TelemetryFlagClear.js]
[test_TelemetryLateWrites.js]
[test_TelemetryLockCount.js]