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

Side by Side Diff: components/ntp_snippets/user_classifier.cc

Issue 2315273002: Measure usage metrics to prepare for adaptive fetching rates in M55 (Closed)
Patch Set: Further polish Created 4 years, 3 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/ntp_snippets/user_classifier.h"
6
7 #include <float.h>
8
9 #include <algorithm>
10 #include <string>
11
12 #include "base/metrics/histogram_macros.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "components/ntp_snippets/pref_names.h"
15 #include "components/prefs/pref_registry_simple.h"
16 #include "components/prefs/pref_service.h"
17
18 namespace {
19
20 // TODO(jkrcal): Make all of this configurable via variations_service.
21
22 // The discount factor for computing the discounted-average metrics. Must be
23 // strictly larger than 0 and strictly smaller than 1!
24 const double kDiscountFactorPerDay = 0.25;
25
26 // Never consider any larger interval than this (so that extreme situations such
27 // as losing your phone or going for a long offline vacation do not skew the
28 // average too much).
29 const double kMaxHours = 7*24;
Bernhard Bauer 2016/09/07 21:31:00 Nit: Space before and after multiplication operato
jkrcal 2016/09/08 05:45:24 Done.
30
31 // Ignore events within |kMinHours| hours since the last event (|kMinHours| is
32 // the length of the browsing session where subsequent events of the same type
33 // do not count again).
34 const double kMinHours = 0.5;
35
36 const char kHistogramAverageHoursToOpenNTP[] =
37 "NewTabPage.UserClassifier.AverageHoursToOpenNTP";
38 const char kHistogramAverageHoursToShowSuggestions[] =
39 "NewTabPage.UserClassifier.AverageHoursToShowSuggestions";
40 const char kHistogramAverageHoursToUseSuggestions[] =
41 "NewTabPage.UserClassifier.AverageHoursToUseSuggestions";
42
43 } // namespace
44
45 namespace ntp_snippets {
46
47 UserClassifier::UserClassifier(PrefService* pref_service)
48 : pref_service_(pref_service) {
49 // Compute the discount_rate_per_hour such that
50 // e^{-discount_rate_per_hour * 24} = (1 - kDiscountFactorPerDay).
51 discount_rate_per_hour_ = std::log(1 / (1 - kDiscountFactorPerDay)) / 24;
52 }
53
54 UserClassifier::~UserClassifier() {}
55
56 // static
57 void UserClassifier::RegisterProfilePrefs(PrefRegistrySimple* registry) {
58 registry->RegisterDoublePref(
59 prefs::kUserClassifierAverageNTPOpenedPerHour, 1);
60 registry->RegisterDoublePref(
61 prefs::kUserClassifierAverageSuggestionsShownPerHour, 1);
62 registry->RegisterDoublePref(
63 prefs::kUserClassifierAverageSuggestionsUsedPerHour, 1);
64
65 registry->RegisterInt64Pref(prefs::kUserClassifierLastTimeToOpenNTP, 0);
66 registry->RegisterInt64Pref(prefs::kUserClassifierLastTimeToShowSuggestions,
67 0);
68 registry->RegisterInt64Pref(prefs::kUserClassifierLastTimeToUseSuggestions,
69 0);
70 }
71
72 void UserClassifier::OnNTPOpened() {
73 UpdateMetricOnEvent(prefs::kUserClassifierAverageNTPOpenedPerHour,
74 prefs::kUserClassifierLastTimeToOpenNTP);
75
76 double avg = GetEstimateHoursBetweenEvents(
77 prefs::kUserClassifierAverageNTPOpenedPerHour);
78 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToOpenNTP, avg, 1,
79 kMaxHours, 50);
80 }
81
82 void UserClassifier::OnSuggestionsShown() {
83 UpdateMetricOnEvent(prefs::kUserClassifierAverageSuggestionsShownPerHour,
84 prefs::kUserClassifierLastTimeToShowSuggestions);
85
86 double avg = GetEstimateHoursBetweenEvents(
87 prefs::kUserClassifierAverageSuggestionsShownPerHour);
88 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToShowSuggestions, avg, 1,
89 kMaxHours, 50);
90 }
91
92 void UserClassifier::OnSuggestionsUsed() {
93 UpdateMetricOnEvent(prefs::kUserClassifierAverageSuggestionsUsedPerHour,
94 prefs::kUserClassifierLastTimeToUseSuggestions);
95
96 double avg = GetEstimateHoursBetweenEvents(
97 prefs::kUserClassifierAverageSuggestionsUsedPerHour);
98 UMA_HISTOGRAM_CUSTOM_COUNTS(kHistogramAverageHoursToUseSuggestions, avg, 1,
99 kMaxHours, 50);
100 }
101
102 void UserClassifier::UpdateMetricOnEvent(const char* metric_pref_name,
103 const char* last_time_pref_name) {
104 if (!pref_service_)
105 return;
106
107 double hours_since_last_time =
108 std::min(kMaxHours, GetHoursSinceLastTime(last_time_pref_name));
109 // Ignore events within the same "browsing session".
110 if (hours_since_last_time < kMinHours)
111 return;
112 SetLastTimeToNow(last_time_pref_name);
113
114 double avg_events_per_hour = pref_service_->GetDouble(metric_pref_name);
115 // Compute and store the new discounted average according to the formula
116 // avg_events := 1 + e^{-discount_rate_per_hour * hours_since} * avg_events.
117 avg_events_per_hour =
Bernhard Bauer 2016/09/07 21:31:00 Maybe use a new variable |new_avg_events_per_hour|
jkrcal 2016/09/08 05:45:24 Done.
118 1 +
119 std::exp(discount_rate_per_hour_ * hours_since_last_time) *
120 avg_events_per_hour;
121 pref_service_->SetDouble(metric_pref_name, avg_events_per_hour);
122 }
123
124 double UserClassifier::GetEstimateHoursBetweenEvents(
125 const char* metric_pref_name) {
126 double avg_events_per_hour = pref_service_->GetDouble(metric_pref_name);
127
128 if (avg_events_per_hour > 1) {
Bernhard Bauer 2016/09/07 21:31:00 Flip the condition and return kMaxHours in the oth
jkrcal 2016/09/08 05:45:24 Done. Yes, it can be equal to 1.
129 // This is the estimate with the assumption that last event happened right
130 // now (for the case when getting the estimate right after the event).
131 // Solve estimate_hours in the equation:
132 // avg_events = 1 + e^{-discount_rate * estimate_hours} * avg_events.
133 return std::min(kMaxHours,
134 std::log(avg_events_per_hour / (avg_events_per_hour - 1)) /
135 discount_rate_per_hour_);
136 } else {
137 return kMaxHours;
138 }
139 }
140
141 double UserClassifier::GetHoursSinceLastTime(
142 const char* last_time_pref_name) {
143 if (!pref_service_->HasPrefPath(last_time_pref_name))
144 return DBL_MAX;
145
146 base::TimeDelta since_last_time =
147 base::Time::Now() - base::Time::FromInternalValue(
148 pref_service_->GetInt64(last_time_pref_name));
149 return since_last_time.InSecondsF() / 3600;
150 }
151
152 void UserClassifier::SetLastTimeToNow(const char* last_time_pref_name) {
153 pref_service_->SetInt64(last_time_pref_name,
154 base::Time::Now().ToInternalValue());
155 }
156
157 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698