Add metric for backup result failures (#31322)

This commit is contained in:
Darnell Andries
2025-09-29 21:37:39 -07:00
committed by GitHub
parent be4a6edf7d
commit c68208e275
12 changed files with 321 additions and 3 deletions
+2 -1
View File
@@ -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)
+1
View File
@@ -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};
};
+8 -1
View File
@@ -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
+5
View File
@@ -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
+4
View File
@@ -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},