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

Side by Side Diff: chrome/installer/util/experiment.cc

Issue 2889323004: Win 10 Inactive toast experiment metrics and storage modifications. (Closed)
Patch Set: Incorporate review comments Created 3 years, 6 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 2017 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 "chrome/installer/util/experiment.h"
6
7 #include <cmath>
8
9 #include "base/logging.h"
10
11 namespace installer {
12
13 // Returns closest integer of logarithm of |x| with base |b|.
grt (UTC plus 2) 2017/05/31 12:24:09 put these helpers in an unnamed namespace (and dro
nikunjb 2017/06/02 05:11:22 Done.
14 static double LogFloor(double x, double b) {
15 return std::round(std::log(x) / std::log(b));
16 }
17
18 // Returns the base to use for exponential buckets so that buckets
19 // 0,1,.. 2^|bits|-1 cover range [0, max_val]. If this function return b
20 // then Bucket value i will store values from [b^i, b^(i+1)]
21 static double ExpBucketBase(int max_val, int bits) {
22 return std::exp(std::log(max_val - 1) / (1 << bits));
23 }
24
25 // Invert bucket to the approximate value that the bucket may correspond to.
26 static int BucketToValue(int bucket, double bucket_base) {
27 return static_cast<int>(std::round(std::pow(bucket_base, bucket) - 1));
28 }
29
30 Experiment::Experiment() = default;
31 Experiment::Experiment(Experiment&&) = default;
32 Experiment::Experiment(const Experiment&) = default;
33 Experiment::~Experiment() = default;
34
35 void Experiment::InitializeFromMetrics(const ExperimentMetrics& metrics) {
grt (UTC plus 2) 2017/05/31 12:24:09 this will only be called when |metrics| is in an i
nikunjb 2017/06/02 05:11:22 Done.
36 *this = Experiment();
37 metrics_ = metrics;
38 state_ = metrics.state;
39 group_ = metrics.group;
40 toast_location_ = metrics.toast_location;
41 toast_count_ = metrics.toast_count;
42 if (metrics_.last_used_bucket > 0) {
43 double log_base = ExpBucketBase(ExperimentMetrics::kMaxLastUsed,
44 ExperimentMetrics::kLastUsedBucketBits);
45 inactive_days_ = BucketToValue(metrics_.last_used_bucket, log_base);
46 if (inactive_days_ > ExperimentMetrics::kMaxLastUsed) {
47 inactive_days_ = ExperimentMetrics::kMaxLastUsed;
48 }
49 }
50 if (metrics_.session_length_bucket > 0) {
51 double log_base = ExpBucketBase(ExperimentMetrics::kMaxSessionLength,
52 ExperimentMetrics::kSessionLengthBits);
53 user_session_uptime_ = base::TimeDelta::FromMinutes(
54 BucketToValue(metrics_.session_length_bucket, log_base));
55 if (user_session_uptime_.InMinutes() >
56 ExperimentMetrics::kMaxSessionLength) {
57 user_session_uptime_ =
58 base::TimeDelta::FromMinutes(ExperimentMetrics::kMaxSessionLength);
59 }
60 }
61
62 if (metrics_.display_time_bucket > 0) {
63 double log_base = ExpBucketBase(ExperimentMetrics::kMaxDisplayTime,
64 ExperimentMetrics::kDisplayTimeBucketBits);
65 action_delay_ = base::TimeDelta::FromSeconds(
66 BucketToValue(metrics_.display_time_bucket, log_base));
67 if (action_delay_.InSeconds() > ExperimentMetrics::kMaxDisplayTime) {
68 action_delay_ =
69 base::TimeDelta::FromSeconds(ExperimentMetrics::kMaxDisplayTime);
70 }
71 }
72
73 if (metrics_.first_toast_offset > 0) {
74 // Accurate time information is not kept in |metrics|. Reconstruct
75 // the toast display time to the closest day.
76 first_display_time_ =
77 (base::Time::UnixEpoch() +
78 base::TimeDelta::FromSeconds(
79 ExperimentMetrics::kExperimentStartSeconds) +
80 base::TimeDelta::FromDays(metrics_.first_toast_offset));
81 DCHECK_LE(metrics_.first_toast_offset,
82 ExperimentMetrics::kExperimentStartSeconds);
83 }
84 // Latest display time is not stored in experiment metrics. So, it will
85 // be initialized to be same as |first_display_time_| for now.
86 latest_display_time_ = first_display_time_;
87 }
88
89 void Experiment::SetState(ExperimentMetrics::State state) {
90 state_ = state;
91 metrics_.SetState(state);
grt (UTC plus 2) 2017/05/31 12:24:09 may has well drop this setter and use metrics_.sta
nikunjb 2017/06/02 05:11:22 Done.
92 }
93
94 void Experiment::AssignGroup(int group) {
95 DCHECK_GE(group, 0);
96 DCHECK_LT(group, ExperimentMetrics::kNumGroups);
97 DCHECK(metrics_.InInitialState());
98
99 group_ = group;
100 metrics_.group = group;
101 SetState(ExperimentMetrics::kGroupAssigned);
102 }
103
104 void Experiment::SetToastLocation(ExperimentMetrics::ToastLocation location) {
105 DCHECK(!metrics_.InTerminalState());
106 DCHECK(!metrics_.InInitialState());
107 toast_location_ = location;
108 metrics_.toast_location = location;
109 }
110
111 void Experiment::SetInactiveDays(int days) {
112 DCHECK(!metrics_.InTerminalState());
113 DCHECK(!metrics_.InInitialState());
114 DCHECK_GE(days, 0);
115 inactive_days_ = days;
116 double log_base = ExpBucketBase(ExperimentMetrics::kMaxLastUsed,
117 ExperimentMetrics::kLastUsedBucketBits);
118 metrics_.last_used_bucket = LogFloor(1 + days, log_base);
grt (UTC plus 2) 2017/05/31 12:24:09 how about: LogFloor(std::min(days, ExperimentMet
nikunjb 2017/06/02 05:11:22 Done.
119 if (days > ExperimentMetrics::kMaxLastUsed) {
120 metrics_.last_used_bucket =
121 LogFloor(1 + ExperimentMetrics::kMaxLastUsed, log_base);
122 }
123 }
124
125 void Experiment::SetToastCount(int count) {
126 DCHECK(!metrics_.InTerminalState());
127 DCHECK(!metrics_.InInitialState());
128 toast_count_ = count;
129 metrics_.toast_count = count;
grt (UTC plus 2) 2017/05/31 12:24:09 std::min(count, ExperimentMetrics::kMaxToastCount)
nikunjb 2017/06/02 05:11:22 Done.
130 if (count > ExperimentMetrics::kMaxToastCount) {
131 metrics_.toast_count = ExperimentMetrics::kMaxToastCount;
132 }
133 }
134
135 void Experiment::SetDisplayTime(const base::Time& time) {
grt (UTC plus 2) 2017/05/31 12:24:09 Time and TimeTicks should be passed by value rathe
nikunjb 2017/06/02 05:11:22 Done.
136 DCHECK(!metrics_.InTerminalState());
137 DCHECK(!metrics_.InInitialState());
138 if (metrics_.first_toast_offset == 0) {
139 // This is the first time toast is shown so add user to today's cohort.
140 first_display_time_ = time;
141 metrics_.first_toast_offset =
142 (time - base::Time::UnixEpoch() -
143 base::TimeDelta::FromSeconds(
144 ExperimentMetrics::kExperimentStartSeconds))
145 .InDays();
146 if (metrics_.first_toast_offset > ExperimentMetrics::kMaxFirstToastOffset ||
147 metrics_.first_toast_offset < 0) {
148 // First display time is outside the experiment range. Invalid local time.
149 // Reset to highest value of first display time.
150 metrics_.first_toast_offset = ExperimentMetrics::kMaxFirstToastOffset;
151 }
152 }
153 latest_display_time_ = time;
154 metrics_.toast_hour = (time - time.LocalMidnight()).InHours();
155 DCHECK_LE(metrics_.toast_hour, 24);
156 DCHECK_GE(metrics_.toast_hour, 0);
157 }
158
159 void Experiment::SetUserSessionUptime(const base::TimeDelta& time_delta) {
160 DCHECK(!metrics_.InTerminalState());
161 DCHECK(!metrics_.InInitialState());
162 user_session_uptime_ = time_delta;
163 double log_base = ExpBucketBase(ExperimentMetrics::kMaxSessionLength,
164 ExperimentMetrics::kSessionLengthBits);
165 metrics_.session_length_bucket =
166 LogFloor(1 + time_delta.InMinutes(), log_base);
167 if (time_delta.InMinutes() > ExperimentMetrics::kMaxSessionLength) {
168 metrics_.session_length_bucket =
169 LogFloor(1 + ExperimentMetrics::kMaxSessionLength, log_base);
170 }
171 }
172
173 void Experiment::SetActionDelay(const base::TimeDelta& time_delta) {
174 DCHECK(!metrics_.InTerminalState());
175 DCHECK(!metrics_.InInitialState());
176 action_delay_ = time_delta;
177 double log_base = ExpBucketBase(ExperimentMetrics::kMaxDisplayTime,
178 ExperimentMetrics::kDisplayTimeBucketBits);
179 metrics_.display_time_bucket = LogFloor(1 + time_delta.InSeconds(), log_base);
180 if (time_delta.InSeconds() > ExperimentMetrics::kMaxDisplayTime) {
181 metrics_.display_time_bucket =
182 LogFloor(1 + ExperimentMetrics::kMaxDisplayTime, log_base);
183 }
184 }
185
186 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698