Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Unified Diff: components/doodle/doodle_service.cc

Issue 2760253003: [Doodle] Record UMA for DoodleConfig download outcome and time (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/doodle/doodle_service.h ('k') | components/doodle/doodle_service_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/doodle/doodle_service.cc
diff --git a/components/doodle/doodle_service.cc b/components/doodle/doodle_service.cc
index 12a56200bb613a7a9dae0f583c444d2082489220..4fe7deaa11d9960aa2f95b8ace94b9de6e98e6d4 100644
--- a/components/doodle/doodle_service.cc
+++ b/components/doodle/doodle_service.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/doodle/pref_names.h"
@@ -16,6 +17,41 @@
namespace doodle {
+namespace {
+
+// Note: Keep in sync with the corresponding enum in histograms.xml. Never
+// remove values, and only insert new values at the end.
+enum DoodleConfigDownloadOutcome {
+ OUTCOME_NEW_DOODLE,
+ OUTCOME_REVALIDATED_DOODLE,
+ OUTCOME_CHANGED_DOODLE,
+ OUTCOME_NO_DOODLE,
+ OUTCOME_EXPIRED,
+ OUTCOME_DOWNLOAD_ERROR,
+ OUTCOME_PARSING_ERROR,
+ // Insert new values here!
+ OUTCOME_COUNT
+};
+
+bool DownloadOutcomeIsSuccess(DoodleConfigDownloadOutcome outcome) {
+ switch (outcome) {
+ case OUTCOME_NEW_DOODLE:
+ case OUTCOME_REVALIDATED_DOODLE:
+ case OUTCOME_CHANGED_DOODLE:
+ case OUTCOME_NO_DOODLE:
+ return true;
+ case OUTCOME_EXPIRED:
+ case OUTCOME_DOWNLOAD_ERROR:
+ case OUTCOME_PARSING_ERROR:
+ return false;
+ case OUTCOME_COUNT:
+ NOTREACHED();
+ }
+ return false;
+}
+
+} // namespace
+
// static
void DoodleService::RegisterProfilePrefs(PrefRegistrySimple* pref_registry) {
pref_registry->RegisterDictionaryPref(prefs::kCachedConfig,
@@ -28,21 +64,27 @@ void DoodleService::RegisterProfilePrefs(PrefRegistrySimple* pref_registry) {
DoodleService::DoodleService(PrefService* pref_service,
std::unique_ptr<DoodleFetcher> fetcher,
std::unique_ptr<base::OneShotTimer> expiry_timer,
- std::unique_ptr<base::Clock> clock)
+ std::unique_ptr<base::Clock> clock,
+ std::unique_ptr<base::TickClock> tick_clock)
: pref_service_(pref_service),
fetcher_(std::move(fetcher)),
expiry_timer_(std::move(expiry_timer)),
- clock_(std::move(clock)) {
+ clock_(std::move(clock)),
+ tick_clock_(std::move(tick_clock)) {
DCHECK(pref_service_);
DCHECK(fetcher_);
DCHECK(expiry_timer_);
DCHECK(clock_);
+ DCHECK(tick_clock_);
base::Time expiry_date = base::Time::FromInternalValue(
pref_service_->GetInt64(prefs::kCachedConfigExpiry));
base::Optional<DoodleConfig> config = DoodleConfig::FromDictionary(
*pref_service_->GetDictionary(prefs::kCachedConfig), base::nullopt);
- UpdateCachedConfig(expiry_date - clock_->Now(), config);
+ DoodleState state =
+ config.has_value() ? DoodleState::AVAILABLE : DoodleState::NO_DOODLE;
+ UpdateCachedConfig(/*download_time=*/base::nullopt, state,
+ expiry_date - clock_->Now(), config);
}
DoodleService::~DoodleService() = default;
@@ -58,18 +100,23 @@ void DoodleService::RemoveObserver(Observer* observer) {
}
void DoodleService::Refresh() {
- fetcher_->FetchDoodle(
- base::BindOnce(&DoodleService::DoodleFetched, base::Unretained(this)));
+ fetcher_->FetchDoodle(base::BindOnce(&DoodleService::DoodleFetched,
+ base::Unretained(this),
+ tick_clock_->NowTicks()));
}
void DoodleService::DoodleFetched(
+ base::TimeTicks start_time,
DoodleState state,
base::TimeDelta time_to_live,
const base::Optional<DoodleConfig>& doodle_config) {
- UpdateCachedConfig(time_to_live, doodle_config);
+ base::TimeDelta download_time = tick_clock_->NowTicks() - start_time;
+ UpdateCachedConfig(download_time, state, time_to_live, doodle_config);
}
void DoodleService::UpdateCachedConfig(
+ base::Optional<base::TimeDelta> download_time,
+ DoodleState state,
base::TimeDelta time_to_live,
const base::Optional<DoodleConfig>& doodle_config) {
fhorschig 2017/03/21 15:26:27 80 lines and nested ifs make this really hard to r
// Handle the case where the new config is already expired.
@@ -77,18 +124,26 @@ void DoodleService::UpdateCachedConfig(
const base::Optional<DoodleConfig>& new_config =
expired ? base::nullopt : doodle_config;
+ DoodleConfigDownloadOutcome outcome = OUTCOME_COUNT;
+
// If the config changed, update our cache and notify observers.
// Note that this checks both for existence changes as well as changes of the
// configs themselves.
if (cached_config_ != new_config) {
fhorschig 2017/03/21 15:26:27 Can we consider putting this branch into a new fun
Marc Treib 2017/03/21 16:10:45 Hm. Maaaybe there's a sensible way to split this u
+ bool had_config_before = cached_config_.has_value();
+
cached_config_ = new_config;
if (cached_config_.has_value()) {
+ outcome = had_config_before ? OUTCOME_CHANGED_DOODLE : OUTCOME_NEW_DOODLE;
+
pref_service_->Set(prefs::kCachedConfig, *cached_config_->ToDictionary());
base::Time expiry_date = clock_->Now() + time_to_live;
pref_service_->SetInt64(prefs::kCachedConfigExpiry,
expiry_date.ToInternalValue());
} else {
+ outcome = OUTCOME_NO_DOODLE;
+
pref_service_->ClearPref(prefs::kCachedConfig);
pref_service_->ClearPref(prefs::kCachedConfigExpiry);
}
@@ -96,6 +151,39 @@ void DoodleService::UpdateCachedConfig(
for (auto& observer : observers_) {
observer.OnDoodleConfigUpdated(cached_config_);
}
+ } else {
+ outcome = cached_config_.has_value() ? OUTCOME_REVALIDATED_DOODLE
+ : OUTCOME_NO_DOODLE;
+ }
+
+ // If the update came from the network, record metrics.
+ DCHECK(outcome != OUTCOME_COUNT);
fhorschig 2017/03/21 15:26:27 Is there any chance this couldn't have happened?
Marc Treib 2017/03/21 16:10:46 Nope, hence the DCHECK.
+ if (download_time.has_value()) {
+ // Determine the final outcome. ERROR or EXPIRED override NO_DOODLE.
fhorschig 2017/03/21 15:26:27 So this complete branch is basically dead for one
Marc Treib 2017/03/21 16:10:45 Good point.
fhorschig 2017/03/21 16:41:34 Not dead but very unused for one call. that's onl
Marc Treib 2017/03/21 16:48:59 Pulled it all out into a separate DetermineDownloa
+ switch (state) {
+ case DoodleState::AVAILABLE:
+ case DoodleState::NO_DOODLE:
+ if (expired) {
+ outcome = OUTCOME_EXPIRED;
+ }
+ break;
+
+ case DoodleState::DOWNLOAD_ERROR:
+ outcome = OUTCOME_DOWNLOAD_ERROR;
+ break;
+
+ case DoodleState::PARSING_ERROR:
+ outcome = OUTCOME_PARSING_ERROR;
+ break;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("Doodle.ConfigDownloadOutcome", outcome,
+ OUTCOME_COUNT);
+
+ if (DownloadOutcomeIsSuccess(outcome)) {
+ UMA_HISTOGRAM_MEDIUM_TIMES("Doodle.ConfigDownloadTime",
+ download_time.value());
+ }
}
// Even if the configs are identical, the time-to-live might have changed.
@@ -111,7 +199,8 @@ void DoodleService::UpdateCachedConfig(
void DoodleService::DoodleExpired() {
DCHECK(cached_config_.has_value());
- UpdateCachedConfig(base::TimeDelta(), base::nullopt);
+ UpdateCachedConfig(/*download_time=*/base::nullopt, DoodleState::NO_DOODLE,
+ base::TimeDelta(), base::nullopt);
}
} // namespace doodle
« no previous file with comments | « components/doodle/doodle_service.h ('k') | components/doodle/doodle_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698