Bug 810146: Add telemetry for addon manager startup times, unpacked add-ons and various changes detected at startup r=Mossop

--HG--
rename : browser/modules/TelemetryTimestamps.jsm => toolkit/modules/TelemetryTimestamps.jsm
rename : browser/modules/test/browser_TelemetryTimestamps.js => toolkit/modules/tests/browser_TelemetryTimestamps.js
This commit is contained in:
Irving Reid 2013-02-07 16:47:33 -05:00
parent f3f31cf0f1
commit 7b6e49cd35
11 changed files with 83 additions and 6 deletions

View File

@ -21,7 +21,6 @@ EXTRA_JS_MODULES = \
NewTabUtils.jsm \
offlineAppCache.jsm \
SignInToWebsite.jsm \
TelemetryTimestamps.jsm \
webappsUI.jsm \
webrtcUI.jsm \
KeywordURLResetPrompter.jsm \

View File

@ -20,7 +20,6 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_NetworkPrioritizer.js \
browser_TelemetryTimestamps.js \
# bug 793906 - temporarily disabling desktop UI while working on b2g
# browser_SignInToWebsite.js \
$(NULL)

View File

@ -121,6 +121,11 @@ function getSimpleMeasurements() {
Cu.import("resource:///modules/TelemetryTimestamps.jsm", o);
appTimestamps = o.TelemetryTimestamps.get();
} catch (ex) {}
try {
let o = {};
Cu.import("resource://gre/modules/AddonManager.jsm", o);
ret.addonManager = o.AddonManagerPrivate.getSimpleMeasures();
} catch (ex) {}
if (si.process) {
for each (let field in Object.keys(si)) {

View File

@ -777,7 +777,9 @@ function sortStartupMilestones(aSimpleMeasurements) {
["start", "main", "startupCrashDetectionBegin", "createTopLevelWindow",
"firstPaint", "delayedStartupStarted", "firstLoadURI",
"sessionRestoreInitialized", "sessionRestoreRestoring", "sessionRestored",
"delayedStartupFinished", "startupCrashDetectionEnd"];
"delayedStartupFinished", "startupCrashDetectionEnd",
"AMI_startup_begin", "AMI_startup_end", "XPI_startup_begin", "XPI_startup_end",
"XPI_bootstrap_addons_begin", "XPI_bootstrap_addons_end"];
let sortedKeys = Object.keys(aSimpleMeasurements);

View File

@ -13,6 +13,7 @@ TEST_DIRS += tests
EXTRA_JS_MODULES := \
Sqlite.jsm \
TelemetryTimestamps.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -14,3 +14,9 @@ XPCSHELL_TESTS = xpcshell
include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_TelemetryTimestamps.js \
$(NULL)
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

View File

@ -7,6 +7,7 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion";
const PREF_EM_UPDATE_ENABLED = "extensions.update.enabled";
@ -436,6 +437,10 @@ var AddonManagerInternal = {
}
}),
recordTimestamp: function AMI_recordTimestamp(name, value) {
this.TelemetryTimestamps.add(name, value);
},
/**
* Initializes the AddonManager, loading any known providers and initializing
* them.
@ -444,6 +449,8 @@ var AddonManagerInternal = {
if (gStarted)
return;
this.recordTimestamp("AMI_startup_begin");
Services.obs.addObserver(this, "xpcom-shutdown", false);
let appChanged = undefined;
@ -551,6 +558,7 @@ var AddonManagerInternal = {
}
gStartupComplete = true;
this.recordTimestamp("AMI_startup_end");
},
/**
@ -2079,7 +2087,20 @@ this.AddonManagerPrivate = {
AddonCompatibilityOverride: AddonCompatibilityOverride,
AddonType: AddonType
AddonType: AddonType,
recordTimestamp: function AMP_recordTimestamp(name, value) {
AddonManagerInternal.recordTimestamp(name, value);
},
_simpleMeasures: {},
recordSimpleMeasure: function AMP_recordSimpleMeasure(name, value) {
this._simpleMeasures[name] = value;
},
getSimpleMeasures: function AMP_getSimpleMeasures() {
return this._simpleMeasures;
}
};
/**
@ -2426,6 +2447,8 @@ this.AddonManager = {
}
};
// load the timestamps module into AddonManagerInternal
Cu.import("resource:///modules/TelemetryTimestamps.jsm", AddonManagerInternal);
Object.freeze(AddonManagerInternal);
Object.freeze(AddonManagerPrivate);
Object.freeze(AddonManager);

View File

@ -1503,6 +1503,8 @@ var XPIProvider = {
enabledAddons: null,
// An array of add-on IDs of add-ons that were inactive during startup
inactiveAddonIDs: [],
// Count of unpacked add-ons
unpackedAddons: 0,
/**
* Starts the XPI provider initializes the install locations and prefs.
@ -1526,6 +1528,8 @@ var XPIProvider = {
this.installLocations = [];
this.installLocationsByName = {};
AddonManagerPrivate.recordTimestamp("XPI_startup_begin");
function addDirectoryInstallLocation(aName, aKey, aPaths, aScope, aLocked) {
try {
var dir = FileUtils.getDir(aKey, aPaths);
@ -1663,6 +1667,7 @@ var XPIProvider = {
this.addAddonsToCrashReporter();
}
AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_begin");
for (let id in this.bootstrappedAddons) {
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.persistentDescriptor = this.bootstrappedAddons[id].descriptor;
@ -1670,6 +1675,7 @@ var XPIProvider = {
this.bootstrappedAddons[id].type, file,
"startup", BOOTSTRAP_REASONS.APP_STARTUP);
}
AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_end");
// Let these shutdown a little earlier when they still have access to most
// of XPCOM
@ -1688,6 +1694,8 @@ var XPIProvider = {
}
}, "quit-application-granted", false);
AddonManagerPrivate.recordTimestamp("XPI_startup_end");
this.extensionsActive = true;
},
@ -1828,7 +1836,15 @@ var XPIProvider = {
descriptor: file.persistentDescriptor,
mtime: recursiveLastModifiedTime(file)
};
});
try {
// get the install.rdf update time, if any
file.append(FILE_INSTALL_MANIFEST);
let rdfTime = file.lastModifiedTime;
addonStates[id].rdfTime = rdfTime;
this.unpackedAddons += 1;
}
catch (e) { }
}, this);
return addonStates;
},
@ -1844,6 +1860,7 @@ var XPIProvider = {
*/
getInstallLocationStates: function XPI_getInstallLocationStates() {
let states = [];
this.unpackedAddons = 0;
this.installLocations.forEach(function(aLocation) {
let addons = aLocation.addonLocations;
if (addons.length == 0)
@ -2808,6 +2825,11 @@ var XPIProvider = {
let changed = false;
let knownLocations = XPIDatabase.getInstallLocations();
// Gather stats for addon telemetry
let modifiedUnpacked = 0;
let modifiedExManifest = 0;
let modifiedXPI = 0;
// The install locations are iterated in reverse order of priority so when
// there are multiple add-ons installed with the same ID the one that
// should be visible is the first one encountered.
@ -2843,6 +2865,17 @@ var XPIProvider = {
if (aOldAddon.visible && !aOldAddon.active)
XPIProvider.inactiveAddonIDs.push(aOldAddon.id);
// Check if the add-on is unpacked, and has had other files changed
// on disk without the install.rdf manifest being changed
if ((addonState.rdfTime) && (aOldAddon.updateDate != addonState.mtime)) {
modifiedUnpacked += 1;
if (aOldAddon.updateDate >= addonState.rdfTime)
modifiedExManifest += 1;
}
else if (aOldAddon.updateDate != addonState.mtime) {
modifiedXPI += 1;
}
// The add-on has changed if the modification time has changed, or
// we have an updated manifest for it. Also reload the metadata for
// add-ons in the application directory when the application version
@ -2894,6 +2927,12 @@ var XPIProvider = {
}, this);
}, this);
// Tell Telemetry what we found
AddonManagerPrivate.recordSimpleMeasure("modifiedUnpacked", modifiedUnpacked);
if (modifiedUnpacked > 0)
AddonManagerPrivate.recordSimpleMeasure("modifiedExceptInstallRDF", modifiedExManifest);
AddonManagerPrivate.recordSimpleMeasure("modifiedXPI", modifiedXPI);
// Cache the new install location states
let cache = JSON.stringify(this.getInstallLocationStates());
Services.prefs.setCharPref(PREF_INSTALL_CACHE, cache);
@ -3049,6 +3088,7 @@ var XPIProvider = {
ERROR("Error processing file changes", e);
}
}
AddonManagerPrivate.recordSimpleMeasure("installedUnpacked", this.unpackedAddons);
if (aAppChanged) {
// When upgrading the app and using a custom skin make sure it is still

View File

@ -13,7 +13,9 @@ const IGNORE = ["escapeAddonURI", "shouldAutoUpdate", "getStartupChanges",
const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride",
"AddonScreenshot", "AddonType", "startup", "shutdown",
"registerProvider", "unregisterProvider",
"addStartupChange", "removeStartupChange"];
"addStartupChange", "removeStartupChange",
"recordTimestamp", "recordSimpleMeasure",
"getSimpleMeasures"];
function test_functions() {
for (let prop in AddonManager) {