Bug 1692350 - Implement a telemetry probe to collect page load data for documents that use lazyload r=emilio,chutten

Differential Revision: https://phabricator.services.mozilla.com/D104912
This commit is contained in:
Sean Feng 2021-02-17 22:25:02 +00:00
parent 973901dc46
commit 93ae22d5b9
10 changed files with 122 additions and 9 deletions

View File

@ -5776,6 +5776,15 @@ var TabsProgressListener = {
stopwatchRunning /* we won't see STATE_START events for pre-rendered tabs */
) {
if (recordLoadTelemetry) {
if (aBrowser.browsingContext?.topWindowContext?.hadLazyLoadImage) {
let timeElapsed = TelemetryStopwatch.timeElapsed(
histogram,
aBrowser
);
Services.telemetry
.getHistogramById("FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS")
.add(timeElapsed);
}
TelemetryStopwatch.finish(histogram, aBrowser);
BrowserTelemetryUtils.recordSiteOriginTelemetry(browserWindows());
}

View File

@ -260,6 +260,11 @@ bool WindowContext::CanSet(FieldIndex<IDX_IsLocalIP>, const bool& aValue,
return CheckOnlyOwningProcessCanSet(aSource);
}
bool WindowContext::CanSet(FieldIndex<IDX_HadLazyLoadImage>, const bool& aValue,
ContentParent* aSource) {
return IsTop();
}
void WindowContext::DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>,
bool aOldValue) {
MOZ_ASSERT(

View File

@ -82,7 +82,10 @@ class BrowsingContextGroup;
FIELD(HasReportedShadowDOMUsage, bool) \
/* Whether the principal of this window is for a local \
* IP address */ \
FIELD(IsLocalIP, bool)
FIELD(IsLocalIP, bool) \
/* Whether the corresponding document has `loading='lazy'` \
* images; It won't become false if the image becomes non-lazy */ \
FIELD(HadLazyLoadImage, bool)
class WindowContext : public nsISupports, public nsWrapperCache {
MOZ_DECL_SYNCED_CONTEXT(WindowContext, MOZ_EACH_WC_FIELD)
@ -175,6 +178,8 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool CanShowPopup();
bool HadLazyLoadImage() const { return GetHadLazyLoadImage(); }
protected:
WindowContext(BrowsingContext* aBrowsingContext, uint64_t aInnerWindowId,
uint64_t aOuterWindowId, bool aInProcess,
@ -262,6 +267,9 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_IsLocalIP>, const bool& aValue,
ContentParent* aSource);
bool CanSet(FieldIndex<IDX_HadLazyLoadImage>, const bool& aValue,
ContentParent* aSource);
void DidSet(FieldIndex<IDX_HasReportedShadowDOMUsage>, bool aOldValue);
void DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>, bool aOldValue);

View File

@ -15572,6 +15572,17 @@ bool Document::ConsumeTransientUserGestureActivation() {
return wc && wc->ConsumeTransientUserGestureActivation();
}
void Document::IncLazyLoadImageCount() {
if (!mLazyLoadImageCount) {
if (WindowContext* wc = GetTopLevelWindowContext()) {
if (!wc->HadLazyLoadImage()) {
MOZ_ALWAYS_SUCCEEDS(wc->SetHadLazyLoadImage(true));
}
}
}
++mLazyLoadImageCount;
}
void Document::SetDocTreeHadMedia() {
RefPtr<WindowContext> topWc = GetTopLevelWindowContext();
if (topWc && !topWc->IsDiscarded() && !topWc->GetDocTreeHadMedia()) {

View File

@ -3739,7 +3739,7 @@ class Document : public nsINode,
}
DOMIntersectionObserver& EnsureLazyLoadImageObserver();
DOMIntersectionObserver& EnsureLazyLoadImageObserverViewport();
void IncLazyLoadImageCount() { ++mLazyLoadImageCount; }
void IncLazyLoadImageCount();
void DecLazyLoadImageCount() {
MOZ_DIAGNOSTIC_ASSERT(mLazyLoadImageCount > 0);
--mLazyLoadImageCount;

View File

@ -25,6 +25,10 @@ interface WindowContext {
// True if the principal of this window is for a local ip address.
readonly attribute boolean isLocalIP;
// True if the corresponding document has `loading='lazy'` images;
// It won't become false if the image becomes non-lazy.
readonly attribute boolean hadLazyLoadImage;
};
// Keep this in sync with nsIContentViewer::PermitUnloadAction.

View File

@ -26,3 +26,7 @@ support-files =
support-files =
file_lazyload_telemetry.html
image_rgrg-256x256.png
[browser_lazyload_page_load_telemetry_iframe.js]
support-files =
file_lazyload_telemetry.html
image_rgrg-256x256.png

View File

@ -0,0 +1,48 @@
const baseURL = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"http://example.com"
);
const testFileURL = `${baseURL}file_lazyload_telemetry.html`;
const { TelemetryTestUtils } = ChromeUtils.import(
"resource://testing-common/TelemetryTestUtils.jsm"
);
function OtherLazyLoadDataIsReported() {
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false)
.content;
return snapshot.LAZYLOAD_IMAGE_TOTAL;
}
function pageLoadIsReported() {
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false)
.parent;
return snapshot.FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS;
}
add_task(async function testTelemetryCollection() {
Services.telemetry.getHistogramById("FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS").clear();
const testTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"data:text/html,<body><iframe src='" + testFileURL + "'></iframe></body>",
true
);
await BrowserTestUtils.waitForCondition(pageLoadIsReported);
gBrowser.removeTab(testTab);
// Running this test also causes some other LAZYLOAD related data
// to be collected. Wait for them to be collected to avoid firing
// them at an unexpected time.
await BrowserTestUtils.waitForCondition(OtherLazyLoadDataIsReported);
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false);
ok(
snapshot.parent.FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS.sum > 0,
"lazyload image page load telemetry"
);
});

View File

@ -9,6 +9,12 @@ const { TelemetryTestUtils } = ChromeUtils.import(
"resource://testing-common/TelemetryTestUtils.jsm"
);
function pageLoadIsReported() {
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false)
.parent;
return snapshot.FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS;
}
function dataIsReported() {
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false)
.content;
@ -25,6 +31,7 @@ add_task(async function testTelemetryCollection() {
.getHistogramById("LAZYLOAD_IMAGE_VIEWPORT_LOADING")
.clear();
Services.telemetry.getHistogramById("LAZYLOAD_IMAGE_VIEWPORT_LOADED").clear();
Services.telemetry.getHistogramById("FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS").clear();
const testTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
@ -47,20 +54,21 @@ add_task(async function testTelemetryCollection() {
}
);
await BrowserTestUtils.waitForCondition(pageLoadIsReported);
gBrowser.removeTab(testTab);
await BrowserTestUtils.waitForCondition(dataIsReported);
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false)
.content;
const snapshot = Services.telemetry.getSnapshotForHistograms("main", false);
// Ensures we have 4 lazyload images.
is(snapshot.LAZYLOAD_IMAGE_TOTAL.values[4], 1, "total images");
is(snapshot.content.LAZYLOAD_IMAGE_TOTAL.values[4], 1, "total images");
// All 4 images should be lazy-loaded.
is(snapshot.LAZYLOAD_IMAGE_STARTED.values[4], 1, "started to load");
is(snapshot.content.LAZYLOAD_IMAGE_STARTED.values[4], 1, "started to load");
// The last image didn't reach to the viewport.
is(
snapshot.LAZYLOAD_IMAGE_NOT_VIEWPORT.values[1],
snapshot.content.LAZYLOAD_IMAGE_NOT_VIEWPORT.values[1],
1,
"images didn't reach viewport"
);
@ -68,9 +76,13 @@ add_task(async function testTelemetryCollection() {
// should be three. This includes all images except
// the last one.
is(
snapshot.LAZYLOAD_IMAGE_VIEWPORT_LOADING.sum +
snapshot.LAZYLOAD_IMAGE_VIEWPORT_LOADED.sum,
snapshot.content.LAZYLOAD_IMAGE_VIEWPORT_LOADING.sum +
snapshot.content.LAZYLOAD_IMAGE_VIEWPORT_LOADED.sum,
3,
"images reached viewport"
);
ok(
snapshot.parent.FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS.sum > 0,
"lazyload image page load telemetry"
);
});

View File

@ -7708,6 +7708,18 @@
"alert_emails": ["tdsmith@mozilla.com", "perf-telemetry-alerts@mozilla.com", "product-metrics-telemetry-alerts@mozilla.com"],
"releaseChannelCollection": "opt-out"
},
"FX_LAZYLOAD_IMAGE_PAGE_LOAD_MS": {
"record_in_processes": ["main"],
"products": ["firefox"],
"expires_in_version": "never",
"kind": "linear",
"high": 10000,
"n_buckets": 100,
"description": "Firefox: Time taken to load a page that has at least one `loading='lazy'` image. (This metric includes both loads and reloads)",
"bug_numbers": [1692350],
"alert_emails": ["sefeng@mozilla.com", "perf-telemetry-alerts@mozilla.com"],
"releaseChannelCollection": "opt-out"
},
"FX_PAGE_RELOAD_NORMAL_MS": {
"record_in_processes": ["main"],
"products": ["firefox", "fennec"],