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

Side by Side Diff: components/metrics/data_use_tracker.cc

Issue 1818613002: Implement UMA log throttling for cellular connections (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nits Created 4 years, 8 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/metrics/data_use_tracker.h"
6
7 #include <string>
8
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/metrics/metrics_pref_names.h"
12 #include "components/prefs/scoped_user_pref_update.h"
13 #include "components/variations/variations_associated_data.h"
14
15 namespace metrics {
16
17 namespace {
18
19 // This function is for forwarding metrics usage pref changes to the appropriate
20 // callback on the appropriate thread.
21 void UpdateMetricsUsagePrefs(
22 const UpdateUsagePrefCallbackType& update_on_ui_callback,
23 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
24 const std::string& service_name,
25 int message_size,
26 bool is_cellular) {
27 ui_task_runner->PostTask(
28 FROM_HERE, base::Bind(update_on_ui_callback, service_name, message_size,
29 is_cellular));
30 }
31
32 } // namespace
33
34 DataUseTracker::DataUseTracker(PrefService* local_state)
35 : local_state_(local_state), weak_ptr_factory_(this) {}
36
37 DataUseTracker::~DataUseTracker() {}
38
39 // static
40 void DataUseTracker::RegisterPrefs(PrefRegistrySimple* registry) {
41 registry->RegisterDictionaryPref(metrics::prefs::kUserCellDataUse);
42 registry->RegisterDictionaryPref(metrics::prefs::kUmaCellDataUse);
43 }
44
45 UpdateUsagePrefCallbackType DataUseTracker::GetDataUseForwardingCallback(
46 scoped_refptr<base::SequencedTaskRunner> ui_task_runner) {
47 DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
48
49 return base::Bind(
50 &UpdateMetricsUsagePrefs,
51 base::Bind(&DataUseTracker::UpdateMetricsUsagePrefsOnUIThread,
52 weak_ptr_factory_.GetWeakPtr()),
53 ui_task_runner);
54 }
55
56 bool DataUseTracker::ShouldUploadLogOnCellular(int log_bytes) {
57 DCHECK(thread_checker_.CalledOnValidThread());
58
59 RemoveExpiredEntries();
60
61 int uma_weekly_quota_bytes;
62 if (!GetUmaWeeklyQuota(&uma_weekly_quota_bytes))
63 return true;
64
65 int uma_total_data_use = ComputeTotalDataUse(prefs::kUmaCellDataUse);
66 int new_uma_total_data_use = log_bytes + uma_total_data_use;
67 // If the new log doesn't increase the total UMA traffic to be above the
68 // allowed quota then the log should be uploaded.
69 if (new_uma_total_data_use <= uma_weekly_quota_bytes)
70 return true;
71
72 double uma_ratio;
73 if (!GetUmaRatio(&uma_ratio))
74 return true;
75
76 int user_total_data_use = ComputeTotalDataUse(prefs::kUserCellDataUse);
77 // If after adding the new log the uma ratio is still under the allowed ratio
78 // then the log should be uploaded and vice versa.
79 return new_uma_total_data_use /
80 static_cast<double>(log_bytes + user_total_data_use) <=
81 uma_ratio;
82 }
83
84 void DataUseTracker::UpdateMetricsUsagePrefsOnUIThread(
85 const std::string& service_name,
86 int message_size,
87 bool is_celllular) {
88 DCHECK(thread_checker_.CalledOnValidThread());
89
90 if (!is_celllular)
91 return;
92
93 UpdateUsagePref(prefs::kUserCellDataUse, message_size);
94 if (service_name == "UMA")
95 UpdateUsagePref(prefs::kUmaCellDataUse, message_size);
96 }
97
98 void DataUseTracker::UpdateUsagePref(const std::string& pref_name,
99 int message_size) {
100 DCHECK(thread_checker_.CalledOnValidThread());
101
102 DictionaryPrefUpdate pref_updater(local_state_, pref_name);
103 int todays_traffic = 0;
104 std::string todays_key = GetCurrentMeasurementDateAsString();
105
106 const base::DictionaryValue* user_pref_dict =
107 local_state_->GetDictionary(pref_name);
108 user_pref_dict->GetInteger(todays_key, &todays_traffic);
109 pref_updater->SetInteger(todays_key, todays_traffic + message_size);
110 }
111
112 void DataUseTracker::RemoveExpiredEntries() {
113 DCHECK(thread_checker_.CalledOnValidThread());
114 RemoveExpiredEntriesForPref(prefs::kUmaCellDataUse);
115 RemoveExpiredEntriesForPref(prefs::kUserCellDataUse);
116 }
117
118 void DataUseTracker::RemoveExpiredEntriesForPref(const std::string& pref_name) {
119 DCHECK(thread_checker_.CalledOnValidThread());
120
121 const base::DictionaryValue* user_pref_dict =
122 local_state_->GetDictionary(pref_name);
123 const base::Time current_date = GetCurrentMeasurementDate();
124 const base::Time week_ago = current_date - base::TimeDelta::FromDays(7);
125
126 base::DictionaryValue user_pref_new_dict;
127 for (base::DictionaryValue::Iterator it(*user_pref_dict); !it.IsAtEnd();
128 it.Advance()) {
129 base::Time key_date;
130 base::Time::FromUTCString(it.key().c_str(), &key_date);
131 if (key_date > week_ago)
132 user_pref_new_dict.Set(it.key(), it.value().CreateDeepCopy());
133 }
134 local_state_->Set(pref_name, user_pref_new_dict);
135 }
136
137 int DataUseTracker::ComputeTotalDataUse(std::string pref_name) {
138 DCHECK(thread_checker_.CalledOnValidThread());
139
140 int total_data_use = 0;
141 const base::DictionaryValue* pref_dict =
142 local_state_->GetDictionary(pref_name);
143 for (base::DictionaryValue::Iterator it(*pref_dict); !it.IsAtEnd();
144 it.Advance()) {
145 int value = 0;
146 it.value().GetAsInteger(&value);
147 total_data_use += value;
148 }
149 return total_data_use;
150 }
151
152 bool DataUseTracker::GetUmaWeeklyQuota(int* uma_weekly_quota_bytes) {
153 DCHECK(thread_checker_.CalledOnValidThread());
154
155 std::string param_value_str = variations::GetVariationParamValue(
156 "UMA_EnableCellularLogUpload", "Uma_Quota");
157 if (param_value_str.empty())
158 return false;
159
160 base::StringToInt(param_value_str, uma_weekly_quota_bytes);
161 return true;
162 }
163
164 bool DataUseTracker::GetUmaRatio(double* ratio) {
165 DCHECK(thread_checker_.CalledOnValidThread());
166
167 std::string param_value_str = variations::GetVariationParamValue(
168 "UMA_EnableCellularLogUpload", "Uma_Ratio");
169 if (param_value_str.empty())
170 return false;
171 base::StringToDouble(param_value_str, ratio);
172 return true;
173 }
174
175 base::Time DataUseTracker::GetCurrentMeasurementDate() {
176 return base::Time::Now().LocalMidnight();
177 }
178
179 std::string DataUseTracker::GetCurrentMeasurementDateAsString() {
180 DCHECK(thread_checker_.CalledOnValidThread());
181
182 base::Time::Exploded today_exploded;
183 GetCurrentMeasurementDate().LocalExplode(&today_exploded);
184 return base::StringPrintf("%04d-%02d-%02d", today_exploded.year,
185 today_exploded.month, today_exploded.day_of_month);
186 }
187
188 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698