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

Unified 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, 7 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
Index: chrome/installer/util/experiment.cc
diff --git a/chrome/installer/util/experiment.cc b/chrome/installer/util/experiment.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8a3ce7ba9b35a5cc77909c235d8e345152d79f7b
--- /dev/null
+++ b/chrome/installer/util/experiment.cc
@@ -0,0 +1,186 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/installer/util/experiment.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+
+namespace installer {
+
+// 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.
+static double LogFloor(double x, double b) {
+ return std::round(std::log(x) / std::log(b));
+}
+
+// Returns the base to use for exponential buckets so that buckets
+// 0,1,.. 2^|bits|-1 cover range [0, max_val]. If this function return b
+// then Bucket value i will store values from [b^i, b^(i+1)]
+static double ExpBucketBase(int max_val, int bits) {
+ return std::exp(std::log(max_val - 1) / (1 << bits));
+}
+
+// Invert bucket to the approximate value that the bucket may correspond to.
+static int BucketToValue(int bucket, double bucket_base) {
+ return static_cast<int>(std::round(std::pow(bucket_base, bucket) - 1));
+}
+
+Experiment::Experiment() = default;
+Experiment::Experiment(Experiment&&) = default;
+Experiment::Experiment(const Experiment&) = default;
+Experiment::~Experiment() = default;
+
+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.
+ *this = Experiment();
+ metrics_ = metrics;
+ state_ = metrics.state;
+ group_ = metrics.group;
+ toast_location_ = metrics.toast_location;
+ toast_count_ = metrics.toast_count;
+ if (metrics_.last_used_bucket > 0) {
+ double log_base = ExpBucketBase(ExperimentMetrics::kMaxLastUsed,
+ ExperimentMetrics::kLastUsedBucketBits);
+ inactive_days_ = BucketToValue(metrics_.last_used_bucket, log_base);
+ if (inactive_days_ > ExperimentMetrics::kMaxLastUsed) {
+ inactive_days_ = ExperimentMetrics::kMaxLastUsed;
+ }
+ }
+ if (metrics_.session_length_bucket > 0) {
+ double log_base = ExpBucketBase(ExperimentMetrics::kMaxSessionLength,
+ ExperimentMetrics::kSessionLengthBits);
+ user_session_uptime_ = base::TimeDelta::FromMinutes(
+ BucketToValue(metrics_.session_length_bucket, log_base));
+ if (user_session_uptime_.InMinutes() >
+ ExperimentMetrics::kMaxSessionLength) {
+ user_session_uptime_ =
+ base::TimeDelta::FromMinutes(ExperimentMetrics::kMaxSessionLength);
+ }
+ }
+
+ if (metrics_.display_time_bucket > 0) {
+ double log_base = ExpBucketBase(ExperimentMetrics::kMaxDisplayTime,
+ ExperimentMetrics::kDisplayTimeBucketBits);
+ action_delay_ = base::TimeDelta::FromSeconds(
+ BucketToValue(metrics_.display_time_bucket, log_base));
+ if (action_delay_.InSeconds() > ExperimentMetrics::kMaxDisplayTime) {
+ action_delay_ =
+ base::TimeDelta::FromSeconds(ExperimentMetrics::kMaxDisplayTime);
+ }
+ }
+
+ if (metrics_.first_toast_offset > 0) {
+ // Accurate time information is not kept in |metrics|. Reconstruct
+ // the toast display time to the closest day.
+ first_display_time_ =
+ (base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(
+ ExperimentMetrics::kExperimentStartSeconds) +
+ base::TimeDelta::FromDays(metrics_.first_toast_offset));
+ DCHECK_LE(metrics_.first_toast_offset,
+ ExperimentMetrics::kExperimentStartSeconds);
+ }
+ // Latest display time is not stored in experiment metrics. So, it will
+ // be initialized to be same as |first_display_time_| for now.
+ latest_display_time_ = first_display_time_;
+}
+
+void Experiment::SetState(ExperimentMetrics::State state) {
+ state_ = state;
+ 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.
+}
+
+void Experiment::AssignGroup(int group) {
+ DCHECK_GE(group, 0);
+ DCHECK_LT(group, ExperimentMetrics::kNumGroups);
+ DCHECK(metrics_.InInitialState());
+
+ group_ = group;
+ metrics_.group = group;
+ SetState(ExperimentMetrics::kGroupAssigned);
+}
+
+void Experiment::SetToastLocation(ExperimentMetrics::ToastLocation location) {
+ DCHECK(!metrics_.InTerminalState());
+ DCHECK(!metrics_.InInitialState());
+ toast_location_ = location;
+ metrics_.toast_location = location;
+}
+
+void Experiment::SetInactiveDays(int days) {
+ DCHECK(!metrics_.InTerminalState());
+ DCHECK(!metrics_.InInitialState());
+ DCHECK_GE(days, 0);
+ inactive_days_ = days;
+ double log_base = ExpBucketBase(ExperimentMetrics::kMaxLastUsed,
+ ExperimentMetrics::kLastUsedBucketBits);
+ 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.
+ if (days > ExperimentMetrics::kMaxLastUsed) {
+ metrics_.last_used_bucket =
+ LogFloor(1 + ExperimentMetrics::kMaxLastUsed, log_base);
+ }
+}
+
+void Experiment::SetToastCount(int count) {
+ DCHECK(!metrics_.InTerminalState());
+ DCHECK(!metrics_.InInitialState());
+ toast_count_ = count;
+ 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.
+ if (count > ExperimentMetrics::kMaxToastCount) {
+ metrics_.toast_count = ExperimentMetrics::kMaxToastCount;
+ }
+}
+
+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.
+ DCHECK(!metrics_.InTerminalState());
+ DCHECK(!metrics_.InInitialState());
+ if (metrics_.first_toast_offset == 0) {
+ // This is the first time toast is shown so add user to today's cohort.
+ first_display_time_ = time;
+ metrics_.first_toast_offset =
+ (time - base::Time::UnixEpoch() -
+ base::TimeDelta::FromSeconds(
+ ExperimentMetrics::kExperimentStartSeconds))
+ .InDays();
+ if (metrics_.first_toast_offset > ExperimentMetrics::kMaxFirstToastOffset ||
+ metrics_.first_toast_offset < 0) {
+ // First display time is outside the experiment range. Invalid local time.
+ // Reset to highest value of first display time.
+ metrics_.first_toast_offset = ExperimentMetrics::kMaxFirstToastOffset;
+ }
+ }
+ latest_display_time_ = time;
+ metrics_.toast_hour = (time - time.LocalMidnight()).InHours();
+ DCHECK_LE(metrics_.toast_hour, 24);
+ DCHECK_GE(metrics_.toast_hour, 0);
+}
+
+void Experiment::SetUserSessionUptime(const base::TimeDelta& time_delta) {
+ DCHECK(!metrics_.InTerminalState());
+ DCHECK(!metrics_.InInitialState());
+ user_session_uptime_ = time_delta;
+ double log_base = ExpBucketBase(ExperimentMetrics::kMaxSessionLength,
+ ExperimentMetrics::kSessionLengthBits);
+ metrics_.session_length_bucket =
+ LogFloor(1 + time_delta.InMinutes(), log_base);
+ if (time_delta.InMinutes() > ExperimentMetrics::kMaxSessionLength) {
+ metrics_.session_length_bucket =
+ LogFloor(1 + ExperimentMetrics::kMaxSessionLength, log_base);
+ }
+}
+
+void Experiment::SetActionDelay(const base::TimeDelta& time_delta) {
+ DCHECK(!metrics_.InTerminalState());
+ DCHECK(!metrics_.InInitialState());
+ action_delay_ = time_delta;
+ double log_base = ExpBucketBase(ExperimentMetrics::kMaxDisplayTime,
+ ExperimentMetrics::kDisplayTimeBucketBits);
+ metrics_.display_time_bucket = LogFloor(1 + time_delta.InSeconds(), log_base);
+ if (time_delta.InSeconds() > ExperimentMetrics::kMaxDisplayTime) {
+ metrics_.display_time_bucket =
+ LogFloor(1 + ExperimentMetrics::kMaxDisplayTime, log_base);
+ }
+}
+
+} // namespace installer

Powered by Google App Engine
This is Rietveld 408576698