Commit 2e720fc7 authored by Robert Ogden's avatar Robert Ogden Committed by Commit Bot

Add PrefetchProxy UKM

Adds a new UKM event, PrefetchProxy, which is recorded once on every
page load for Data Saver users. The metrics in the event are capped and
bucketed as described in the privacy doc (see bug).

Bug: 995437
Change-Id: Iddf5d148ccbfe784316ae57bcf439db0cdaffc85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1872986
Commit-Queue: Robert Ogden <robertogden@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709548}
parent 5c31ec73
......@@ -4,6 +4,8 @@
#include "chrome/browser/page_load_metrics/observers/subresource_loading_page_load_metrics_observer.h"
#include <algorithm>
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "chrome/browser/history/history_service_factory.h"
......@@ -16,10 +18,24 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "net/cookies/cookie_options.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
namespace {
// Yields 10 buckets between 1 and 180 (1,2,3,5,9,15,25,42,70,119), per privacy
// requirements. Computed using:
// CEIL(
// POW(kDaysSinceLastVisitBucketSpacing,
// FLOOR(LN(sample) / LN(kDaysSinceLastVisitBucketSpacing)))
// )
const double kDaysSinceLastVisitBucketSpacing = 1.7;
const size_t kUkmCssJsBeforeFcpMax = 10;
bool IsCSSOrJS(const std::string& mime_type) {
std::string lower_mime_type = base::ToLowerASCII(mime_type);
return lower_mime_type == "text/css" ||
......@@ -78,6 +94,9 @@ SubresourceLoadingPageLoadMetricsObserver::OnCommit(
if (profile->IsOffTheRecord())
return STOP_OBSERVING;
data_saver_enabled_at_commit_ = data_reduction_proxy::
DataReductionProxySettings::IsDataSaverEnabledByUser(profile->GetPrefs());
history::HistoryService* history_service =
HistoryServiceFactory::GetForProfileIfExists(
profile, ServiceAccessType::IMPLICIT_ACCESS);
......@@ -186,9 +205,6 @@ void SubresourceLoadingPageLoadMetricsObserver::RecordMetrics() {
}
history_query_times_.clear();
// TODO(crbug.com/995437): Add UKM for data saver users once all metrics
// are in place.
if (mainframe_had_cookies_.has_value()) {
UMA_HISTOGRAM_BOOLEAN(
"PageLoad.Clients.SubresourceLoading.MainFrameHadCookies",
......@@ -215,6 +231,42 @@ void SubresourceLoadingPageLoadMetricsObserver::RecordMetrics() {
UMA_HISTOGRAM_COUNTS_100(
"PageLoad.Clients.SubresourceLoading.LoadedCSSJSBeforeFCP.Noncached",
loaded_css_js_from_network_before_fcp_);
// Only record UKM for Data Saver users.
if (!data_saver_enabled_at_commit_)
return;
ukm::builders::PrefetchProxy builder(GetDelegate().GetSourceId());
if (min_days_since_last_visit_to_origin_.has_value()) {
// The -1 value is a sentinel to signal there was no previous visit. Don't
// let the ukm call make it 0.
if (min_days_since_last_visit_to_origin_.value() == -1) {
builder.Setdays_since_last_visit_to_origin(-1);
} else {
int64_t maxxed_days_since_last_visit =
std::min(180, min_days_since_last_visit_to_origin_.value());
int64_t ukm_days_since_last_visit = ukm::GetExponentialBucketMin(
maxxed_days_since_last_visit, kDaysSinceLastVisitBucketSpacing);
builder.Setdays_since_last_visit_to_origin(ukm_days_since_last_visit);
}
}
if (mainframe_had_cookies_.has_value()) {
int ukm_mainpage_had_cookies = mainframe_had_cookies_.value() ? 1 : 0;
builder.Setmainpage_request_had_cookies(ukm_mainpage_had_cookies);
}
int ukm_loaded_css_js_from_cache_before_fcp =
std::min(kUkmCssJsBeforeFcpMax, loaded_css_js_from_cache_before_fcp_);
builder.Setcount_css_js_loaded_cache_before_fcp(
ukm_loaded_css_js_from_cache_before_fcp);
int ukm_loaded_css_js_from_network_before_fcp =
std::min(kUkmCssJsBeforeFcpMax, loaded_css_js_from_network_before_fcp_);
builder.Setcount_css_js_loaded_network_before_fcp(
ukm_loaded_css_js_from_network_before_fcp);
builder.Record(ukm::UkmRecorder::Get());
}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
......
......@@ -71,6 +71,9 @@ class SubresourceLoadingPageLoadMetricsObserver
const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
resources) override;
// Whether data saver was enabled for this page load when it committed.
bool data_saver_enabled_at_commit_ = false;
// The time that the navigation started. Used to timebox the history service
// query on commit.
base::Time navigation_start_;
......
......@@ -4,12 +4,19 @@
#include "chrome/browser/page_load_metrics/observers/subresource_loading_page_load_metrics_observer.h"
#include <memory>
#include "base/command_line.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/ukm/test_ukm_recorder.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "testing/gtest/include/gtest/gtest.h"
class SubresourceLoadingPageLoadMetricsObserverBrowserTest
......@@ -18,6 +25,11 @@ class SubresourceLoadingPageLoadMetricsObserverBrowserTest
SubresourceLoadingPageLoadMetricsObserverBrowserTest() = default;
~SubresourceLoadingPageLoadMetricsObserverBrowserTest() override = default;
void EnableDataSaver() {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
data_reduction_proxy::switches::kEnableDataReductionProxy);
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
......@@ -26,6 +38,8 @@ class SubresourceLoadingPageLoadMetricsObserverBrowserTest
embedded_test_server()->ServeFilesFromSourceDirectory(
"chrome/test/data/subresource_loading");
ASSERT_TRUE(embedded_test_server()->Start());
ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
void NavigateToPath(const std::string& path) {
......@@ -38,6 +52,36 @@ class SubresourceLoadingPageLoadMetricsObserverBrowserTest
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
base::RunLoop().RunUntilIdle();
}
void VerifyNoUKM() {
auto entries = ukm_recorder_->GetEntriesByName(
ukm::builders::PrefetchProxy::kEntryName);
EXPECT_TRUE(entries.empty());
}
void VerifyUKMEntry(const std::string& metric_name,
base::Optional<int64_t> expected_value) {
auto entries = ukm_recorder_->GetEntriesByName(
ukm::builders::PrefetchProxy::kEntryName);
ASSERT_EQ(1U, entries.size());
const auto* entry = entries.front();
ukm_recorder_->ExpectEntrySourceHasUrl(
entry, embedded_test_server()->GetURL("origin.com", "/index.html"));
const int64_t* value =
ukm::TestUkmRecorder::GetEntryMetric(entry, metric_name);
EXPECT_EQ(value != nullptr, expected_value.has_value());
if (!expected_value.has_value())
return;
EXPECT_EQ(*value, expected_value.value());
}
private:
std::unique_ptr<ukm::TestAutoSetUkmRecorder> ukm_recorder_;
};
IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
......@@ -66,6 +110,7 @@ IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
// Revisit and expect a 0 days-ago entry.
NavigateToPath("/index.html");
NavigateAway();
histogram_tester.ExpectBucketCount(
"PageLoad.Clients.SubresourceLoading.HasPreviousVisitToOrigin", true, 1);
histogram_tester.ExpectBucketCount(
......@@ -76,9 +121,25 @@ IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
"PageLoad.Clients.SubresourceLoading.HistoryQueryTime", 2);
}
IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
MainFrameHadCookies_NoUKM) {
base::HistogramTester histogram_tester;
NavigateToPath("/index.html");
NavigateAway();
histogram_tester.ExpectUniqueSample(
"PageLoad.Clients.SubresourceLoading.MainFrameHadCookies", false, 1);
histogram_tester.ExpectTotalCount(
"PageLoad.Clients.SubresourceLoading.CookiesQueryTime", 1);
VerifyNoUKM();
}
IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
MainFrameHadCookies_None) {
EnableDataSaver();
base::HistogramTester histogram_tester;
NavigateToPath("/index.html");
NavigateAway();
......@@ -86,15 +147,22 @@ IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
"PageLoad.Clients.SubresourceLoading.MainFrameHadCookies", false, 1);
histogram_tester.ExpectTotalCount(
"PageLoad.Clients.SubresourceLoading.CookiesQueryTime", 1);
using UkmEntry = ukm::builders::PrefetchProxy;
VerifyUKMEntry(UkmEntry::kmainpage_request_had_cookiesName, 0);
}
IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
MainFrameHadCookies_CookiesOnNextPageLoad) {
base::HistogramTester histogram_tester;
NavigateToPath("/set_cookies.html");
base::HistogramTester histogram_tester;
EnableDataSaver();
NavigateToPath("/index.html");
NavigateAway();
using UkmEntry = ukm::builders::PrefetchProxy;
VerifyUKMEntry(UkmEntry::kmainpage_request_had_cookiesName, 1);
histogram_tester.ExpectBucketCount(
"PageLoad.Clients.SubresourceLoading.MainFrameHadCookies", true, 1);
// From the first page load.
......@@ -106,11 +174,15 @@ IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
MainFrameHadCookies_CookiesOnRedirect) {
base::HistogramTester histogram_tester;
NavigateToPath("/set_cookies.html");
base::HistogramTester histogram_tester;
EnableDataSaver();
NavigateToPath("/redirect_to_index.html");
NavigateAway();
using UkmEntry = ukm::builders::PrefetchProxy;
VerifyUKMEntry(UkmEntry::kmainpage_request_had_cookiesName, 1);
histogram_tester.ExpectBucketCount(
"PageLoad.Clients.SubresourceLoading.MainFrameHadCookies", true, 1);
// From the first page load.
......@@ -122,11 +194,13 @@ IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
IN_PROC_BROWSER_TEST_F(SubresourceLoadingPageLoadMetricsObserverBrowserTest,
RecordNothingOnUntrackedPage) {
EnableDataSaver();
base::HistogramTester histogram_tester;
NavigateAway();
NavigateAway();
VerifyNoUKM();
histogram_tester.ExpectTotalCount(
"PageLoad.Clients.SubresourceLoading.CookiesQueryTime", 0);
histogram_tester.ExpectTotalCount(
......
......@@ -6662,6 +6662,46 @@ be describing additional metrics about the same event.
</metric>
</event>
<event name="PrefetchProxy" singular="True">
<owner>robertogden@chromium.org</owner>
<owner>ryansturm@chromium.org</owner>
<owner>tbansal@chromium.org</owner>
<summary>
Metrics related to the privacy-preserving prefetch proxy. Recorded only for
Lite mode (AKA Data Saver) users.
</summary>
<metric name="count_css_js_loaded_cache_before_fcp">
<summary>
The number of CSS or JS files that were loaded from the cache before first
contentful paint, with a maximum of 10. Always set when this event is
recorded.
</summary>
</metric>
<metric name="count_css_js_loaded_network_before_fcp">
<summary>
The number of CSS or JS files that were loaded from the network before
FCP, with a maximum of 10. Always set when this event is recorded.
</summary>
</metric>
<metric name="days_since_last_visit_to_origin">
<summary>
The number of days since the user has last visited any page on this
origin, either during a redirect or a committed page. Records -1 if the
origin has never been visited before. Metrics for origins that have been
visited before are capped at 180 then exponentially bucketed into 10
buckets with values (1,2,3,5,9,15,25,42,70,119). Only set when a query
result was received from the history service before event recording.
</summary>
</metric>
<metric name="mainpage_request_had_cookies" enum="Boolean">
<summary>
A boolean indicating if any mainpage request in the redirect chain or
committed request had cookies set on it. Only set when a query result was
received from the cookie manager before event recording.
</summary>
</metric>
</event>
<event name="Previews" singular="True">
<owner>ryansturm@chromium.org</owner>
<summary>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment