Bug 1955429 - Instrument attribution and distribution information in Glean r=TravisLong

Differential Revision: https://phabricator.services.mozilla.com/D244987
This commit is contained in:
Chris H-C
2025-04-21 14:12:43 +00:00
parent 1f16f366bb
commit 42e484060f
5 changed files with 162 additions and 1 deletions

View File

@@ -0,0 +1,102 @@
# 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/.
# Adding a new metric? We have docs for that!
# https://firefox-source-docs.mozilla.org/toolkit/components/glean/user/new_definitions_file.html
---
$schema: moz://mozilla.org/schemas/glean/metrics/2-0-0
$tags:
- 'Toolkit :: Telemetry'
glean.attribution:
ext:
type: object
lifetime: user
# Permit long description lines
# yamllint disable
description: |
Extended attribution information.
Mapped to client_info.attribution.ext in datasets.
* `experiment`: name/id of the enrolled funnel experiment
* `variation`: name/id of the variation cohort used in the enrolled funnel experiment
* `ua`: identifier derived from the user agent downloading the installer
e.g. chrome, Google Chrome 123
* `dltoken`: Unique token created at Firefox download time.
e.g. c18f86a3-f228-4d98-91bb-f90135c0aa9c
* `msstoresignedin`: only present if the installation was done through the Microsoft Store,
and was able to retrieve the "campaign ID" it was first installed with.
This value is "true" if the user was signed into the Microsoft Store
when they first installed, and false otherwise.
* `dlsource`: identifier that indicate where installations of Firefox originate
# yamllint enable
bugs:
- https://bugzilla.mozilla.org/1955429
data_reviews:
- https://bugzilla.mozilla.org/1955429
notification_emails:
- chutten@mozilla.com
send_in_pings:
- metrics
- baseline
- events
expires: never
no_lint:
- BASELINE_PING
structure:
type: object
properties:
experiment:
type: string
variation:
type: string
ua:
type: string
dltoken:
type: string
msstoresignedin:
type: boolean
dlsource:
type: string
glean.distribution:
ext:
type: object
lifetime: user
description: |
Extended distribution information.
Mapped to client_info.distribution.ext in datasets.
* `distributionVersion`: pref `distribution.version`, `null` on failure
* `partnerId`: pref `mozilla.partner.id`, `null` on failure
* `distributor`: pref `app.distributor`, `null` on failure
* `distributorChannel`: pref `app.distributor.channel`, `null` on failure
* `partnerNames`: list from prefs `app.partner.<name>=<name>`
bugs:
- https://bugzilla.mozilla.org/1955429
data_reviews:
- https://bugzilla.mozilla.org/1955429
notification_emails:
- chutten@mozilla.com
send_in_pings:
- metrics
- baseline
- events
expires: never
no_lint:
- BASELINE_PING
structure:
type: object
properties:
distributionVersion:
type: string
partnerId:
type: string
distributor:
type: string
distributorChannel:
type: string
partnerNames:
type: array
items:
type: string

View File

@@ -112,6 +112,7 @@ gecko_metrics = [
firefox_desktop_metrics = [ firefox_desktop_metrics = [
"browser/actors/metrics.yaml", "browser/actors/metrics.yaml",
"browser/components/asrouter/metrics.yaml", "browser/components/asrouter/metrics.yaml",
"browser/components/attribution/metrics.yaml",
"browser/components/backup/metrics.yaml", "browser/components/backup/metrics.yaml",
"browser/components/doh/metrics.yaml", "browser/components/doh/metrics.yaml",
"browser/components/downloads/metrics.yaml", "browser/components/downloads/metrics.yaml",

View File

@@ -3,6 +3,7 @@ firefox-appdir = "browser"
head = "head.js" head = "head.js"
["test_AttributionDistribution.js"] ["test_AttributionDistribution.js"]
skip-if = ["os == 'android'"] # FOG isn't responsible for attribution/distribution on Android.
["test_FOGIPCLimit.js"] ["test_FOGIPCLimit.js"]

View File

@@ -83,7 +83,7 @@ var gActiveExperimentStartupBuffer = new Map();
// For Powering arewegleanyet.com (See bug 1944592) // For Powering arewegleanyet.com (See bug 1944592)
// Legacy Count: 114 // Legacy Count: 114
// Glean Count: 32 // Glean Count: 48
var gGlobalEnvironment; var gGlobalEnvironment;
function getGlobal() { function getGlobal() {
@@ -1789,6 +1789,22 @@ EnvironmentCache.prototype = {
: data[key]; : data[key];
} }
this._currentEnvironment.settings.attribution = attributionData; this._currentEnvironment.settings.attribution = attributionData;
let extAttribution = {
experiment: attributionData.experiment,
variation: attributionData.variation,
ua: attributionData.ua,
dltoken: attributionData.dltoken,
msstoresignedin: attributionData.msstoresignedin,
dlsource: attributionData.dlsource,
};
Services.fog.updateAttribution(
attributionData.source,
attributionData.medium,
attributionData.campaign,
attributionData.term,
attributionData.content
);
Glean.gleanAttribution.ext.set(extAttribution);
}, },
/** /**
@@ -1894,6 +1910,15 @@ EnvironmentCache.prototype = {
); );
partnerData.partnerNames = partnerBranch.getChildList(""); partnerData.partnerNames = partnerBranch.getChildList("");
Services.fog.updateDistribution(partnerData.distributionId);
Glean.gleanDistribution.ext.set({
distributionVersion: partnerData.distributionVersion,
partnerId: partnerData.partnerId,
distributor: partnerData.distributor,
distributorChannel: partnerData.distributorChannel,
partnerNames: partnerData.partnerNames,
});
return partnerData; return partnerData;
}, },

View File

@@ -379,6 +379,18 @@ export var TelemetryEnvironmentTesting = {
lazy.Assert.equal(typeof data.settings.attribution, "object"); lazy.Assert.equal(typeof data.settings.attribution, "object");
lazy.Assert.equal(data.settings.attribution.source, "google.com"); lazy.Assert.equal(data.settings.attribution.source, "google.com");
lazy.Assert.equal(data.settings.attribution.dlsource, "unittest"); lazy.Assert.equal(data.settings.attribution.dlsource, "unittest");
let attr = Services.fog.testGetAttribution();
lazy.Assert.equal(
attr.source,
"google.com",
"Must have correct attribution.source."
);
let attrExt = Glean.gleanAttribution.ext.testGetValue();
lazy.Assert.equal(
attrExt.dlsource,
"unittest",
"Must have correct dlsource."
);
} }
this.checkIntlSettings(data.settings); this.checkIntlSettings(data.settings);
@@ -444,6 +456,8 @@ export var TelemetryEnvironmentTesting = {
"There must be a partner section in Environment." "There must be a partner section in Environment."
); );
let dist = Services.fog.testGetDistribution();
let distExt = Glean.gleanDistribution.ext.testGetValue();
for (let f in EXPECTED_FIELDS) { for (let f in EXPECTED_FIELDS) {
let expected = isInitial ? null : EXPECTED_FIELDS[f]; let expected = isInitial ? null : EXPECTED_FIELDS[f];
lazy.Assert.strictEqual( lazy.Assert.strictEqual(
@@ -451,14 +465,32 @@ export var TelemetryEnvironmentTesting = {
expected, expected,
f + " must have the correct value." f + " must have the correct value."
); );
if (f == "distributionId") {
lazy.Assert.strictEqual(
dist.name,
expected,
"Core Glean distribution must be correct."
);
} else {
lazy.Assert.equal(
distExt[f],
expected,
`Extended Glean distribution field "${f}" must be correct.`
);
}
} }
// Check that "partnerNames" exists and contains the correct element. // Check that "partnerNames" exists and contains the correct element.
lazy.Assert.ok(Array.isArray(data.partner.partnerNames)); lazy.Assert.ok(Array.isArray(data.partner.partnerNames));
if (isInitial) { if (isInitial) {
lazy.Assert.equal(data.partner.partnerNames.length, 0); lazy.Assert.equal(data.partner.partnerNames.length, 0);
lazy.Assert.equal(distExt.partnerNames, null);
} else { } else {
lazy.Assert.ok(data.partner.partnerNames.includes(PARTNER_NAME)); lazy.Assert.ok(data.partner.partnerNames.includes(PARTNER_NAME));
lazy.Assert.ok(
distExt.partnerNames.includes(PARTNER_NAME),
"Glean partner names contain expected partner name."
);
} }
}, },