Bug 1759744 - Add support for page load event telemetry r=smaug,chutten

Differential Revision: https://phabricator.services.mozilla.com/D141369
This commit is contained in:
Denis Palmeiro 2022-04-11 17:15:00 +00:00
Родитель 42699cdd90
Коммит dede6512b0
5 изменённых файлов: 191 добавлений и 6 удалений

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

@ -240,6 +240,7 @@
#include "mozilla/gfx/Coord.h" #include "mozilla/gfx/Coord.h"
#include "mozilla/gfx/Point.h" #include "mozilla/gfx/Point.h"
#include "mozilla/gfx/ScaleFactor.h" #include "mozilla/gfx/ScaleFactor.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/intl/LocaleService.h" #include "mozilla/intl/LocaleService.h"
#include "mozilla/ipc/IdleSchedulerChild.h" #include "mozilla/ipc/IdleSchedulerChild.h"
#include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/MessageChannel.h"
@ -278,6 +279,7 @@
#include "nsDOMString.h" #include "nsDOMString.h"
#include "nsDeviceContext.h" #include "nsDeviceContext.h"
#include "nsDocShell.h" #include "nsDocShell.h"
#include "nsDocShellLoadTypes.h"
#include "nsError.h" #include "nsError.h"
#include "nsEscape.h" #include "nsEscape.h"
#include "nsFocusManager.h" #include "nsFocusManager.h"
@ -1981,12 +1983,19 @@ void Document::ConstructUbiNode(void* storage) {
} }
void Document::LoadEventFired() { void Document::LoadEventFired() {
// Object used to collect some telemetry data so we don't need to query for it
// twice.
PageLoadEventTelemetryData pageLoadEventData;
// Accumulate timing data located in each document's realm and report to // Accumulate timing data located in each document's realm and report to
// telemetry. // telemetry.
AccumulateJSTelemetry(); AccumulateJSTelemetry(pageLoadEventData);
// Collect page load timings // Collect page load timings
AccumulatePageLoadTelemetry(); AccumulatePageLoadTelemetry(pageLoadEventData);
// Record page load event
RecordPageLoadEventTelemetry(pageLoadEventData);
// Release the JS bytecode cache from its wait on the load event, and // Release the JS bytecode cache from its wait on the load event, and
// potentially dispatch the encoding of the bytecode. // potentially dispatch the encoding of the bytecode.
@ -1995,7 +2004,85 @@ void Document::LoadEventFired() {
} }
} }
void Document::AccumulatePageLoadTelemetry() { void Document::RecordPageLoadEventTelemetry(
PageLoadEventTelemetryData aEventTelemetryData) {
static bool sTelemetryEventEnabled = false;
if (!sTelemetryEventEnabled) {
sTelemetryEventEnabled = true;
Telemetry::SetEventRecordingEnabled("page_load"_ns, true);
}
// If the page load time is empty, then the content wasn't something we want
// to report (i.e. not a top level document).
if (!aEventTelemetryData.mPageLoadTime ||
aEventTelemetryData.mPageLoadTime.IsZero()) {
return;
}
MOZ_ASSERT(IsTopLevelContentDocument());
nsPIDOMWindowOuter* window = GetWindow();
if (!window) {
return;
}
nsIDocShell* docshell = window->GetDocShell();
if (!docshell) {
return;
}
nsAutoCString loadTypeStr;
switch (docshell->GetLoadType()) {
case LOAD_NORMAL:
case LOAD_NORMAL_REPLACE:
case LOAD_NORMAL_BYPASS_CACHE:
case LOAD_NORMAL_BYPASS_PROXY:
case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
loadTypeStr.Append("NORMAL");
break;
case LOAD_HISTORY:
loadTypeStr.Append("HISTORY");
break;
case LOAD_RELOAD_NORMAL:
case LOAD_RELOAD_BYPASS_CACHE:
case LOAD_RELOAD_BYPASS_PROXY:
case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
case LOAD_REFRESH:
case LOAD_REFRESH_REPLACE:
case LOAD_RELOAD_CHARSET_CHANGE:
case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
loadTypeStr.Append("RELOAD");
break;
case LOAD_LINK:
loadTypeStr.Append("LINK");
break;
case LOAD_STOP_CONTENT:
case LOAD_STOP_CONTENT_AND_REPLACE:
loadTypeStr.Append("STOP");
break;
case LOAD_ERROR_PAGE:
loadTypeStr.Append("ERROR");
break;
default:
loadTypeStr.Append("OTHER");
break;
}
mozilla::glean::perf::PageLoadExtra extra = {
mozilla::Some(static_cast<uint32_t>(
aEventTelemetryData.mFirstContentfulPaintTime.ToMilliseconds())),
mozilla::Some(static_cast<uint32_t>(
aEventTelemetryData.mTotalJSExecutionTime.ToMilliseconds())),
mozilla::Some(static_cast<uint32_t>(
aEventTelemetryData.mPageLoadTime.ToMilliseconds())),
mozilla::Some(loadTypeStr),
mozilla::Some(static_cast<uint32_t>(
aEventTelemetryData.mResponseStartTime.ToMilliseconds()))};
mozilla::glean::perf::page_load.Record(mozilla::Some(extra));
}
void Document::AccumulatePageLoadTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut) {
// Interested only in top level documents for real websites that are in the // Interested only in top level documents for real websites that are in the
// foreground. // foreground.
if (!ShouldIncludeInTelemetry(false) || !IsTopLevelContentDocument() || if (!ShouldIncludeInTelemetry(false) || !IsTopLevelContentDocument() ||
@ -2076,6 +2163,9 @@ void Document::AccumulatePageLoadTelemetry() {
Telemetry::AccumulateTimeDelta( Telemetry::AccumulateTimeDelta(
Telemetry::PERF_FIRST_CONTENTFUL_PAINT_FROM_RESPONSESTART_MS, Telemetry::PERF_FIRST_CONTENTFUL_PAINT_FROM_RESPONSESTART_MS,
responseStart, firstContentfulComposite); responseStart, firstContentfulComposite);
aEventTelemetryDataOut.mFirstContentfulPaintTime =
firstContentfulComposite - navigationStart;
} }
// DOM Content Loaded event // DOM Content Loaded event
@ -2107,10 +2197,14 @@ void Document::AccumulatePageLoadTelemetry() {
Telemetry::AccumulateTimeDelta( Telemetry::AccumulateTimeDelta(
Telemetry::PERF_PAGE_LOAD_TIME_FROM_RESPONSESTART_MS, responseStart, Telemetry::PERF_PAGE_LOAD_TIME_FROM_RESPONSESTART_MS, responseStart,
loadEventStart); loadEventStart);
aEventTelemetryDataOut.mResponseStartTime = responseStart - navigationStart;
aEventTelemetryDataOut.mPageLoadTime = loadEventStart - navigationStart;
} }
} }
void Document::AccumulateJSTelemetry() { void Document::AccumulateJSTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut) {
if (!IsTopLevelContentDocument() || !ShouldIncludeInTelemetry(false)) { if (!IsTopLevelContentDocument() || !ShouldIncludeInTelemetry(false)) {
return; return;
} }
@ -2128,6 +2222,7 @@ void Document::AccumulateJSTelemetry() {
Telemetry::Accumulate( Telemetry::Accumulate(
Telemetry::JS_PAGELOAD_EXECUTION_MS, Telemetry::JS_PAGELOAD_EXECUTION_MS,
static_cast<uint32_t>(timers.executionTime.ToMilliseconds())); static_cast<uint32_t>(timers.executionTime.ToMilliseconds()));
aEventTelemetryDataOut.mTotalJSExecutionTime = timers.executionTime;
} }
if (!timers.delazificationTime.IsZero()) { if (!timers.delazificationTime.IsZero()) {

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

@ -338,6 +338,12 @@ class DOMStyleSheetSetList;
class ResizeObserver; class ResizeObserver;
class ResizeObserverController; class ResizeObserverController;
class PostMessageEvent; class PostMessageEvent;
struct PageLoadEventTelemetryData {
TimeDuration mPageLoadTime;
TimeDuration mTotalJSExecutionTime;
TimeDuration mResponseStartTime;
TimeDuration mFirstContentfulPaintTime;
};
#define DEPRECATED_OPERATION(_op) e##_op, #define DEPRECATED_OPERATION(_op) e##_op,
enum class DeprecatedOperations : uint16_t { enum class DeprecatedOperations : uint16_t {
@ -5280,11 +5286,17 @@ class Document : public nsINode,
// See SetNotifyFormOrPasswordRemoved and ShouldNotifyFormOrPasswordRemoved. // See SetNotifyFormOrPasswordRemoved and ShouldNotifyFormOrPasswordRemoved.
bool mShouldNotifyFormOrPasswordRemoved; bool mShouldNotifyFormOrPasswordRemoved;
// Record page load telemetry
void RecordPageLoadEventTelemetry(
PageLoadEventTelemetryData aEventTelemetryData);
// Accumulate JS telemetry collected // Accumulate JS telemetry collected
void AccumulateJSTelemetry(); void AccumulateJSTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut);
// Accumulate page load metrics // Accumulate page load metrics
void AccumulatePageLoadTelemetry(); void AccumulatePageLoadTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut);
// The OOP counterpart to nsDocLoader::mChildrenInOnload. // The OOP counterpart to nsDocLoader::mChildrenInOnload.
// Not holding strong refs here since we don't actually use the BBCs. // Not holding strong refs here since we don't actually use the BBCs.

55
dom/metrics.yaml Normal file
Просмотреть файл

@ -0,0 +1,55 @@
# 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/.
# This file defines the metrics that are recorded by the Glean SDK. They are
# automatically converted to platform-specific code at build time using the
# `glean_parser` PyPI package.
# 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:
- 'Core :: DOM: Core & HTML'
perf:
page_load:
type: event
description: >
Recorded when a top level content document has been loaded.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1759744
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1759744#c5
notification_emails:
- perf-telemetry-alerts@mozilla.com
- dpalmeiro@mozilla.com
expires: never
extra_keys:
load_time:
description:
"Time between loadEventStart and navigationStart, in ms."
type: quantity
unit: ms
response_time:
description:
"Time between responseStart and navigationStart, in ms."
type: quantity
unit: ms
fcp_time:
description:
"Time between firstContentfulPaint and naviationStart, in ms."
type: quantity
unit: ms
js_exec_time:
description:
"Time spent executing JS during page load, in ms."
type: quantity
unit: ms
load_type:
description:
"One of normal,reload,stop,link,history,error or other."
type: string
telemetry_mirror: Page_load_Toplevel_Content

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

@ -23,6 +23,7 @@ metrics_yamls = [
"browser/modules/metrics.yaml", "browser/modules/metrics.yaml",
"browser/components/metrics.yaml", "browser/components/metrics.yaml",
"toolkit/components/telemetry/metrics.yaml", "toolkit/components/telemetry/metrics.yaml",
"dom/metrics.yaml",
] ]
# The list of all Glean pings.yaml files, relative to the top src dir. # The list of all Glean pings.yaml files, relative to the top src dir.

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

@ -2897,6 +2897,28 @@ slow_script_warning:
uri_type: The kind of script URL that hung. uri_type: The kind of script URL that hung.
uptime: How long the notification was up (ms). uptime: How long the notification was up (ms).
page_load:
toplevel:
bug_numbers:
- 1759744
description: >
Recorded when a top level content document has been loaded.
products:
- "firefox"
record_in_processes: ["content"]
release_channel_collection: opt-out
expiry_version: "never"
notification_emails:
- dpalmeiro@mozilla.com
- perf-telemetry-alerts@mozilla.com
objects: ["content"]
extra_keys:
load_time: Time between loadEventStart and navigationStart, in ms.
response_time: Time between responseStart and navigationStart, in ms.
fcp_time: Time between firstContentfulPaint and navigationStart, in ms.
js_exec_time: Time spent executing JS during page load, in ms.
load_type: One of normal,reload,stop,link,history,error or other.
webrtc.ui: webrtc.ui:
show_indicator: show_indicator:
objects: ["show_indicator"] objects: ["show_indicator"]