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/Point.h"
#include "mozilla/gfx/ScaleFactor.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/intl/LocaleService.h"
#include "mozilla/ipc/IdleSchedulerChild.h"
#include "mozilla/ipc/MessageChannel.h"
@ -278,6 +279,7 @@
#include "nsDOMString.h"
#include "nsDeviceContext.h"
#include "nsDocShell.h"
#include "nsDocShellLoadTypes.h"
#include "nsError.h"
#include "nsEscape.h"
#include "nsFocusManager.h"
@ -1981,12 +1983,19 @@ void Document::ConstructUbiNode(void* storage) {
}
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
// telemetry.
AccumulateJSTelemetry();
AccumulateJSTelemetry(pageLoadEventData);
// 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
// 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
// foreground.
if (!ShouldIncludeInTelemetry(false) || !IsTopLevelContentDocument() ||
@ -2076,6 +2163,9 @@ void Document::AccumulatePageLoadTelemetry() {
Telemetry::AccumulateTimeDelta(
Telemetry::PERF_FIRST_CONTENTFUL_PAINT_FROM_RESPONSESTART_MS,
responseStart, firstContentfulComposite);
aEventTelemetryDataOut.mFirstContentfulPaintTime =
firstContentfulComposite - navigationStart;
}
// DOM Content Loaded event
@ -2107,10 +2197,14 @@ void Document::AccumulatePageLoadTelemetry() {
Telemetry::AccumulateTimeDelta(
Telemetry::PERF_PAGE_LOAD_TIME_FROM_RESPONSESTART_MS, responseStart,
loadEventStart);
aEventTelemetryDataOut.mResponseStartTime = responseStart - navigationStart;
aEventTelemetryDataOut.mPageLoadTime = loadEventStart - navigationStart;
}
}
void Document::AccumulateJSTelemetry() {
void Document::AccumulateJSTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut) {
if (!IsTopLevelContentDocument() || !ShouldIncludeInTelemetry(false)) {
return;
}
@ -2128,6 +2222,7 @@ void Document::AccumulateJSTelemetry() {
Telemetry::Accumulate(
Telemetry::JS_PAGELOAD_EXECUTION_MS,
static_cast<uint32_t>(timers.executionTime.ToMilliseconds()));
aEventTelemetryDataOut.mTotalJSExecutionTime = timers.executionTime;
}
if (!timers.delazificationTime.IsZero()) {

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

@ -338,6 +338,12 @@ class DOMStyleSheetSetList;
class ResizeObserver;
class ResizeObserverController;
class PostMessageEvent;
struct PageLoadEventTelemetryData {
TimeDuration mPageLoadTime;
TimeDuration mTotalJSExecutionTime;
TimeDuration mResponseStartTime;
TimeDuration mFirstContentfulPaintTime;
};
#define DEPRECATED_OPERATION(_op) e##_op,
enum class DeprecatedOperations : uint16_t {
@ -5280,11 +5286,17 @@ class Document : public nsINode,
// See SetNotifyFormOrPasswordRemoved and ShouldNotifyFormOrPasswordRemoved.
bool mShouldNotifyFormOrPasswordRemoved;
// Record page load telemetry
void RecordPageLoadEventTelemetry(
PageLoadEventTelemetryData aEventTelemetryData);
// Accumulate JS telemetry collected
void AccumulateJSTelemetry();
void AccumulateJSTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut);
// Accumulate page load metrics
void AccumulatePageLoadTelemetry();
void AccumulatePageLoadTelemetry(
PageLoadEventTelemetryData& aEventTelemetryDataOut);
// The OOP counterpart to nsDocLoader::mChildrenInOnload.
// 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/components/metrics.yaml",
"toolkit/components/telemetry/metrics.yaml",
"dom/metrics.yaml",
]
# 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.
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:
show_indicator:
objects: ["show_indicator"]