Issue 8854: Implement search counter p3a metric.

Fix https://github.com/brave/brave-browser/issues/8854

To start measuring search volumes we start with omnibox - we would
count all search-related events coming from here. This PR also
refactors the utility class for recording "weekly" metrics.
This commit is contained in:
Ivan Efremov
2020-05-04 23:06:33 +07:00
parent b2a3f9a65e
commit 14aed89b84
18 changed files with 401 additions and 437 deletions
+1
View File
@@ -144,6 +144,7 @@ source_set("browser_process") {
"//brave/components/resources",
"//brave/components/services:brave_content_manifest_overlays",
"//brave/components/speedreader:buildflags",
"//brave/components/weekly_storage",
"//brave/services/network/public/cpp",
"//chrome/common",
"//components/autofill/core/common",
+3
View File
@@ -6,6 +6,7 @@
#include "brave/browser/brave_profile_prefs.h"
#include "brave/browser/themes/brave_dark_mode_utils.h"
#include "brave/browser/ui/omnibox/brave_omnibox_client_impl.h"
#include "brave/common/brave_wallet_constants.h"
#include "brave/common/pref_names.h"
#include "brave/components/binance/browser/buildflags/buildflags.h"
@@ -227,6 +228,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
speedreader::SpeedreaderService::RegisterPrefs(registry);
#endif
BraveOmniboxClientImpl::RegisterPrefs(registry);
RegisterProfilePrefsForMigration(registry);
}
+19 -107
View File
@@ -5,7 +5,6 @@
#include "brave/browser/p3a/p3a_core_metrics.h"
#include <numeric>
#include <utility>
#include "base/metrics/histogram_macros.h"
@@ -16,7 +15,6 @@
#include "chrome/browser/ui/browser_list.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
namespace brave {
@@ -54,103 +52,33 @@ const char* GetPrefNameForProfile(Profile* profile) {
BraveUptimeTracker* g_brave_uptime_tracker_instance = nullptr;
constexpr size_t kUsageTimeQueryIntervalMinutes = 1;
constexpr size_t kNumOfSavedDailyUptimes = 7;
constexpr char kDailyUptimesListPrefName[] = "daily_uptimes";
} // namespace
UsagePermanentState::UsagePermanentState(PrefService* local_state)
: local_state_(local_state) {
if (local_state) {
LoadUptimes();
BraveUptimeTracker::BraveUptimeTracker(PrefService* local_state)
: state_(local_state, kDailyUptimesListPrefName) {
timer_.Start(
FROM_HERE, base::TimeDelta::FromMinutes(kUsageTimeQueryIntervalMinutes),
base::Bind(&BraveUptimeTracker::RecordUsage, base::Unretained(this)));
}
void BraveUptimeTracker::RecordUsage() {
const base::TimeDelta new_total = usage_clock_.GetTotalUsageTime();
const base::TimeDelta interval = new_total - current_total_usage_;
if (interval > base::TimeDelta()) {
state_.AddDelta(interval.InSeconds());
current_total_usage_ = new_total;
RecordP3A();
}
}
UsagePermanentState::~UsagePermanentState() = default;
void UsagePermanentState::AddInterval(base::TimeDelta delta) {
base::Time now_midnight = base::Time::Now().LocalMidnight();
base::Time last_saved_midnight;
if (!daily_uptimes_.empty()) {
last_saved_midnight = daily_uptimes_.front().day;
}
if (now_midnight - last_saved_midnight > base::TimeDelta()) {
// Day changed. Since we consider only small incoming intervals, lets just
// save it with a new timestamp.
daily_uptimes_.push_front({now_midnight, delta});
if (daily_uptimes_.size() > kNumOfSavedDailyUptimes) {
daily_uptimes_.pop_back();
}
} else {
daily_uptimes_.front().uptime += delta;
}
RecordP3A();
SaveUptimes();
}
base::TimeDelta UsagePermanentState::GetTotalUsage() const {
// We record only uptime for last N days.
const base::Time n_days_ago =
base::Time::Now() - base::TimeDelta::FromDays(kNumOfSavedDailyUptimes);
return std::accumulate(daily_uptimes_.begin(), daily_uptimes_.end(),
DailyUptime(),
[n_days_ago](const auto& u1, const auto& u2) {
base::TimeDelta add;
// Check only last continious days.
if (u2.day > n_days_ago) {
add = u2.uptime;
}
return DailyUptime{{}, u1.uptime + add};
})
.uptime;
}
void UsagePermanentState::LoadUptimes() {
DCHECK(daily_uptimes_.empty());
const base::ListValue* list =
local_state_->GetList(kDailyUptimesListPrefName);
if (!list) {
return;
}
for (auto it = list->begin(); it != list->end(); ++it) {
const base::Value* day = it->FindKey("day");
const base::Value* uptime = it->FindKey("uptime");
if (!day || !uptime || !day->is_double() || !uptime->is_double()) {
continue;
}
if (daily_uptimes_.size() == kNumOfSavedDailyUptimes) {
break;
}
daily_uptimes_.push_back(
{base::Time::FromDoubleT(day->GetDouble()),
base::TimeDelta::FromSecondsD(uptime->GetDouble())});
}
}
void UsagePermanentState::SaveUptimes() {
DCHECK(!daily_uptimes_.empty());
DCHECK_LE(daily_uptimes_.size(), kNumOfSavedDailyUptimes);
ListPrefUpdate update(local_state_, kDailyUptimesListPrefName);
base::ListValue* list = update.Get();
// TODO(iefremov): Optimize if needed.
list->Clear();
for (const auto& u : daily_uptimes_) {
base::DictionaryValue value;
value.SetKey("day", base::Value(u.day.ToDoubleT()));
value.SetKey("uptime", base::Value(u.uptime.InSecondsF()));
list->Append(std::move(value));
}
}
void UsagePermanentState::RecordP3A() {
void BraveUptimeTracker::RecordP3A() {
int answer = 0;
if (daily_uptimes_.size() == kNumOfSavedDailyUptimes) {
base::TimeDelta total = GetTotalUsage();
const int minutes = total.InMinutes();
if (state_.IsOneWeekPassed()) {
uint64_t total = state_.GetWeeklySum();
const int minutes = base::TimeDelta::FromSeconds(total).InMinutes();
DCHECK_GE(minutes, 0);
if (0 <= minutes && minutes < 30) {
answer = 1;
@@ -163,22 +91,6 @@ void UsagePermanentState::RecordP3A() {
UMA_HISTOGRAM_EXACT_LINEAR("Brave.Uptime.BrowserOpenMinutes", answer, 3);
}
BraveUptimeTracker::BraveUptimeTracker(PrefService* local_state)
: state_(local_state) {
timer_.Start(
FROM_HERE, base::TimeDelta::FromMinutes(kUsageTimeQueryIntervalMinutes),
base::Bind(&BraveUptimeTracker::RecordUsage, base::Unretained(this)));
}
void BraveUptimeTracker::RecordUsage() {
const base::TimeDelta new_total = usage_clock_.GetTotalUsageTime();
const base::TimeDelta interval = new_total - current_total_usage_;
if (interval > base::TimeDelta()) {
state_.AddInterval(interval);
current_total_usage_ = new_total;
}
}
BraveUptimeTracker::~BraveUptimeTracker() = default;
void BraveUptimeTracker::CreateInstance(PrefService* local_state) {
+3 -22
View File
@@ -9,6 +9,7 @@
#include <list>
#include "base/timer/timer.h"
#include "brave/components/weekly_storage/weekly_storage.h"
#include "chrome/browser/resource_coordinator/usage_clock.h"
#include "chrome/browser/ui/browser_list_observer.h"
@@ -17,27 +18,6 @@ class PrefRegistrySimple;
namespace brave {
class UsagePermanentState {
public:
explicit UsagePermanentState(PrefService* local_state);
~UsagePermanentState();
void AddInterval(base::TimeDelta delta);
base::TimeDelta GetTotalUsage() const;
private:
struct DailyUptime {
base::Time day;
base::TimeDelta uptime;
};
void LoadUptimes();
void SaveUptimes();
void RecordP3A();
std::list<DailyUptime> daily_uptimes_;
PrefService* local_state_ = nullptr;
};
class BraveUptimeTracker {
public:
explicit BraveUptimeTracker(PrefService* local_state);
@@ -49,11 +29,12 @@ class BraveUptimeTracker {
private:
void RecordUsage();
void RecordP3A();
resource_coordinator::UsageClock usage_clock_;
base::RepeatingTimer timer_;
base::TimeDelta current_total_usage_;
UsagePermanentState state_;
WeeklyStorage state_;
DISALLOW_COPY_AND_ASSIGN(BraveUptimeTracker);
};
+1
View File
@@ -212,6 +212,7 @@ source_set("ui") {
"//brave/components/brave_wallet/browser/buildflags:buildflags",
"//brave/components/brave_welcome_ui:generated_resources",
"//brave/components/p3a:buildflags",
"//brave/components/weekly_storage",
"//chrome/app:command_ids",
"//chrome/app/vector_icons:vector_icons",
"//chrome/common",
@@ -5,22 +5,73 @@
#include "brave/browser/ui/omnibox/brave_omnibox_client_impl.h"
#include <algorithm>
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "brave/browser/autocomplete/brave_autocomplete_scheme_classifier.h"
#include "brave/common/pref_names.h"
#include "brave/components/weekly_storage/weekly_storage.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
#include "chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
namespace {
constexpr char kSearchCountPrefName[] = "brave.weekly_storage.search_count";
bool IsSearchEvent(const AutocompleteMatch& match) {
switch (match.type) {
case AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED:
case AutocompleteMatchType::SEARCH_HISTORY:
case AutocompleteMatchType::SEARCH_SUGGEST:
case AutocompleteMatchType::SEARCH_SUGGEST_ENTITY:
case AutocompleteMatchType::SEARCH_SUGGEST_TAIL:
case AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED:
case AutocompleteMatchType::SEARCH_SUGGEST_PROFILE:
case AutocompleteMatchType::SEARCH_OTHER_ENGINE:
return true;
default:
return false;
}
return false;
}
void RecordSearchEventP3A(uint64_t number_of_searches) {
constexpr int kIntervals[] = {0, 5, 10, 20, 50, 100, 500};
const int* it =
std::lower_bound(kIntervals, std::end(kIntervals), number_of_searches);
const int answer = it - kIntervals;
UMA_HISTOGRAM_EXACT_LINEAR("Brave.Omnibox.SearchCount", answer,
base::size(kIntervals));
}
} // namespace
BraveOmniboxClientImpl::BraveOmniboxClientImpl(
OmniboxEditController* controller,
Profile* profile)
: ChromeOmniboxClient(controller, profile),
profile_(profile),
scheme_classifier_(profile) {}
OmniboxEditController* controller,
Profile* profile)
: ChromeOmniboxClient(controller, profile),
profile_(profile),
scheme_classifier_(profile) {
// Record initial search count p3a value.
const base::Value* search_p3a =
profile_->GetPrefs()->GetList(kSearchCountPrefName);
if (search_p3a->GetList().size() == 0) {
RecordSearchEventP3A(0);
}
}
BraveOmniboxClientImpl::~BraveOmniboxClientImpl() {}
void BraveOmniboxClientImpl::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(kSearchCountPrefName);
}
const AutocompleteSchemeClassifier&
BraveOmniboxClientImpl::GetSchemeClassifier() const {
return scheme_classifier_;
@@ -29,3 +80,12 @@ BraveOmniboxClientImpl::GetSchemeClassifier() const {
bool BraveOmniboxClientImpl::IsAutocompleteEnabled() const {
return profile_->GetPrefs()->GetBoolean(kAutocompleteEnabled);
}
void BraveOmniboxClientImpl::OnInputAccepted(const AutocompleteMatch& match) {
// TODO(iefremov): Optimize this.
WeeklyStorage storage(profile_->GetPrefs(), kSearchCountPrefName);
if (IsSearchEvent(match)) {
storage.AddDelta(1);
RecordSearchEventP3A(storage.GetWeeklySum());
}
}
@@ -6,20 +6,25 @@
#ifndef BRAVE_BROWSER_UI_OMNIBOX_BRAVE_OMNIBOX_CLIENT_IMPL_H_
#define BRAVE_BROWSER_UI_OMNIBOX_BRAVE_OMNIBOX_CLIENT_IMPL_H_
#include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
#include "brave/browser/autocomplete/brave_autocomplete_scheme_classifier.h"
#include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
class OmniboxEditController;
class PrefRegistrySimple;
class Profile;
class BraveOmniboxClientImpl : public ChromeOmniboxClient {
public:
BraveOmniboxClientImpl(OmniboxEditController* controller,
Profile* profile);
BraveOmniboxClientImpl(OmniboxEditController* controller, Profile* profile);
~BraveOmniboxClientImpl() override;
static void RegisterPrefs(PrefRegistrySimple* prefs);
const AutocompleteSchemeClassifier& GetSchemeClassifier() const override;
bool IsAutocompleteEnabled() const override;
void OnInputAccepted(const AutocompleteMatch& match) override;
private:
Profile* profile_;
BraveAutocompleteSchemeClassifier scheme_classifier_;
@@ -22,8 +22,6 @@ source_set("browser") {
"bandwidth_savings_predictor.h",
"named_third_party_registry.cc",
"named_third_party_registry.h",
"p3a_bandwidth_savings_permanent_state.cc",
"p3a_bandwidth_savings_permanent_state.h",
"p3a_bandwidth_savings_tracker.cc",
"p3a_bandwidth_savings_tracker.h",
"perf_predictor_page_metrics_observer.cc",
@@ -36,6 +34,7 @@ source_set("browser") {
"//base",
"//brave/components/brave_perf_predictor/common",
"//brave/components/resources",
"//brave/components/weekly_storage",
"//components/page_load_metrics/browser",
"//components/page_load_metrics/common",
"//components/prefs",
@@ -1,115 +0,0 @@
/* Copyright 2019 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 http://mozilla.org/MPL/2.0/. */
#include "brave/components/brave_perf_predictor/browser/p3a_bandwidth_savings_permanent_state.h"
#include <numeric>
#include <utility>
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "brave/components/brave_perf_predictor/common/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
namespace brave_perf_predictor {
namespace {
constexpr size_t kNumOfSavedDailyUptimes = 7;
} // namespace
P3ABandwidthSavingsPermanentState::P3ABandwidthSavingsPermanentState(
PrefService* user_prefs)
: P3ABandwidthSavingsPermanentState(
user_prefs,
std::make_unique<base::DefaultClock>()) {}
P3ABandwidthSavingsPermanentState::P3ABandwidthSavingsPermanentState(
PrefService* user_prefs,
std::unique_ptr<base::Clock> clock)
: clock_(std::move(clock)), user_prefs_(user_prefs) {
if (user_prefs)
LoadSavingsDaily();
}
P3ABandwidthSavingsPermanentState::~P3ABandwidthSavingsPermanentState() =
default;
void P3ABandwidthSavingsPermanentState::AddSavings(uint64_t delta) {
base::Time now_midnight = clock_->Now().LocalMidnight();
base::Time last_saved_midnight;
if (!daily_savings_.empty())
last_saved_midnight = daily_savings_.front().day;
if (now_midnight - last_saved_midnight > base::TimeDelta()) {
// Day changed.
daily_savings_.emplace_front(DailySaving{now_midnight, delta});
if (daily_savings_.size() > kNumOfSavedDailyUptimes)
daily_savings_.pop_back();
} else {
daily_savings_.front().saving += delta;
}
SaveSavingsDaily();
}
uint64_t P3ABandwidthSavingsPermanentState::GetFullPeriodSavingsBytes() const {
// We record only saving for last N days.
const base::Time n_days_ago =
clock_->Now() - base::TimeDelta::FromDays(kNumOfSavedDailyUptimes);
return std::accumulate(daily_savings_.begin(), daily_savings_.end(), 0UL,
[n_days_ago](const uint64_t acc, const auto& u2) {
uint64_t add = 0;
// Check only last continious days.
if (u2.day > n_days_ago) {
add = u2.saving;
}
return acc + add;
});
}
void P3ABandwidthSavingsPermanentState::LoadSavingsDaily() {
DCHECK(daily_savings_.empty());
if (!user_prefs_)
return;
const base::ListValue* list =
user_prefs_->GetList(prefs::kBandwidthSavedDailyBytes);
if (!list)
return;
for (auto it = list->begin(); it != list->end(); ++it) {
const base::Value* day = it->FindKey("day");
const base::Value* saving = it->FindKey("saving");
if (!day || !saving || !day->is_double() || !saving->is_double())
continue;
if (daily_savings_.size() == kNumOfSavedDailyUptimes)
break;
daily_savings_.emplace_back(base::Time::FromDoubleT(day->GetDouble()),
static_cast<uint64_t>(saving->GetDouble()));
}
}
void P3ABandwidthSavingsPermanentState::SaveSavingsDaily() {
DCHECK(!daily_savings_.empty());
DCHECK_LE(daily_savings_.size(), kNumOfSavedDailyUptimes);
if (!user_prefs_)
return;
ListPrefUpdate update(user_prefs_, prefs::kBandwidthSavedDailyBytes);
base::ListValue* list = update.Get();
list->Clear();
for (const auto& u : daily_savings_) {
base::DictionaryValue value;
value.SetKey("day", base::Value(u.day.ToDoubleT()));
value.SetKey("saving", base::Value(static_cast<double>(u.saving)));
list->Append(std::move(value));
}
}
} // namespace brave_perf_predictor
@@ -1,62 +0,0 @@
/* Copyright 2019 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 http://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_BRAVE_PERF_PREDICTOR_BROWSER_P3A_BANDWIDTH_SAVINGS_PERMANENT_STATE_H_
#define BRAVE_COMPONENTS_BRAVE_PERF_PREDICTOR_BROWSER_P3A_BANDWIDTH_SAVINGS_PERMANENT_STATE_H_
#include <list>
#include <memory>
#include "base/time/time.h"
#include "base/values.h"
class PrefService;
namespace base {
class Clock;
} // namespace base
namespace brave_perf_predictor {
// This class accumulates savings reported via |AddSavings| over time in
// |PrefService| User Preferences for persistency and returns those for the last
// full period available when queried via |GetFullPeriodSavingsBytes|.
//
// Time interval to accumulate data for is defined internally and
// |GetFullPeriodSavingsBytes| returns 0 if there aren't enough readings to
// cover a full period.
class P3ABandwidthSavingsPermanentState {
public:
explicit P3ABandwidthSavingsPermanentState(PrefService* user_prefs);
// Constructor with injected clock for testing
P3ABandwidthSavingsPermanentState(PrefService* user_prefs,
std::unique_ptr<base::Clock> clock);
~P3ABandwidthSavingsPermanentState();
P3ABandwidthSavingsPermanentState(const P3ABandwidthSavingsPermanentState&) =
delete;
P3ABandwidthSavingsPermanentState& operator=(
const P3ABandwidthSavingsPermanentState&) = delete;
void AddSavings(uint64_t delta);
uint64_t GetFullPeriodSavingsBytes() const;
private:
struct DailySaving {
base::Time day;
uint64_t saving;
DailySaving(base::Time day, uint64_t saving) : day(day), saving(saving) {}
};
void LoadSavingsDaily();
void SaveSavingsDaily();
void RecordSavingsTotal();
std::unique_ptr<base::Clock> clock_;
std::list<DailySaving> daily_savings_;
PrefService* user_prefs_ = nullptr;
};
} // namespace brave_perf_predictor
#endif // BRAVE_COMPONENTS_BRAVE_PERF_PREDICTOR_BROWSER_P3A_BANDWIDTH_SAVINGS_PERMANENT_STATE_H_
@@ -1,100 +0,0 @@
/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */
#include "brave/components/brave_perf_predictor/browser/p3a_bandwidth_savings_permanent_state.h"
#include <memory>
#include <utility>
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "brave/components/brave_perf_predictor/browser/p3a_bandwidth_savings_tracker.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace brave_perf_predictor {
class P3ABandwidthSavingsPermanentStateTest : public ::testing::Test {
public:
P3ABandwidthSavingsPermanentStateTest() : clock_(new base::SimpleTestClock) {
P3ABandwidthSavingsTracker::RegisterPrefs(pref_service_.registry());
state_ = std::make_unique<P3ABandwidthSavingsPermanentState>(
&pref_service_, std::unique_ptr<base::Clock>(clock_));
clock_->SetNow(base::Time::Now());
}
protected:
base::SimpleTestClock* clock_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<P3ABandwidthSavingsPermanentState> state_;
};
TEST_F(P3ABandwidthSavingsPermanentStateTest, StartsZero) {
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), 0ULL);
}
TEST_F(P3ABandwidthSavingsPermanentStateTest, AddsSavings) {
uint64_t saving = 10000;
state_->AddSavings(saving);
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), saving);
// Accumulate
state_->AddSavings(saving);
state_->AddSavings(saving);
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), saving * 3);
}
TEST_F(P3ABandwidthSavingsPermanentStateTest, ForgetsOldSavings) {
uint64_t saving = 10000;
state_->AddSavings(saving);
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), saving);
clock_->Advance(base::TimeDelta::FromDays(8));
// More savings
state_->AddSavings(saving);
state_->AddSavings(saving);
// Should have forgotten about older days
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), saving * 2);
}
TEST_F(P3ABandwidthSavingsPermanentStateTest, RetrievesDailySavings) {
uint64_t saving = 10000;
for (int day = 0; day <= 7; day++) {
clock_->Advance(base::TimeDelta::FromDays(1));
state_->AddSavings(saving);
}
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), 7 * saving);
}
TEST_F(P3ABandwidthSavingsPermanentStateTest, HandlesSkippedDay) {
uint64_t saving = 10000;
for (int day = 0; day < 7; day++) {
clock_->Advance(base::TimeDelta::FromDays(1));
if (day == 3)
continue;
state_->AddSavings(saving);
}
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), 6 * saving);
}
TEST_F(P3ABandwidthSavingsPermanentStateTest, IntermittentUsage) {
uint64_t saving = 10000;
for (int day = 0; day < 10; day++) {
clock_->Advance(base::TimeDelta::FromDays(2));
state_->AddSavings(saving);
}
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), 4 * saving);
}
TEST_F(P3ABandwidthSavingsPermanentStateTest, InfrequentUsage) {
uint64_t saving = 10000;
state_->AddSavings(saving);
clock_->Advance(base::TimeDelta::FromDays(6));
state_->AddSavings(saving);
EXPECT_EQ(state_->GetFullPeriodSavingsBytes(), 2 * saving);
}
} // namespace brave_perf_predictor
@@ -11,8 +11,8 @@
#include "base/metrics/histogram_macros.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "brave/components/brave_perf_predictor/browser/p3a_bandwidth_savings_permanent_state.h"
#include "brave/components/brave_perf_predictor/common/pref_names.h"
#include "brave/components/weekly_storage/weekly_storage.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
@@ -51,11 +51,9 @@ void P3ABandwidthSavingsTracker::RecordSavings(uint64_t savings) {
if (savings > 0 && user_prefs_) {
// TODO(AndriusA): optimise if needed, loading permanent state on every
// record could be costly
auto permanent_state =
std::make_unique<P3ABandwidthSavingsPermanentState>(user_prefs_);
permanent_state->AddSavings(savings);
const auto total = permanent_state->GetFullPeriodSavingsBytes();
StoreSavingsHistogram(total);
WeeklyStorage weekly(user_prefs_, prefs::kBandwidthSavedDailyBytes);
weekly.AddDelta(savings);
StoreSavingsHistogram(weekly.GetWeeklySum());
}
}
+11 -14
View File
@@ -48,27 +48,24 @@ constexpr uint64_t kDefaultUploadIntervalSeconds = 60; // 1 minute.
// Whitelist for histograms that we collect. Will be replaced with something
// updating on the fly.
constexpr const char* kCollectedHistograms[] = {
"Brave.P3A.SentAnswersCount",
"Brave.Savings.BandwidthSavingsMB",
"Brave.Sync.Status",
// Deprecated:
// "DefaultBrowser.State",
"Brave.Importer.ImporterSource",
"Brave.Shields.UsageStatus",
// Do not gather detailed info regarding TOR usage for now.
// "Brave.Core.LastTimeTorUsed",
"Brave.Core.BookmarksCountOnProfileLoad",
"Brave.Core.IsDefault",
"Brave.Core.TorEverUsed",
"Brave.Core.LastTimeIncognitoUsed",
"Brave.Core.NumberOfExtensions",
"Brave.Core.BookmarksCountOnProfileLoad",
"Brave.Core.TabCount",
"Brave.Core.TorEverUsed",
"Brave.Core.WindowCount",
"Brave.Search.DefaultEngine",
"Brave.Rewards.WalletBalance.2",
"Brave.Importer.ImporterSource",
"Brave.Omnibox.SearchCount",
"Brave.P3A.SentAnswersCount",
"Brave.Rewards.AdsState.2",
"Brave.Rewards.AutoContributionsState.2",
"Brave.Rewards.TipsState.2",
"Brave.Rewards.AdsState.2",
"Brave.Rewards.WalletBalance.2",
"Brave.Savings.BandwidthSavingsMB",
"Brave.Search.DefaultEngine",
"Brave.Shields.UsageStatus",
"Brave.Sync.Status",
"Brave.Uptime.BrowserOpenMinutes",
"Brave.Welcome.InteractionStatus",
};
+10
View File
@@ -0,0 +1,10 @@
source_set("weekly_storage") {
sources = [
"weekly_storage.cc",
"weekly_storage.h",
]
deps = [
"//components/prefs",
]
}
+119
View File
@@ -0,0 +1,119 @@
/* Copyright 2020 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 http://mozilla.org/MPL/2.0/. */
#include "brave/components/weekly_storage/weekly_storage.h"
#include <numeric>
#include <utility>
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
namespace {
constexpr size_t kDaysInWeek = 7;
}
WeeklyStorage::WeeklyStorage(PrefService* prefs, const char* pref_name)
: prefs_(prefs),
pref_name_(pref_name),
clock_(std::make_unique<base::DefaultClock>()) {
DCHECK(pref_name);
if (prefs) {
Load();
}
}
WeeklyStorage::WeeklyStorage(PrefService* prefs,
const char* pref_name,
std::unique_ptr<base::Clock> clock)
: prefs_(prefs), pref_name_(pref_name), clock_(std::move(clock)) {
DCHECK(prefs);
DCHECK(pref_name);
Load();
}
WeeklyStorage::~WeeklyStorage() = default;
void WeeklyStorage::AddDelta(uint64_t delta) {
base::Time now_midnight = clock_->Now().LocalMidnight();
base::Time last_saved_midnight;
if (!daily_values_.empty()) {
last_saved_midnight = daily_values_.front().day;
}
if (now_midnight - last_saved_midnight > base::TimeDelta()) {
// Day changed. Since we consider only small incoming intervals, lets just
// save it with a new timestamp.
daily_values_.push_front({now_midnight, delta});
if (daily_values_.size() > kDaysInWeek) {
daily_values_.pop_back();
}
} else {
daily_values_.front().value += delta;
}
Save();
}
uint64_t WeeklyStorage::GetWeeklySum() const {
// We record only value for last N days.
const base::Time n_days_ago =
clock_->Now() - base::TimeDelta::FromDays(kDaysInWeek);
return std::accumulate(daily_values_.begin(), daily_values_.end(), 0ull,
[n_days_ago](const uint64_t acc, const auto& u2) {
uint64_t add = 0;
// Check only last continious days.
if (u2.day > n_days_ago) {
add = u2.value;
}
return acc + add;
});
}
bool WeeklyStorage::IsOneWeekPassed() const {
// TODO(iefremov): This is not true 100% (if the browser was launched once
// per week just after installation, for example).
return daily_values_.size() == kDaysInWeek;
}
void WeeklyStorage::Load() {
DCHECK(daily_values_.empty());
const base::ListValue* list = prefs_->GetList(pref_name_);
if (!list) {
return;
}
for (auto it = list->begin(); it != list->end(); ++it) {
const base::Value* day = it->FindKey("day");
const base::Value* value = it->FindKey("value");
if (!day || !value || !day->is_double() || !value->is_double()) {
continue;
}
if (daily_values_.size() == kDaysInWeek) {
break;
}
daily_values_.push_back({base::Time::FromDoubleT(day->GetDouble()),
static_cast<uint64_t>(value->GetDouble())});
}
}
void WeeklyStorage::Save() {
DCHECK(!daily_values_.empty());
DCHECK_LE(daily_values_.size(), kDaysInWeek);
ListPrefUpdate update(prefs_, pref_name_);
base::ListValue* list = update.Get();
// TODO(iefremov): Optimize if needed.
list->Clear();
for (const auto& u : daily_values_) {
base::DictionaryValue value;
value.SetKey("day", base::Value(u.day.ToDoubleT()));
value.SetDoubleKey("value", u.value);
list->Append(std::move(value));
}
}
@@ -0,0 +1,57 @@
/* Copyright 2020 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 http://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_COMPONENTS_WEEKLY_STORAGE_WEEKLY_STORAGE_H_
#define BRAVE_COMPONENTS_WEEKLY_STORAGE_WEEKLY_STORAGE_H_
#include <list>
#include <memory>
#include "base/time/time.h"
namespace base {
class Clock;
}
class PrefService;
// Mostly used by various P3A recorders - allows to track a sum of some
// values added from time to time via |AddDelta| over a last week.
// Requires |pref_name| to be already registered.
// Feel free to improve and refactor it - templatize a stored value type,
// change weekly interval or make a keyed service from it.
class WeeklyStorage {
public:
WeeklyStorage(PrefService* prefs, const char* pref_name);
// For tests.
WeeklyStorage(PrefService* user_prefs,
const char* pref_name,
std::unique_ptr<base::Clock> clock);
~WeeklyStorage();
WeeklyStorage(const WeeklyStorage&) = delete;
WeeklyStorage& operator=(const WeeklyStorage&) = delete;
void AddDelta(uint64_t delta);
uint64_t GetWeeklySum() const;
bool IsOneWeekPassed() const;
private:
struct DailyValue {
base::Time day;
uint64_t value = 0ull;
};
void Load();
void Save();
PrefService* prefs_ = nullptr;
const char* pref_name_ = nullptr;
std::unique_ptr<base::Clock> clock_;
std::list<DailyValue> daily_values_;
};
#endif // BRAVE_COMPONENTS_WEEKLY_STORAGE_WEEKLY_STORAGE_H_
@@ -0,0 +1,98 @@
/* Copyright (c) 2020 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 http://mozilla.org/MPL/2.0/. */
#include "brave/components/weekly_storage/weekly_storage.h"
#include <memory>
#include <utility>
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
class WeeklyStorageTest : public ::testing::Test {
public:
WeeklyStorageTest() : clock_(new base::SimpleTestClock) {
constexpr char kPrefName[] = "brave.weekly_test";
pref_service_.registry()->RegisterListPref(kPrefName);
state_ = std::make_unique<WeeklyStorage>(
&pref_service_, kPrefName, std::unique_ptr<base::Clock>(clock_));
clock_->SetNow(base::Time::Now());
}
protected:
base::SimpleTestClock* clock_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<WeeklyStorage> state_;
};
TEST_F(WeeklyStorageTest, StartsZero) {
EXPECT_EQ(state_->GetWeeklySum(), 0ULL);
}
TEST_F(WeeklyStorageTest, AddsSavings) {
uint64_t saving = 10000;
state_->AddDelta(saving);
EXPECT_EQ(state_->GetWeeklySum(), saving);
// Accumulate
state_->AddDelta(saving);
state_->AddDelta(saving);
EXPECT_EQ(state_->GetWeeklySum(), saving * 3);
}
TEST_F(WeeklyStorageTest, ForgetsOldSavings) {
uint64_t saving = 10000;
state_->AddDelta(saving);
EXPECT_EQ(state_->GetWeeklySum(), saving);
clock_->Advance(base::TimeDelta::FromDays(8));
// More savings
state_->AddDelta(saving);
state_->AddDelta(saving);
// Should have forgotten about older days
EXPECT_EQ(state_->GetWeeklySum(), saving * 2);
}
TEST_F(WeeklyStorageTest, RetrievesDailySavings) {
uint64_t saving = 10000;
for (int day = 0; day <= 7; day++) {
clock_->Advance(base::TimeDelta::FromDays(1));
state_->AddDelta(saving);
}
EXPECT_EQ(state_->GetWeeklySum(), 7 * saving);
}
TEST_F(WeeklyStorageTest, HandlesSkippedDay) {
uint64_t saving = 10000;
for (int day = 0; day < 7; day++) {
clock_->Advance(base::TimeDelta::FromDays(1));
if (day == 3)
continue;
state_->AddDelta(saving);
}
EXPECT_EQ(state_->GetWeeklySum(), 6 * saving);
}
TEST_F(WeeklyStorageTest, IntermittentUsage) {
uint64_t saving = 10000;
for (int day = 0; day < 10; day++) {
clock_->Advance(base::TimeDelta::FromDays(2));
state_->AddDelta(saving);
}
EXPECT_EQ(state_->GetWeeklySum(), 4 * saving);
}
TEST_F(WeeklyStorageTest, InfrequentUsage) {
uint64_t saving = 10000;
state_->AddDelta(saving);
clock_->Advance(base::TimeDelta::FromDays(6));
state_->AddDelta(saving);
EXPECT_EQ(state_->GetWeeklySum(), 2 * saving);
}
+1 -1
View File
@@ -118,6 +118,7 @@ test("brave_unit_tests") {
"//brave/components/ntp_background_images/browser/view_counter_service_unittest.cc",
"//brave/components/rappor/log_uploader_unittest.cc",
"//brave/components/translate/core/browser/translate_language_list_unittest.cc",
"//brave/components/weekly_storage/weekly_storage_unittest.cc",
"//brave/third_party/libaddressinput/chromium/chrome_metadata_source_unittest.cc",
"//brave/vendor/brave_base/random_unittest.cc",
"//components/bookmarks/browser/bookmark_model_unittest.cc",
@@ -480,7 +481,6 @@ test("brave_unit_tests") {
"//brave/components/brave_perf_predictor/browser/named_third_party_registry_unittest.cc",
"//brave/components/brave_perf_predictor/browser/bandwidth_linreg_unittest.cc",
"//brave/components/brave_perf_predictor/browser/bandwidth_savings_predictor_unittest.cc",
"//brave/components/brave_perf_predictor/browser/p3a_bandwidth_savings_permanent_state_unittest.cc",
"//brave/components/brave_perf_predictor/browser/p3a_bandwidth_savings_tracker_unittest.cc",
]