Add metric for backup result failures (#31322)
This commit is contained in:
@@ -16,13 +16,13 @@
|
||||
#include "brave/browser/misc_metrics/uptime_monitor_impl.h"
|
||||
#include "brave/browser/ntp_background/ntp_p3a_helper_impl.h"
|
||||
#include "brave/browser/playlist/playlist_service_factory.h"
|
||||
#include "brave/browser/search_engines/search_engine_tracker.h"
|
||||
#include "brave/browser/themes/brave_dark_mode_utils.h"
|
||||
#include "brave/browser/updater/buildflags.h"
|
||||
#include "brave/components/ai_chat/core/browser/ai_chat_metrics.h"
|
||||
#include "brave/components/ai_chat/core/common/pref_names.h"
|
||||
#include "brave/components/brave_origin/brave_origin_prefs.h"
|
||||
#include "brave/components/brave_referrals/browser/brave_referrals_service.h"
|
||||
#include "brave/components/brave_search/browser/backup_results_metrics.h"
|
||||
#include "brave/components/brave_search_conversion/p3a.h"
|
||||
#include "brave/components/brave_shields/content/browser/ad_block_service.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_p3a.h"
|
||||
@@ -198,6 +198,7 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
|
||||
ai_chat::AIChatMetrics::RegisterPrefs(registry);
|
||||
brave_ads::BraveStatsHelper::RegisterLocalStatePrefs(registry);
|
||||
misc_metrics::GeneralBrowserUsage::RegisterPrefs(registry);
|
||||
brave_search::BackupResultsMetrics::RegisterPrefs(registry);
|
||||
|
||||
playlist::PlaylistServiceFactory::RegisterLocalStatePrefs(registry);
|
||||
#if BUILDFLAG(ENABLE_WEB_DISCOVERY_NATIVE)
|
||||
|
||||
@@ -17,6 +17,7 @@ source_set("brave_search") {
|
||||
"//brave/components/brave_search/browser",
|
||||
"//brave/components/brave_search/common",
|
||||
"//brave/components/brave_shields/core/browser",
|
||||
"//chrome/browser:browser_process",
|
||||
"//chrome/browser/content_extraction",
|
||||
"//chrome/browser/content_settings:content_settings_factory",
|
||||
"//chrome/browser/profiles",
|
||||
|
||||
@@ -42,4 +42,8 @@ BackupResultsServiceFactory::BuildServiceInstanceForBrowserContext(
|
||||
Profile::FromBrowserContext(context));
|
||||
}
|
||||
|
||||
bool BackupResultsServiceFactory::ServiceIsCreatedWithBrowserContext() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace brave_search
|
||||
|
||||
@@ -37,6 +37,8 @@ class BackupResultsServiceFactory : public ProfileKeyedServiceFactory {
|
||||
// ProfileKeyedServiceFactory overrides:
|
||||
std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
|
||||
content::BrowserContext* context) const override;
|
||||
|
||||
bool ServiceIsCreatedWithBrowserContext() const override;
|
||||
};
|
||||
|
||||
} // namespace brave_search
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "brave/components/brave_search/browser/backup_results_service.h"
|
||||
#include "brave/components/brave_search/common/features.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_utils.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "chrome/browser/content_extraction/inner_html.h"
|
||||
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
@@ -109,7 +110,8 @@ WEB_CONTENTS_USER_DATA_KEY_IMPL(BackupResultsWebContentsObserver);
|
||||
} // namespace
|
||||
|
||||
BackupResultsServiceImpl::BackupResultsServiceImpl(Profile* profile)
|
||||
: profile_(profile) {
|
||||
: profile_(profile),
|
||||
backup_results_metrics_(g_browser_process->local_state()) {
|
||||
profile_->AddObserver(this);
|
||||
}
|
||||
BackupResultsServiceImpl::~BackupResultsServiceImpl() = default;
|
||||
@@ -344,6 +346,9 @@ void BackupResultsServiceImpl::CleanupAndDispatchResult(
|
||||
std::optional<BackupResults> result) {
|
||||
auto* otr_profile = pending_request->otr_profile.get();
|
||||
|
||||
// Track query result (failure if result is nullopt, success otherwise)
|
||||
backup_results_metrics_.RecordQuery(!result);
|
||||
|
||||
std::move(pending_request->callback).Run(result);
|
||||
pending_requests_.erase(pending_request);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "brave/components/brave_search/browser/backup_results_metrics.h"
|
||||
#include "brave/components/brave_search/browser/backup_results_service.h"
|
||||
#include "chrome/browser/profiles/profile_observer.h"
|
||||
#include "net/http/http_request_headers.h"
|
||||
@@ -102,6 +103,8 @@ class BackupResultsServiceImpl : public BackupResultsService,
|
||||
|
||||
PendingRequestList pending_requests_;
|
||||
|
||||
BackupResultsMetrics backup_results_metrics_;
|
||||
|
||||
base::WeakPtrFactory<BackupResultsServiceImpl> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ static_library("browser") {
|
||||
sources = [
|
||||
"backup_results_allowed_urls.cc",
|
||||
"backup_results_allowed_urls.h",
|
||||
"backup_results_metrics.cc",
|
||||
"backup_results_metrics.h",
|
||||
"backup_results_service.cc",
|
||||
"backup_results_service.h",
|
||||
"brave_search_default_host.cc",
|
||||
@@ -25,6 +27,7 @@ static_library("browser") {
|
||||
"//brave/components/brave_search/common",
|
||||
"//brave/components/brave_search/common:mojom",
|
||||
"//brave/components/brave_search_conversion",
|
||||
"//brave/components/p3a_utils",
|
||||
"//brave/components/time_period_storage",
|
||||
"//components/prefs",
|
||||
"//components/search_engines",
|
||||
@@ -36,11 +39,15 @@ static_library("browser") {
|
||||
|
||||
source_set("unit_tests") {
|
||||
testonly = true
|
||||
sources = [ "backup_results_allowed_urls_unittest.cc" ]
|
||||
sources = [
|
||||
"backup_results_allowed_urls_unittest.cc",
|
||||
"backup_results_metrics_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":browser",
|
||||
"//base/test:test_support",
|
||||
"//components/prefs:test_support",
|
||||
"//testing/gtest",
|
||||
"//url",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
|
||||
* 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/brave_search/browser/backup_results_metrics.h"
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/time/time.h"
|
||||
#include "brave/components/brave_search/browser/prefs.h"
|
||||
#include "brave/components/p3a_utils/bucket.h"
|
||||
#include "brave/components/time_period_storage/daily_storage.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
|
||||
namespace brave_search {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr base::TimeDelta kReportUpdateInterval = base::Hours(1);
|
||||
|
||||
// Bucket ranges for P3A metric: 0, 1, 2, 3-8, 8+
|
||||
constexpr int kFailureCountBuckets[] = {0, 1, 2, 8};
|
||||
|
||||
} // namespace
|
||||
|
||||
BackupResultsMetrics::BackupResultsMetrics(PrefService* local_state)
|
||||
: local_state_(local_state) {
|
||||
ReportMetrics();
|
||||
}
|
||||
|
||||
BackupResultsMetrics::~BackupResultsMetrics() = default;
|
||||
|
||||
void BackupResultsMetrics::RegisterPrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterTimePref(prefs::kBackupResultsLastQueryTime, {});
|
||||
registry->RegisterListPref(prefs::kBackupResultsFailuresStorage);
|
||||
}
|
||||
|
||||
void BackupResultsMetrics::RecordQuery(bool is_failure) {
|
||||
// Always record the query time when a query is made
|
||||
local_state_->SetTime(prefs::kBackupResultsLastQueryTime, base::Time::Now());
|
||||
|
||||
// If it's a failure, increment the failure counter
|
||||
if (is_failure) {
|
||||
MaybeInitializeFailureStorage();
|
||||
failures_storage_->RecordValueNow(1);
|
||||
}
|
||||
|
||||
// Update the metric immediately
|
||||
ReportMetrics();
|
||||
}
|
||||
|
||||
void BackupResultsMetrics::ReportMetrics() {
|
||||
auto now = base::Time::Now();
|
||||
auto last_query_time =
|
||||
local_state_->GetTime(prefs::kBackupResultsLastQueryTime);
|
||||
|
||||
// Early return if no background search query was made in the past 24 hours
|
||||
if (last_query_time.is_null() || (now - last_query_time) >= base::Days(1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MaybeInitializeFailureStorage();
|
||||
|
||||
uint64_t failure_count = failures_storage_->GetLast24HourSum();
|
||||
|
||||
p3a_utils::RecordToHistogramBucket(kBackupResultsFailuresHistogramName,
|
||||
kFailureCountBuckets, failure_count);
|
||||
|
||||
// Set up the next timer after reporting
|
||||
report_timer_.Start(FROM_HERE, now + kReportUpdateInterval,
|
||||
base::BindOnce(&BackupResultsMetrics::ReportMetrics,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
|
||||
void BackupResultsMetrics::MaybeInitializeFailureStorage() {
|
||||
if (!failures_storage_) {
|
||||
failures_storage_ = std::make_unique<DailyStorage>(
|
||||
local_state_, prefs::kBackupResultsFailuresStorage);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace brave_search
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
|
||||
* 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_COMPONENTS_BRAVE_SEARCH_BROWSER_BACKUP_RESULTS_METRICS_H_
|
||||
#define BRAVE_COMPONENTS_BRAVE_SEARCH_BROWSER_BACKUP_RESULTS_METRICS_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/timer/wall_clock_timer.h"
|
||||
|
||||
class PrefRegistrySimple;
|
||||
class PrefService;
|
||||
class DailyStorage;
|
||||
|
||||
namespace brave_search {
|
||||
|
||||
inline constexpr char kBackupResultsFailuresHistogramName[] =
|
||||
"Brave.Search.BackupResultsFailures";
|
||||
|
||||
// Metrics for tracking background search query failures
|
||||
// Only reports if at least one background search query was made in the past day
|
||||
class BackupResultsMetrics {
|
||||
public:
|
||||
explicit BackupResultsMetrics(PrefService* local_state);
|
||||
~BackupResultsMetrics();
|
||||
|
||||
BackupResultsMetrics(const BackupResultsMetrics&) = delete;
|
||||
BackupResultsMetrics& operator=(const BackupResultsMetrics&) = delete;
|
||||
|
||||
static void RegisterPrefs(PrefRegistrySimple* registry);
|
||||
|
||||
// Called when a background search query is made
|
||||
// |is_failure| - true if the query failed, false if it succeeded or started
|
||||
void RecordQuery(bool is_failure);
|
||||
|
||||
private:
|
||||
void ReportMetrics();
|
||||
void MaybeInitializeFailureStorage();
|
||||
|
||||
raw_ptr<PrefService> local_state_;
|
||||
|
||||
std::unique_ptr<DailyStorage> failures_storage_;
|
||||
|
||||
base::WallClockTimer report_timer_;
|
||||
};
|
||||
|
||||
} // namespace brave_search
|
||||
|
||||
#endif // BRAVE_COMPONENTS_BRAVE_SEARCH_BROWSER_BACKUP_RESULTS_METRICS_H_
|
||||
@@ -0,0 +1,151 @@
|
||||
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
|
||||
* 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/brave_search/browser/backup_results_metrics.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/prefs/testing_pref_service.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace brave_search {
|
||||
|
||||
class BackupResultsMetricsTest : public ::testing::Test {
|
||||
protected:
|
||||
BackupResultsMetricsTest()
|
||||
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
|
||||
|
||||
void SetUp() override {
|
||||
BackupResultsMetrics::RegisterPrefs(prefs_.registry());
|
||||
}
|
||||
|
||||
void CreateMetrics() {
|
||||
backup_results_metrics_ = std::make_unique<BackupResultsMetrics>(&prefs_);
|
||||
}
|
||||
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
TestingPrefServiceSimple prefs_;
|
||||
std::unique_ptr<BackupResultsMetrics> backup_results_metrics_;
|
||||
base::HistogramTester histogram_tester_;
|
||||
};
|
||||
|
||||
TEST_F(BackupResultsMetricsTest, RecordsSuccessfulQuery) {
|
||||
CreateMetrics();
|
||||
|
||||
histogram_tester_.ExpectTotalCount(kBackupResultsFailuresHistogramName, 0);
|
||||
|
||||
// Record a successful query
|
||||
backup_results_metrics_->RecordQuery(false);
|
||||
|
||||
// Should report 0 failures
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 0,
|
||||
1);
|
||||
}
|
||||
|
||||
TEST_F(BackupResultsMetricsTest, RecordsFailedQuery) {
|
||||
CreateMetrics();
|
||||
|
||||
// Record a failed query
|
||||
backup_results_metrics_->RecordQuery(true);
|
||||
|
||||
// Should report 1 failure
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 1,
|
||||
1);
|
||||
|
||||
backup_results_metrics_->RecordQuery(true);
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 2,
|
||||
1);
|
||||
|
||||
// Record multiple failed queries
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
backup_results_metrics_->RecordQuery(true);
|
||||
}
|
||||
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 3,
|
||||
3);
|
||||
histogram_tester_.ExpectTotalCount(kBackupResultsFailuresHistogramName, 5);
|
||||
}
|
||||
|
||||
TEST_F(BackupResultsMetricsTest, RecordsMixedQueries) {
|
||||
CreateMetrics();
|
||||
|
||||
// Record mix of successful and failed queries
|
||||
backup_results_metrics_->RecordQuery(false); // success - reports 0 failures
|
||||
backup_results_metrics_->RecordQuery(true); // failure - reports 1 failure
|
||||
backup_results_metrics_->RecordQuery(
|
||||
false); // success - reports 1 failure (unchanged)
|
||||
backup_results_metrics_->RecordQuery(true); // failure - reports 2 failures
|
||||
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 0,
|
||||
1);
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 1,
|
||||
2); // 1 intermediate report
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 2,
|
||||
1); // final report
|
||||
histogram_tester_.ExpectTotalCount(kBackupResultsFailuresHistogramName, 4);
|
||||
}
|
||||
|
||||
TEST_F(BackupResultsMetricsTest, CanResetMetricsDuringTest) {
|
||||
CreateMetrics();
|
||||
|
||||
// Record a query
|
||||
backup_results_metrics_->RecordQuery(true);
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 1,
|
||||
1);
|
||||
|
||||
CreateMetrics();
|
||||
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 1,
|
||||
2);
|
||||
|
||||
backup_results_metrics_->RecordQuery(false);
|
||||
|
||||
// Should report 0 failures for the new instance
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 1,
|
||||
3);
|
||||
}
|
||||
|
||||
TEST_F(BackupResultsMetricsTest, HistogramUpdatedAfterTimerFires) {
|
||||
CreateMetrics();
|
||||
|
||||
// Record a successful query first to establish last query time
|
||||
backup_results_metrics_->RecordQuery(false);
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 0,
|
||||
1);
|
||||
|
||||
task_environment_.FastForwardBy(base::Hours(1));
|
||||
|
||||
histogram_tester_.ExpectUniqueSample(kBackupResultsFailuresHistogramName, 0,
|
||||
2);
|
||||
|
||||
// Record a failure
|
||||
backup_results_metrics_->RecordQuery(true);
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 1,
|
||||
1);
|
||||
|
||||
// Fast forward by 1 hour (within 24 hours)
|
||||
task_environment_.FastForwardBy(base::Hours(1));
|
||||
|
||||
// Timer should have fired and reported the metric again since within 24h
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 1,
|
||||
2);
|
||||
|
||||
task_environment_.FastForwardBy(base::Days(2));
|
||||
|
||||
// Histogram should NOT update anymore since last query time exceeds 24 hours
|
||||
histogram_tester_.ExpectBucketCount(kBackupResultsFailuresHistogramName, 1,
|
||||
24);
|
||||
histogram_tester_.ExpectTotalCount(kBackupResultsFailuresHistogramName,
|
||||
26); // No change
|
||||
|
||||
CreateMetrics();
|
||||
histogram_tester_.ExpectTotalCount(kBackupResultsFailuresHistogramName,
|
||||
26); // No change
|
||||
}
|
||||
|
||||
} // namespace brave_search
|
||||
@@ -18,6 +18,11 @@ inline constexpr char kFetchFromNative[] =
|
||||
"brave.brave_search.fetch_se_from_native";
|
||||
#endif
|
||||
|
||||
inline constexpr char kBackupResultsLastQueryTime[] =
|
||||
"brave.search.backup_results.last_query_time";
|
||||
inline constexpr char kBackupResultsFailuresStorage[] =
|
||||
"brave.search.backup_results.failures_storage";
|
||||
|
||||
} // namespace prefs
|
||||
} // namespace brave_search
|
||||
|
||||
|
||||
@@ -212,6 +212,10 @@ inline constexpr auto kCollectedExpressHistograms =
|
||||
}},
|
||||
{"Brave.PermissionLifetime.24Hours", MetricConfig{.ephemeral = true}},
|
||||
{"Brave.Rewards.EnabledInstallationTime", MetricConfig{.ephemeral = true}},
|
||||
{"Brave.Search.BackupResultsFailures", MetricConfig{
|
||||
.ephemeral = true,
|
||||
.attributes = MetricAttributes{MetricAttribute::kAnswerIndex, MetricAttribute::kVersion, MetricAttribute::kChannel, MetricAttribute::kPlatform, MetricAttribute::kCountryCode},
|
||||
}},
|
||||
{"Brave.Search.BraveDaily", MetricConfig{.ephemeral = true}},
|
||||
{"Brave.Search.DefaultEngine.4", MetricConfig{
|
||||
.attributes = MetricAttributes{MetricAttribute::kAnswerIndex, MetricAttribute::kChannel, MetricAttribute::kPlatform, MetricAttribute::kDateOfInstall, MetricAttribute::kVersion, MetricAttribute::kCountryCode},
|
||||
|
||||
Reference in New Issue
Block a user