Bug 1722465 - Investigate using telemetry archived data for determining profile activity r=Mardak

Differential Revision: https://phabricator.services.mozilla.com/D120959
This commit is contained in:
Andrei Oprea 2021-07-30 15:57:54 +00:00
Родитель 8d0f109dc3
Коммит 640ce71da0
5 изменённых файлов: 176 добавлений и 0 удалений

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

@ -50,6 +50,8 @@ Please note that some targeting attributes require stricter controls on the tele
* [activeNotifications](#activenotifications)
* [isMajorUpgrade](#ismajorupgrade)
* [hasActiveEnterprisePolicies](#hasactiveenterprisepolicies)
* [mainPingSubmissions](#mainpingsubmissions)
* [userMonthlyActivity](#usermonthlyactivity)
## Detailed usage
@ -816,3 +818,23 @@ A boolean. `true` if the browser just updated to a new major version.
### `hasActiveEnterprisePolicies`
A boolean. `true` if any Enterprise Policies are active.
### `mainPingSubmissions`
Filter through the local telemetry pings archive submitted and select the `main`
pings sent at least 24 hours apart. Result is sorted in ascending order.
```javascript
interface MainTelemetryPing {
id: string,
type: "main",
timestampCreated: number,
}
declare const mainPingSubmissions: Promise<MainTelemetryPing[]>
```
### `userMonthlyActivity`
Returns an array of entries in the form `[int, unixTimestamp]` for each day of
user activity where the first entry is the total urls visited for that day.

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

@ -28,6 +28,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
HomePage: "resource:///modules/HomePage.jsm",
AboutNewTab: "resource:///modules/AboutNewTab.jsm",
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
TelemetryArchive: "resource://gre/modules/TelemetryArchive.jsm",
});
XPCOMUtils.defineLazyPreferenceGetter(
@ -243,6 +244,7 @@ const QueryCache = {
CheckBrowserNeedsUpdate: new CheckBrowserNeedsUpdate(),
RecentBookmarks: new CachedTargetingGetter("getRecentBookmarks"),
ListAttachedOAuthClients: new CacheListAttachedOAuthClients(),
UserMonthlyActivity: new CachedTargetingGetter("getUserMonthlyActivity"),
},
};
@ -634,6 +636,38 @@ const TargetingGetters = {
get hasActiveEnterprisePolicies() {
return Services.policies.status === Services.policies.ACTIVE;
},
get mainPingSubmissions() {
return (
TelemetryArchive.promiseArchivedPingList()
// Filter out non-main pings. Do it before so we compare timestamps
// between pings of same type.
.then(pings => pings.filter(p => p.type === "main"))
.then(pings => {
if (pings.length <= 1) {
return pings;
}
// Pings are returned in ascending order.
return pings.reduce(
(acc, ping) => {
if (
// Keep only main pings sent a day (or more) apart
new Date(ping.timestampCreated).toDateString() !==
new Date(acc[acc.length - 1].timestampCreated).toDateString()
) {
acc.push(ping);
}
return acc;
},
[pings[0]]
);
})
);
},
get userMonthlyActivity() {
return QueryCache.queries.UserMonthlyActivity.get();
},
};
this.ASRouterTargeting = {

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

@ -1103,3 +1103,10 @@ add_task(async function check_is_major_upgrade() {
"Should select the message"
);
});
add_task(async function check_userMonthlyActivity() {
ok(
Array.isArray(await ASRouterTargeting.Environment.userMonthlyActivity),
"value is an array"
);
});

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

@ -273,6 +273,103 @@ describe("#CacheListAttachedOAuthClients", () => {
assert.calledOnce(fxAccounts.listAttachedOAuthClients);
});
});
describe("#mainPingSubmissions", () => {
let promiseArchivedPingList;
let globals;
let sandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
globals = new GlobalOverrider();
});
afterEach(() => {
sandbox.restore();
globals.restore();
});
it("should return an empty list", async () => {
promiseArchivedPingList = sandbox.stub().resolves([]);
globals.set("TelemetryArchive", { promiseArchivedPingList });
assert.typeOf(
await ASRouterTargeting.Environment.mainPingSubmissions,
"array",
"we get back an array"
);
assert.lengthOf(
await ASRouterTargeting.Environment.mainPingSubmissions,
0,
"no pings available"
);
});
it("should filter out bhr pings", async () => {
promiseArchivedPingList = sandbox.stub().resolves([
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaf",
timestampCreated: 1622525975674,
type: "bhr",
},
]);
globals.set("TelemetryArchive", { promiseArchivedPingList });
assert.lengthOf(
await ASRouterTargeting.Environment.mainPingSubmissions,
0,
"no `main` pings available"
);
});
it("should filter out pings less than 24hrs apart", async () => {
let startTime = 0;
promiseArchivedPingList = sandbox.stub().resolves([
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaf",
timestampCreated: 1622525975674,
type: "bhr",
},
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaa",
timestampCreated: startTime,
type: "main",
},
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaa",
timestampCreated: startTime + 1000,
type: "main",
},
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaac",
timestampCreated: startTime + 86400001,
type: "main",
},
]);
globals.set("TelemetryArchive", { promiseArchivedPingList });
assert.lengthOf(
await ASRouterTargeting.Environment.mainPingSubmissions,
2,
"1 main ping is removed"
);
});
it("should allow for pings < 24hrs apart but on different days", async () => {
let startTime = new Date("2020-02-20").getTime();
let oneDay = 86400000;
promiseArchivedPingList = sandbox.stub().resolves([
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaaa",
// Using oneDay / 2 because timezone of browser running the test
// affects the calculation
timestampCreated: startTime - oneDay / 2,
type: "main",
},
{
id: "5c8c786b-eca5-734b-a755-7ec0f022aaac",
timestampCreated: startTime + 1000,
type: "main",
},
]);
globals.set("TelemetryArchive", { promiseArchivedPingList });
assert.lengthOf(
await ASRouterTargeting.Environment.mainPingSubmissions,
2,
"pings are less day oneDay apart but fall on different days"
);
});
});
describe("ASRouterTargeting", () => {
let evalStub;
let sandbox;

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

@ -1341,6 +1341,22 @@ var ActivityStreamProvider = {
return result;
},
/**
* Count the number of visited urls grouped by day
*/
getUserMonthlyActivity() {
let sqlQuery = `
SELECT count(*),
strftime('%d-%m-%Y', visit_date/1000000.0, 'unixepoch') as date_format
FROM moz_historyvisits
WHERE visit_date > 0
AND visit_date > strftime('%s','now','localtime','start of day','-30 days','utc') * 1000000
GROUP BY date_format
`;
return this.executePlacesQuery(sqlQuery);
},
/**
* Executes arbitrary query against places database
*