Android: add UMA instrumentation for inertial sensors.
[chromium-blink-merge.git] / chrome / browser / net / chrome_network_data_saving_metrics.cc
blob6a71b772176848fbd16291822c1b2e6ab4e7d70e
1 // Copyright 2013 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.
5 #include "chrome/browser/net/chrome_network_data_saving_metrics.h"
7 #include "base/metrics/histogram.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "chrome/common/pref_names.h"
13 #if defined(OS_ANDROID) || defined(OS_IOS)
14 namespace {
16 // The number of days of history stored in the content lengths prefs.
17 const size_t kNumDaysInHistory = 60;
19 // Increments an int64, stored as a string, in a ListPref at the specified
20 // index. The value must already exist and be a string representation of a
21 // number.
22 void AddInt64ToListPref(size_t index,
23 int64 length,
24 base::ListValue* list_update) {
25 int64 value = 0;
26 std::string old_string_value;
27 bool rv = list_update->GetString(index, &old_string_value);
28 DCHECK(rv);
29 if (rv) {
30 rv = base::StringToInt64(old_string_value, &value);
31 DCHECK(rv);
33 value += length;
34 list_update->Set(index, Value::CreateStringValue(base::Int64ToString(value)));
37 int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) {
38 std::string string_value;
39 if (!list_update.GetString(index, &string_value)) {
40 NOTREACHED();
41 return 0;
44 int64 value = 0;
45 bool rv = base::StringToInt64(string_value, &value);
46 DCHECK(rv);
47 return value;
50 // Report UMA metrics for daily data reductions.
51 void RecordDailyContentLengthHistograms(
52 int64 original_length,
53 int64 received_length,
54 int64 original_length_with_data_reduction_enabled,
55 int64 received_length_with_data_reduction_enabled,
56 int64 original_length_via_data_reduction_proxy,
57 int64 received_length_via_data_reduction_proxy) {
58 // Report daily UMA only for days having received content.
59 if (original_length <= 0 || received_length <= 0)
60 return;
62 // Record metrics in KB.
63 UMA_HISTOGRAM_COUNTS(
64 "Net.DailyOriginalContentLength", original_length >> 10);
65 UMA_HISTOGRAM_COUNTS(
66 "Net.DailyContentLength", received_length >> 10);
67 int percent = 0;
68 // UMA percentage cannot be negative.
69 if (original_length > received_length) {
70 percent = (100 * (original_length - received_length)) / original_length;
72 UMA_HISTOGRAM_PERCENTAGE("Net.DailyContentSavingPercent", percent);
74 if (original_length_with_data_reduction_enabled <= 0 ||
75 received_length_with_data_reduction_enabled <= 0) {
76 return;
79 UMA_HISTOGRAM_COUNTS(
80 "Net.DailyOriginalContentLength_DataReductionProxyEnabled",
81 original_length_with_data_reduction_enabled >> 10);
82 UMA_HISTOGRAM_COUNTS(
83 "Net.DailyContentLength_DataReductionProxyEnabled",
84 received_length_with_data_reduction_enabled >> 10);
86 int percent_data_reduction_proxy_enabled = 0;
87 // UMA percentage cannot be negative.
88 if (original_length_with_data_reduction_enabled >
89 received_length_with_data_reduction_enabled) {
90 percent_data_reduction_proxy_enabled =
91 100 * (original_length_with_data_reduction_enabled -
92 received_length_with_data_reduction_enabled) /
93 original_length_with_data_reduction_enabled;
95 UMA_HISTOGRAM_PERCENTAGE(
96 "Net.DailyContentSavingPercent_DataReductionProxyEnabled",
97 percent_data_reduction_proxy_enabled);
99 UMA_HISTOGRAM_PERCENTAGE(
100 "Net.DailyContentPercent_DataReductionProxyEnabled",
101 (100 * received_length_with_data_reduction_enabled) / received_length);
103 if (original_length_via_data_reduction_proxy <= 0 ||
104 received_length_via_data_reduction_proxy <= 0) {
105 return;
108 UMA_HISTOGRAM_COUNTS(
109 "Net.DailyOriginalContentLength_ViaDataReductionProxy",
110 original_length_via_data_reduction_proxy >> 10);
111 UMA_HISTOGRAM_COUNTS(
112 "Net.DailyContentLength_ViaDataReductionProxy",
113 received_length_via_data_reduction_proxy >> 10);
114 int percent_via_data_reduction_proxy = 0;
115 if (original_length_via_data_reduction_proxy >
116 received_length_via_data_reduction_proxy) {
117 percent_via_data_reduction_proxy =
118 100 * (original_length_via_data_reduction_proxy -
119 received_length_via_data_reduction_proxy) /
120 original_length_via_data_reduction_proxy;
122 UMA_HISTOGRAM_PERCENTAGE(
123 "Net.DailyContentSavingPercent_ViaDataReductionProxy",
124 percent_via_data_reduction_proxy);
125 UMA_HISTOGRAM_PERCENTAGE(
126 "Net.DailyContentPercent_ViaDataReductionProxy",
127 (100 * received_length_via_data_reduction_proxy) / received_length);
130 // Ensure list has exactly |length| elements, either by truncating at the
131 // front, or appending "0"'s to the back.
132 void MaintainContentLengthPrefsWindow(base::ListValue* list, size_t length) {
133 // Remove data for old days from the front.
134 while (list->GetSize() > length)
135 list->Remove(0, NULL);
136 // Newly added lists are empty. Add entries to back to fill the window,
137 // each initialized to zero.
138 while (list->GetSize() < length)
139 list->AppendString(base::Int64ToString(0));
140 DCHECK_EQ(length, list->GetSize());
143 // Update list for date change and ensure list has exactly |length| elements.
144 // The last entry in each list will be for the current day after the update.
145 void MaintainContentLengthPrefsForDateChange(
146 base::ListValue* original_update,
147 base::ListValue* received_update,
148 int days_since_last_update) {
149 if (days_since_last_update == -1) {
150 // The system may go backwards in time by up to a day for legitimate
151 // reasons, such as with changes to the time zone. In such cases, we
152 // keep adding to the current day.
153 // Note: we accept the fact that some reported data is shifted to
154 // the adjacent day if users travel back and forth across time zones.
155 days_since_last_update = 0;
156 } else if (days_since_last_update < -1) {
157 // Erase all entries if the system went backwards in time by more than
158 // a day.
159 original_update->Clear();
160 received_update->Clear();
162 days_since_last_update = kNumDaysInHistory;
164 DCHECK_GE(days_since_last_update, 0);
166 // Add entries for days since last update event. This will make the
167 // lists longer than kNumDaysInHistory. The additional items will be cut off
168 // from the head of the lists by |MaintainContentLengthPrefsWindow|, below.
169 for (int i = 0;
170 i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory);
171 ++i) {
172 original_update->AppendString(base::Int64ToString(0));
173 received_update->AppendString(base::Int64ToString(0));
176 // Entries for new days may have been appended. Maintain the invariant that
177 // there should be exactly |kNumDaysInHistory| days in the histories.
178 MaintainContentLengthPrefsWindow(original_update, kNumDaysInHistory);
179 MaintainContentLengthPrefsWindow(received_update, kNumDaysInHistory);
182 // DailyDataSavingUpdate maintains a pair of data saving prefs, original_update_
183 // and received_update_. pref_original is a list of |kNumDaysInHistory| elements
184 // of daily total original content lengths for the past |kNumDaysInHistory|
185 // days. pref_received is the corresponding list of the daily total received
186 // content lengths.
187 class DailyDataSavingUpdate {
188 public:
189 DailyDataSavingUpdate(
190 const char* pref_original, const char* pref_received,
191 PrefService* pref_service)
192 : pref_original_(pref_original),
193 pref_received_(pref_received),
194 original_update_(pref_service, pref_original_),
195 received_update_(pref_service, pref_received_) {
198 void UpdateForDataChange(int days_since_last_update) {
199 // New empty lists may have been created. Maintain the invariant that
200 // there should be exactly |kNumDaysInHistory| days in the histories.
201 MaintainContentLengthPrefsWindow(original_update_.Get(), kNumDaysInHistory);
202 MaintainContentLengthPrefsWindow(received_update_.Get(), kNumDaysInHistory);
203 if (days_since_last_update) {
204 MaintainContentLengthPrefsForDateChange(
205 original_update_.Get(), received_update_.Get(),
206 days_since_last_update);
210 // Update the lengths for the current day.
211 void Add(int original_content_length, int received_content_length) {
212 AddInt64ToListPref(
213 kNumDaysInHistory - 1, original_content_length, original_update_.Get());
214 AddInt64ToListPref(
215 kNumDaysInHistory - 1, received_content_length, received_update_.Get());
218 int64 GetOriginalListPrefValue(size_t index) {
219 return ListPrefInt64Value(*original_update_, index);
221 int64 GetReceivedListPrefValue(size_t index) {
222 return ListPrefInt64Value(*received_update_, index);
225 private:
226 const char* pref_original_;
227 const char* pref_received_;
228 ListPrefUpdate original_update_;
229 ListPrefUpdate received_update_;
232 } // namespace
233 #endif // defined(OS_ANDROID) || defined(OS_IOS)
235 namespace chrome_browser_net {
237 #if defined(OS_ANDROID) || defined(OS_IOS)
238 void UpdateContentLengthPrefsForDataReductionProxy(
239 int received_content_length, int original_content_length,
240 bool with_data_reduction_proxy_enabled, bool via_data_reduction_proxy,
241 base::Time now, PrefService* prefs) {
242 // TODO(bengr): Remove this check once the underlying cause of
243 // http://crbug.com/287821 is fixed. For now, only continue if the current
244 // year is reported as being between 1972 and 2970.
245 base::TimeDelta time_since_unix_epoch = now - base::Time::UnixEpoch();
246 const int kMinDaysSinceUnixEpoch = 365 * 2; // 2 years.
247 const int kMaxDaysSinceUnixEpoch = 365 * 1000; // 1000 years.
248 if (time_since_unix_epoch.InDays() < kMinDaysSinceUnixEpoch ||
249 time_since_unix_epoch.InDays() > kMaxDaysSinceUnixEpoch) {
250 return;
253 // Determine how many days it has been since the last update.
254 int64 then_internal = prefs->GetInt64(
255 prefs::kDailyHttpContentLengthLastUpdateDate);
256 // Local midnight could have been shifted due to time zone change.
257 base::Time then_midnight =
258 base::Time::FromInternalValue(then_internal).LocalMidnight();
259 base::Time midnight = now.LocalMidnight();
260 int days_since_last_update = (midnight - then_midnight).InDays();
262 // Each day, we calculate the total number of bytes received and the total
263 // size of all corresponding resources before any data-reducing recompression
264 // is applied. These values are used to compute the data savings realized
265 // by applying our compression techniques. Totals for the last
266 // |kNumDaysInHistory| days are maintained.
267 DailyDataSavingUpdate total(
268 prefs::kDailyHttpOriginalContentLength,
269 prefs::kDailyHttpReceivedContentLength,
270 prefs);
271 total.UpdateForDataChange(days_since_last_update);
273 DailyDataSavingUpdate proxy_enabled(
274 prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled,
275 prefs::kDailyContentLengthWithDataReductionProxyEnabled,
276 prefs);
277 proxy_enabled.UpdateForDataChange(days_since_last_update);
279 DailyDataSavingUpdate via_proxy(
280 prefs::kDailyOriginalContentLengthViaDataReductionProxy,
281 prefs::kDailyContentLengthViaDataReductionProxy,
282 prefs);
283 via_proxy.UpdateForDataChange(days_since_last_update);
285 total.Add(original_content_length, received_content_length);
286 if (with_data_reduction_proxy_enabled) {
287 proxy_enabled.Add(original_content_length, received_content_length);
288 // Ignore cases, if exist, when
289 // "with_data_reduction_proxy_enabled == false", and
290 // "via_data_reduction_proxy == true"
291 if (via_data_reduction_proxy) {
292 via_proxy.Add(original_content_length, received_content_length);
296 if (days_since_last_update) {
297 // Record the last update time in microseconds in UTC.
298 prefs->SetInt64(prefs::kDailyHttpContentLengthLastUpdateDate,
299 midnight.ToInternalValue());
301 // A new day. Report the previous day's data if exists. We'll lose usage
302 // data if the last time Chrome was run was more than a day ago.
303 // Here, we prefer collecting less data but the collected data is
304 // associated with an accurate date.
305 if (days_since_last_update == 1) {
306 // The previous day's data point is the second one from the tail.
307 RecordDailyContentLengthHistograms(
308 total.GetOriginalListPrefValue(kNumDaysInHistory - 2),
309 total.GetReceivedListPrefValue(kNumDaysInHistory - 2),
310 proxy_enabled.GetOriginalListPrefValue(kNumDaysInHistory - 2),
311 proxy_enabled.GetReceivedListPrefValue(kNumDaysInHistory - 2),
312 via_proxy.GetOriginalListPrefValue(kNumDaysInHistory - 2),
313 via_proxy.GetReceivedListPrefValue(kNumDaysInHistory - 2));
317 #endif // defined(OS_ANDROID) || defined(OS_IOS)
319 void UpdateContentLengthPrefs(
320 int received_content_length, int original_content_length,
321 bool with_data_reduction_proxy_enabled, bool via_data_reduction_proxy,
322 PrefService* prefs) {
323 int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
324 int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
325 total_received += received_content_length;
326 total_original += original_content_length;
327 prefs->SetInt64(prefs::kHttpReceivedContentLength, total_received);
328 prefs->SetInt64(prefs::kHttpOriginalContentLength, total_original);
330 #if defined(OS_ANDROID) || defined(OS_IOS)
331 UpdateContentLengthPrefsForDataReductionProxy(
332 received_content_length,
333 original_content_length,
334 with_data_reduction_proxy_enabled,
335 via_data_reduction_proxy,
336 base::Time::Now(),
337 prefs);
338 #endif // defined(OS_ANDROID) || defined(OS_IOS)
342 } // namespace chrome_browser_net