mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 893098, record update starts, stops and errors in the health report, r=rnewman,rstrong
This commit is contained in:
parent
2e61ca824a
commit
58cddbe4a5
69
toolkit/mozapps/update/UpdaterHealthProvider.jsm
Normal file
69
toolkit/mozapps/update/UpdaterHealthProvider.jsm
Normal file
@ -0,0 +1,69 @@
|
||||
/* 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 = [
|
||||
"UpdateProvider",
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Metrics.jsm", this);
|
||||
Cu.import("resource://gre/modules/Task.jsm", this);
|
||||
|
||||
const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER};
|
||||
const DAILY_DISCRETE_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_DISCRETE_NUMERIC};
|
||||
|
||||
function UpdateMeasurement1() {
|
||||
Metrics.Measurement.call(this);
|
||||
}
|
||||
|
||||
UpdateMeasurement1.prototype = Object.freeze({
|
||||
__proto__: Metrics.Measurement.prototype,
|
||||
|
||||
name: "update",
|
||||
version: 1,
|
||||
|
||||
fields: {
|
||||
updateCheckStartCount: DAILY_COUNTER_FIELD,
|
||||
updateCheckSuccessCount: DAILY_COUNTER_FIELD,
|
||||
updateCheckFailedCount: DAILY_COUNTER_FIELD,
|
||||
updateCheckFailedStatuses: DAILY_DISCRETE_NUMERIC_FIELD,
|
||||
completeUpdateStartCount: DAILY_COUNTER_FIELD,
|
||||
partialUpdateStartCount: DAILY_COUNTER_FIELD,
|
||||
completeUpdateSuccessCount: DAILY_COUNTER_FIELD,
|
||||
partialUpdateSuccessCount: DAILY_COUNTER_FIELD,
|
||||
updateFailedCount: DAILY_COUNTER_FIELD,
|
||||
updateFailedStatuses: DAILY_DISCRETE_NUMERIC_FIELD,
|
||||
},
|
||||
});
|
||||
|
||||
this.UpdateProvider = function () {
|
||||
Metrics.Provider.call(this);
|
||||
};
|
||||
UpdateProvider.prototype = Object.freeze({
|
||||
__proto__: Metrics.Provider.prototype,
|
||||
|
||||
name: "org.mozilla.update",
|
||||
|
||||
measurementTypes: [
|
||||
UpdateMeasurement1,
|
||||
],
|
||||
|
||||
recordUpdate: function (field, status) {
|
||||
let m = this.getMeasurement(UpdateMeasurement1.prototype.name,
|
||||
UpdateMeasurement1.prototype.version);
|
||||
|
||||
return this.enqueueStorageOperation(function recordUpdateFields() {
|
||||
return Task.spawn(function recordUpdateFieldsTask() {
|
||||
yield m.incrementDailyCounter(field + "Count");
|
||||
|
||||
if ((field == "updateFailed" || field == "updateCheckFailed") && status) {
|
||||
yield m.addDailyDiscreteNumeric(field + "Statuses", status);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
});
|
@ -46,4 +46,8 @@ if CONFIG['MOZ_UPDATER']:
|
||||
'nsUpdateServiceStub.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'UpdaterHealthProvider.jsm'
|
||||
]
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
@ -12,6 +12,7 @@ Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
Components.utils.import("resource://gre/modules/UpdaterHealthProvider.jsm");
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
@ -258,6 +259,18 @@ const PING_BGUC_ADDON_UPDATES_FOR_INCOMPAT = 29;
|
||||
// Incompatible add-ons found (update notification)
|
||||
const PING_BGUC_ADDON_HAVE_INCOMPAT = 30;
|
||||
|
||||
// Health report field names
|
||||
const UpdaterHealthReportFields = {
|
||||
CHECK_START: "updateCheckStart",
|
||||
CHECK_SUCCESS: "updateCheckSuccess",
|
||||
CHECK_FAILED: "updateCheckFailed",
|
||||
COMPLETE_START: "completeUpdateStart",
|
||||
PARTIAL_START: "partialUpdateStart",
|
||||
COMPLETE_SUCCESS: "completeUpdateSuccess",
|
||||
PARTIAL_SUCCESS: "partialUpdateSuccess",
|
||||
FAILED: "updateFailed"
|
||||
};
|
||||
|
||||
var gLocale = null;
|
||||
var gUpdateMutexHandle = null;
|
||||
|
||||
@ -935,6 +948,37 @@ function getStatusTextFromCode(code, defaultCode) {
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record count in the health report.
|
||||
* @param field
|
||||
* The field name to record
|
||||
* @param status
|
||||
* Status code for errors, 0 otherwise
|
||||
*/
|
||||
function recordInHealthReport(field, status) {
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
try {
|
||||
LOG("recordInHealthReport - " + field + " - " + status);
|
||||
|
||||
let reporter = Cc["@mozilla.org/datareporting/service;1"]
|
||||
.getService().wrappedJSObject.healthReporter;
|
||||
|
||||
if (reporter) {
|
||||
reporter.onInit().then(function recordUpdateInHealthReport() {
|
||||
try {
|
||||
reporter.getProvider("org.mozilla.update").recordUpdate(field, status);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
// If getting the heath reporter service fails, don't fail updating.
|
||||
} catch (ex) {
|
||||
LOG("recordInHealthReport - could not initialize health reporter");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Active Updates directory
|
||||
* @return The active updates directory, as a nsIFile object
|
||||
@ -3600,6 +3644,8 @@ Checker.prototype = {
|
||||
if (!url || (!this.enabled && !force))
|
||||
return;
|
||||
|
||||
recordInHealthReport(UpdaterHealthReportFields.CHECK_START, 0);
|
||||
|
||||
this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsISupports);
|
||||
// This is here to let unit test code override XHR
|
||||
@ -3723,6 +3769,8 @@ Checker.prototype = {
|
||||
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS))
|
||||
Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDERRORS);
|
||||
|
||||
recordInHealthReport(UpdaterHealthReportFields.CHECK_SUCCESS, 0);
|
||||
|
||||
// Tell the callback about the updates
|
||||
this._callback.onCheckComplete(event.target, updates, updates.length);
|
||||
}
|
||||
@ -3743,6 +3791,9 @@ Checker.prototype = {
|
||||
update.errorCode = updates[0] ? CERT_ATTR_CHECK_FAILED_HAS_UPDATE
|
||||
: CERT_ATTR_CHECK_FAILED_NO_UPDATE;
|
||||
}
|
||||
|
||||
recordInHealthReport(UpdaterHealthReportFields.CHECK_FAILED, update.errorCode);
|
||||
|
||||
this._callback.onError(request, update);
|
||||
}
|
||||
|
||||
@ -3774,6 +3825,8 @@ Checker.prototype = {
|
||||
update.errorCode = HTTP_ERROR_OFFSET + status;
|
||||
}
|
||||
|
||||
recordInHealthReport(UpdaterHealthReportFields.CHECK_FAILED, update.errorCode);
|
||||
|
||||
this._callback.onError(request, update);
|
||||
|
||||
this._request = null;
|
||||
@ -4088,6 +4141,10 @@ Downloader.prototype = {
|
||||
}
|
||||
this.isCompleteUpdate = this._patch.type == "complete";
|
||||
|
||||
recordInHealthReport(
|
||||
this.isCompleteUpdate ? UpdaterHealthReportFields.COMPLETE_START :
|
||||
UpdaterHealthReportFields.PARTIAL_START, 0);
|
||||
|
||||
var patchFile = null;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -4343,6 +4400,10 @@ Downloader.prototype = {
|
||||
"current fail: " + this.updateService._consecutiveSocketErrors + ", " +
|
||||
"max fail: " + maxFail + ", " + "retryTimeout: " + retryTimeout);
|
||||
if (Components.isSuccessCode(status)) {
|
||||
recordInHealthReport(
|
||||
this.isCompleteUpdate ? UpdaterHealthReportFields.COMPLETE_SUCCESS :
|
||||
UpdaterHealthReportFields.PARTIAL_SUCCESS, 0);
|
||||
|
||||
if (this._verifyDownload()) {
|
||||
state = shouldUseService() ? STATE_PENDING_SVC : STATE_PENDING;
|
||||
if (this.background) {
|
||||
@ -4371,7 +4432,10 @@ Downloader.prototype = {
|
||||
// Destroy the updates directory, since we're done with it.
|
||||
cleanUpUpdatesDir();
|
||||
}
|
||||
} else if (status == Cr.NS_ERROR_OFFLINE) {
|
||||
} else {
|
||||
recordInHealthReport(UpdaterHealthReportFields.FAILED, status);
|
||||
|
||||
if (status == Cr.NS_ERROR_OFFLINE) {
|
||||
// Register an online observer to try again.
|
||||
// The online observer will continue the incremental download by
|
||||
// calling downloadUpdate on the active update which continues
|
||||
@ -4415,6 +4479,7 @@ Downloader.prototype = {
|
||||
|
||||
deleteActiveUpdate = true;
|
||||
}
|
||||
}
|
||||
LOG("Downloader:onStopRequest - setting state to: " + state);
|
||||
this._patch.state = state;
|
||||
var um = Cc["@mozilla.org/updates/update-manager;1"].
|
||||
|
@ -10,3 +10,6 @@ contract @mozilla.org/updates/update-prompt;1 {27ABA825-35B5-4018-9FDD-F99250A0E
|
||||
component {e43b0010-04ba-4da6-b523-1f92580bc150} nsUpdateServiceStub.js
|
||||
contract @mozilla.org/updates/update-service-stub;1 {e43b0010-04ba-4da6-b523-1f92580bc150}
|
||||
category profile-after-change nsUpdateServiceStub @mozilla.org/updates/update-service-stub;1
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
category healthreport-js-provider-default UpdateProvider resource://gre/modules/UpdaterHealthProvider.jsm
|
||||
#endif
|
||||
|
@ -0,0 +1,91 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {utils: Cu, classes: Cc, interfaces: Ci} = Components;
|
||||
|
||||
|
||||
Cu.import("resource://gre/modules/Metrics.jsm");
|
||||
Cu.import("resource://gre/modules/UpdaterHealthProvider.jsm");
|
||||
|
||||
// Create a profile
|
||||
let gProfile = do_get_profile();
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_constructor() {
|
||||
let provider = new UpdateProvider();
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_task(function test_init() {
|
||||
let storage = yield Metrics.Storage("init");
|
||||
let provider = new UpdateProvider();
|
||||
yield provider.init(storage);
|
||||
yield provider.shutdown();
|
||||
|
||||
yield storage.close();
|
||||
});
|
||||
|
||||
add_task(function test_collect() {
|
||||
let storage = yield Metrics.Storage("collect");
|
||||
let provider = new UpdateProvider();
|
||||
yield provider.init(storage);
|
||||
|
||||
let now = new Date();
|
||||
|
||||
let m = provider.getMeasurement("update", 1);
|
||||
|
||||
let fieldcount = 0;
|
||||
for (let field of ["updateCheckStart",
|
||||
"updateCheckSuccess",
|
||||
"completeUpdateStart",
|
||||
"partialUpdateStart",
|
||||
"completeUpdateSuccess",
|
||||
"partialUpdateSuccess"]) {
|
||||
fieldcount++; // One new day per iteration
|
||||
|
||||
yield provider.recordUpdate(field, 0);
|
||||
|
||||
let data = yield m.getValues();
|
||||
do_check_eq(data.days.size, 1);
|
||||
|
||||
let day = data.days.getDay(now);
|
||||
do_check_eq(day.size, fieldcount);
|
||||
do_check_eq(day.get(field + "Count"), 1);
|
||||
|
||||
yield provider.recordUpdate(field, 0);
|
||||
|
||||
data = yield m.getValues();
|
||||
day = data.days.getDay(now);
|
||||
do_check_eq(day.size, fieldcount);
|
||||
do_check_eq(day.get(field + "Count"), 2);
|
||||
}
|
||||
|
||||
for (let field of ["updateCheckFailed", "updateFailed"]) {
|
||||
fieldcount += 2; // Two fields added per iteration
|
||||
|
||||
yield provider.recordUpdate(field, 500);
|
||||
|
||||
let data = yield m.getValues();
|
||||
let day = data.days.getDay(now);
|
||||
do_check_eq(day.size, fieldcount);
|
||||
|
||||
do_check_eq(day.get(field + "Statuses"), 500);
|
||||
|
||||
yield provider.recordUpdate(field, 800);
|
||||
|
||||
data = yield m.getValues();
|
||||
day = data.days.getDay(now);
|
||||
do_check_eq(day.size, fieldcount);
|
||||
do_check_eq(day.get(field + "Statuses")[0], 500);
|
||||
do_check_eq(day.get(field + "Statuses")[1], 800);
|
||||
}
|
||||
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
});
|
||||
|
@ -39,3 +39,5 @@ skip-if = toolkit == 'gonk'
|
||||
reason = custom nsIUpdatePrompt
|
||||
[updateRootDirMigration_win.js]
|
||||
run-if = os == 'win'
|
||||
[updateHealthReport.js]
|
||||
skip-if = ! healthreport
|
||||
|
Loading…
Reference in New Issue
Block a user