Bug 1621402 - Add telemetry to capture failures to read attribution data r=janerik,mixedpuppy

Differential Revision: https://phabricator.services.mozilla.com/D67163

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrei Oprea 2020-03-24 18:32:57 +00:00
Родитель fdec3e7197
Коммит afdcacc413
5 изменённых файлов: 145 добавлений и 8 удалений

Просмотреть файл

@ -80,7 +80,16 @@ var AttributionCode = {
break;
}
}
return isValid ? parsed : {};
if (isValid) {
return parsed;
}
Services.telemetry
.getHistogramById("BROWSER_ATTRIBUTION_ERRORS")
.add("decode_error");
return {};
},
/**
@ -100,15 +109,28 @@ var AttributionCode = {
gCachedAttrData = {};
if (AppConstants.platform == "win") {
let bytes;
try {
let bytes = await OS.File.read(getAttributionFile().path);
let decoder = new TextDecoder();
let code = decoder.decode(bytes);
gCachedAttrData = this.parseAttributionCode(code);
bytes = await OS.File.read(getAttributionFile().path);
} catch (ex) {
// The attribution file may already have been deleted,
// or it may have never been installed at all;
// failure to open or read it isn't an error.
if (ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
return gCachedAttrData;
}
Services.telemetry
.getHistogramById("BROWSER_ATTRIBUTION_ERRORS")
.add("read_error");
}
if (bytes) {
try {
let decoder = new TextDecoder();
let code = decoder.decode(bytes);
gCachedAttrData = this.parseAttributionCode(code);
} catch (ex) {
// TextDecoder can throw an error
Services.telemetry
.getHistogramById("BROWSER_ATTRIBUTION_ERRORS")
.add("decode_error");
}
}
} else if (AppConstants.platform == "macosx") {
try {

Просмотреть файл

@ -9,6 +9,8 @@ with Files("**"):
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
EXTRA_JS_MODULES += [
'AttributionCode.jsm',
]

Просмотреть файл

@ -0,0 +1,4 @@
[DEFAULT]
[browser_AttributionCode_telemetry.js]
skip-if = os != "win" # Windows only telemetry

Просмотреть файл

@ -0,0 +1,97 @@
ChromeUtils.defineModuleGetter(
this,
"TelemetryTestUtils",
"resource://testing-common/TelemetryTestUtils.jsm"
);
const { AttributionCode } = ChromeUtils.import(
"resource:///modules/AttributionCode.jsm"
);
ChromeUtils.defineModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
async function writeAttributionFile(data) {
let appDir = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
let file = appDir.clone();
file.append(Services.appinfo.vendor || "mozilla");
file.append(AppConstants.MOZ_APP_NAME);
await OS.File.makeDir(file.path, { from: appDir.path, ignoreExisting: true });
file.append("postSigningData");
await OS.File.writeAtomic(file.path, data);
}
add_task(function setup() {
// Clear cache call is only possible in a testing environment
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
env.set("XPCSHELL_TEST_PROFILE_DIR", "testing");
registerCleanupFunction(() => {
env.set("XPCSHELL_TEST_PROFILE_DIR", null);
});
});
add_task(async function test_parse_error() {
registerCleanupFunction(async () => {
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
});
const histogram = Services.telemetry.getHistogramById(
"BROWSER_ATTRIBUTION_ERRORS"
);
// Delete the file to trigger a read error
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
// Clear any existing telemetry
histogram.clear();
let result = await AttributionCode.getAttrDataAsync();
Assert.deepEqual(
result,
{},
"Shouldn't be able to get a result if the file doesn't exist"
);
// Write an invalid file to trigger a decode error
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
await writeAttributionFile(""); // empty string is invalid
result = await AttributionCode.getAttrDataAsync();
Assert.deepEqual(result, {}, "Should have failed to parse");
// `assertHistogram` also ensures that `read_error` index 0 is 0
// as we should not have recorded telemetry from the previous `getAttrDataAsync` call
TelemetryTestUtils.assertHistogram(histogram, 1, 1);
// Reset
histogram.clear();
});
add_task(async function test_read_error() {
registerCleanupFunction(async () => {
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
});
const histogram = Services.telemetry.getHistogramById(
"BROWSER_ATTRIBUTION_ERRORS"
);
const sandbox = sinon.createSandbox();
// Delete the file to trigger a read error
await AttributionCode.deleteFileAsync();
AttributionCode._clearCache();
// Clear any existing telemetry
histogram.clear();
// Force a read error
const stub = sandbox.stub(OS.File, "read");
stub.throws(() => new Error("read_error"));
// Try to read the file
await AttributionCode.getAttrDataAsync();
// It should record the read error
TelemetryTestUtils.assertHistogram(histogram, 0, 1);
// Clear any existing telemetry
histogram.clear();
sandbox.restore();
});

Просмотреть файл

@ -10728,6 +10728,18 @@
"kind": "boolean",
"description": "The result of the default browser check for assist intent."
},
"BROWSER_ATTRIBUTION_ERRORS": {
"record_in_processes": ["main", "content"],
"products": ["firefox"],
"expires_in_version": "80",
"kind": "categorical",
"labels": ["read_error", "decode_error"],
"description": "Count for the number of errors encountered trying to read the attribution data from the stub installer.",
"releaseChannelCollection": "opt-out",
"bug_numbers": [1621402],
"alert_emails": ["aoprea@mozilla.com"],
"operating_systems": ["windows"]
},
"MIXED_CONTENT_PAGE_LOAD": {
"record_in_processes": ["main", "content"],
"products": ["firefox", "fennec", "geckoview"],