author | Taras Glek <tglek@mozilla.com> |
Thu, 11 Aug 2011 14:19:40 -0700 | |
changeset 74263 | fdffde7c3b14935e8d7701f15738ebf45bd8d7e2 |
parent 74262 | 4b4b359e77e48709bdd71a03cc6318b7d4fc232d |
child 74264 | 792eb2aff31526cd7b168441130d36da03ee4cae |
push id | 1149 |
push user | tglek@mozilla.com |
push date | Thu, 11 Aug 2011 21:20:06 +0000 |
treeherder | mozilla-inbound@792eb2aff315 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Mossop |
bugs | 668392 |
milestone | 8.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
|
--- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -37,16 +37,17 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cr = Components.results; const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/LightweightThemeManager.jsm"); // When modifying the payload in incompatible ways, please bump this version number const PAYLOAD_VERSION = 1; const PREF_SERVER = "toolkit.telemetry.server"; const PREF_ENABLED = "toolkit.telemetry.enabled"; // Do not gather data more than once a minute const TELEMETRY_INTERVAL = 60; @@ -216,16 +217,64 @@ TelemetryPing.prototype = { if (!h) { h = Telemetry.getHistogramById(id); this._histograms[name] = h; } h.add(val); }, /** + * Descriptive metadata + * + * @param reason + * The reason for the telemetry ping, this will be included in the + * returned metadata, + * @return The metadata as a JS object + */ + getMetadata: function getMetadata(reason) { + let ai = Services.appinfo; + let ret = { + reason: reason, + OS: ai.OS, + appID: ai.ID, + appVersion: ai.version, + appName: ai.name, + appBuildID: ai.appBuildID, + platformBuildID: ai.platformBuildID, + }; + + // 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", "device", "manufacturer", "hardware"]; + for each (let field in fields) { + let value; + try { + value = sysInfo.getProperty(field); + } catch (e) { + continue + } + if (field == "memsize") { + // Send RAM size in megabytes. Rounding because sysinfo doesn't + // always provide RAM in multiples of 1024. + value = Math.round(value / 1024 / 1024) + } + ret[field] = value + } + + let theme = LightweightThemeManager.currentTheme; + if (theme) + ret.persona = theme.id; + + if (this._addons) + ret.addons = this._addons; + + return ret; + }, + + /** * Pull values from about:memory into corresponding histograms */ gatherMemory: function gatherMemory() { let mgr; try { mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. getService(Ci.nsIMemoryReporterManager); } catch (e) { @@ -281,20 +330,21 @@ TelemetryPing.prototype = { /** * Send data to the server. Record success/send-time in histograms */ send: function send(reason, server) { // populate histograms one last time this.gatherMemory(); let payload = { ver: PAYLOAD_VERSION, - info: getMetadata(reason), + info: this.getMetadata(reason), simpleMeasurements: getSimpleMeasurements(), histograms: getHistograms() }; + let isTestPing = (reason == "test-ping"); // Generate a unique id once per session so the server can cope with duplicate submissions. // Use a deterministic url for testing. if (!this._path) this._path = "/submit/telemetry/" + (isTestPing ? reason : generateUUID()); let hping = Telemetry.getHistogramById("TELEMETRY_PING"); let hsuccess = Telemetry.getHistogramById("TELEMETRY_SUCCESS"); @@ -390,16 +440,19 @@ TelemetryPing.prototype = { /** * This observer drives telemetry. */ observe: function (aSubject, aTopic, aData) { // Allows to change the server for testing var server = this._server; switch (aTopic) { + case "Add-ons": + this._addons = aData; + break; case "profile-after-change": this.setup(); break; case "profile-before-change": this.uninstall(); break; case "idle": this.gatherMemory();
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryPing.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetryPing.js @@ -5,27 +5,29 @@ * * Telemetry code keeps histograms of past telemetry pings. The first * ping populates these histograms. One of those histograms is then * checked in the second request. */ do_load_httpd_js(); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/LightweightThemeManager.jsm"); const PATH = "/submit/telemetry/test-ping"; const SERVER = "http://localhost:4444"; const IGNORE_HISTOGRAM = "test::ignore_me"; const BinaryInputStream = Components.Constructor( "@mozilla.org/binaryinputstream;1", "nsIBinaryInputStream", "setInputStream"); var httpserver = new nsHttpServer(); +var gFinished = false; function telemetry_ping () { const TelemetryPing = Cc["@mozilla.org/base/telemetry-ping;1"].getService(Ci.nsIObserver); TelemetryPing.observe(null, "test-ping", SERVER); } function nonexistentServerObserver(aSubject, aTopic, aData) { Services.obs.removeObserver(nonexistentServerObserver, aTopic); @@ -41,37 +43,22 @@ function nonexistentServerObserver(aSubj function telemetryObserver(aSubject, aTopic, aData) { Services.obs.removeObserver(telemetryObserver, aTopic); httpserver.registerPathHandler(PATH, checkHistograms); const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); Telemetry.newHistogram(IGNORE_HISTOGRAM, 1, 2, 3, Telemetry.HISTOGRAM_BOOLEAN); telemetry_ping(); } -function run_test() { - createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - Services.obs.addObserver(nonexistentServerObserver, "telemetry-test-xhr-complete", false); - telemetry_ping(); - // spin the event loop - do_test_pending(); -} - -function readBytesFromInputStream(inputStream, count) { - if (!count) { - count = inputStream.available(); - } - return new BinaryInputStream(inputStream).readBytes(count); -} - function checkHistograms(request, response) { // do not need the http server anymore httpserver.stop(do_test_finished); let s = request.bodyInputStream let payload = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON) - .decode(readBytesFromInputStream(s)) + .decodeFromStream(s, s.available()) do_check_eq(request.getHeader("content-type"), "application/json; charset=UTF-8"); do_check_true(payload.simpleMeasurements.uptime >= 0) // get rid of the non-deterministic field const expected_info = { reason: "test-ping", OS: "XPCShell", @@ -97,16 +84,17 @@ function checkHistograms(request, respon bucket_count: 3, histogram_type: 2, values: {0:1, 1:1, 2:0}, sum: 1 } let tc = payload.histograms[TELEMETRY_SUCCESS] do_check_eq(uneval(tc), uneval(expected_tc)); + gFinished = true; } // copied from toolkit/mozapps/extensions/test/xpcshell/head_addons.js const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1"; const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"); function createAppInfo(id, name, version, platformVersion) { gAppInfo = { @@ -147,8 +135,39 @@ function createAppInfo(id, name, version throw Components.results.NS_ERROR_NO_AGGREGATION; return gAppInfo.QueryInterface(iid); } }; var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo", XULAPPINFO_CONTRACTID, XULAppInfoFactory); } + +function dummyTheme(id) { + return { + id: id, + name: Math.random().toString(), + headerURL: "http://lwttest.invalid/a.png", + footerURL: "http://lwttest.invalid/b.png", + textcolor: Math.random().toString(), + accentcolor: Math.random().toString() + }; +} + +function run_test() { + // Addon manager needs a profile directory + do_get_profile(); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + // try to make LightweightThemeManager do stuff + let gInternalManager = Cc["@mozilla.org/addons/integration;1"] + .getService(Ci.nsIObserver) + .QueryInterface(Ci.nsITimerCallback); + + gInternalManager.observe(null, "addons-startup", null); + LightweightThemeManager.currentTheme = dummyTheme("1234"); + + Services.obs.addObserver(nonexistentServerObserver, "telemetry-test-xhr-complete", false); + telemetry_ping(); + // spin the event loop + do_test_pending(); + // ensure that test runs to completion + do_register_cleanup(function () do_check_true(gFinished)) + }
--- a/toolkit/mozapps/extensions/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/XPIProvider.jsm @@ -1733,16 +1733,19 @@ var XPIProvider = { let data = this.enabledAddons; for (let id in this.bootstrappedAddons) data += (data ? "," : "") + id + ":" + this.bootstrappedAddons[id].version; try { Services.appinfo.annotateCrashReport("Add-ons", data); } catch (e) { } + + const TelemetryPing = Cc["@mozilla.org/base/telemetry-ping;1"].getService(Ci.nsIObserver); + TelemetryPing.observe(null, "Add-ons", data); }, /** * Gets the add-on states for an install location. * This function may be expensive because of the recursiveLastModifiedTime call. * * @param location * The install location to retrieve the add-on states for