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

Side by Side Diff: chrome/browser/android/data_usage/external_data_use_observer.cc

Issue 1491793002: Add histograms for ExternalDataUseObserver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 5 years 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/data_usage/external_data_use_observer.h" 5 #include "chrome/browser/android/data_usage/external_data_use_observer.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/containers/hash_tables.h" 9 #include "base/containers/hash_tables.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/field_trial.h" 11 #include "base/metrics/field_trial.h"
12 #include "base/single_thread_task_runner.h" 12 #include "base/metrics/histogram_base.h"
13 #include "base/metrics/histogram_macros.h"
13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
14 #include "chrome/browser/android/data_usage/data_use_tab_model.h" 15 #include "chrome/browser/android/data_usage/data_use_tab_model.h"
15 #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h" 16 #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h"
16 #include "components/data_usage/core/data_use.h" 17 #include "components/data_usage/core/data_use.h"
17 #include "components/variations/variations_associated_data.h" 18 #include "components/variations/variations_associated_data.h"
18 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
19 20
21 namespace chrome {
22
23 namespace android {
24
20 namespace { 25 namespace {
21 26
27 // Record the result of data use report submission. |bytes| is the sum of send
28 // and received bytes in the report.
29 void RecordDataUsageReportSubmission(
30 ExternalDataUseObserver::DataUsageReportSubmissionResult result,
31 int64_t bytes) {
32 DCHECK_LE(0, bytes);
33 UMA_HISTOGRAM_ENUMERATION(
34 "DataUsage.ReportSubmissionResult", result,
35 ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_MAX);
36 // Cap to the maximum sample value.
37 const int32_t bytes_capped = bytes <= base::HistogramBase::kSampleType_MAX - 1
38 ? bytes
39 : base::HistogramBase::kSampleType_MAX - 1;
40 switch (result) {
41 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL:
42 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Successful",
43 bytes_capped);
44 break;
45 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_FAILED:
46 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Failed",
47 bytes_capped);
48 break;
49 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT:
50 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.TimedOut",
51 bytes_capped);
52 break;
53 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_LOST:
54 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Lost",
55 bytes_capped);
56 break;
57 default:
58 NOTIMPLEMENTED();
59 break;
60 }
61 }
62
22 // Default duration after which matching rules are periodically fetched. May be 63 // Default duration after which matching rules are periodically fetched. May be
23 // overridden by the field trial. 64 // overridden by the field trial.
24 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes. 65 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes.
25 66
67 // Default duration after which a pending data use report is considered timed
68 // out. May be overridden by the field trial.
69 const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes.
70
26 // Default value of the minimum number of bytes that should be buffered before 71 // Default value of the minimum number of bytes that should be buffered before
27 // a data use report is submitted. May be overridden by the field trial. 72 // a data use report is submitted. May be overridden by the field trial.
28 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB. 73 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB.
29 74
30 // Populates various parameters from the values specified in the field trial. 75 // Populates various parameters from the values specified in the field trial.
31 int32_t GetFetchMatchingRulesDurationSeconds() { 76 int32_t GetFetchMatchingRulesDurationSeconds() {
32 int32_t duration_seconds = -1; 77 int32_t duration_seconds = -1;
33 std::string variation_value = variations::GetVariationParamValue( 78 const std::string variation_value = variations::GetVariationParamValue(
34 chrome::android::ExternalDataUseObserver:: 79 chrome::android::ExternalDataUseObserver::
35 kExternalDataUseObserverFieldTrial, 80 kExternalDataUseObserverFieldTrial,
36 "fetch_matching_rules_duration_seconds"); 81 "fetch_matching_rules_duration_seconds");
37 if (!variation_value.empty() && 82 if (!variation_value.empty() &&
38 base::StringToInt(variation_value, &duration_seconds)) { 83 base::StringToInt(variation_value, &duration_seconds)) {
39 DCHECK_LE(0, duration_seconds); 84 DCHECK_LE(0, duration_seconds);
40 return duration_seconds; 85 return duration_seconds;
41 } 86 }
42 return kDefaultFetchMatchingRulesDurationSeconds; 87 return kDefaultFetchMatchingRulesDurationSeconds;
43 } 88 }
44 89
45 // Populates various parameters from the values specified in the field trial. 90 // Populates various parameters from the values specified in the field trial.
91 int32_t GetDataReportSubmitTimeoutMsec() {
92 int32_t duration_seconds = -1;
93 const std::string variation_value = variations::GetVariationParamValue(
94 chrome::android::ExternalDataUseObserver::
95 kExternalDataUseObserverFieldTrial,
96 "data_report_submit_timeout_msec");
97 if (!variation_value.empty() &&
98 base::StringToInt(variation_value, &duration_seconds)) {
99 DCHECK_LE(0, duration_seconds);
100 return duration_seconds;
101 }
102 return kDefaultDataUseReportSubmitTimeoutMsec;
103 }
104
105 // Populates various parameters from the values specified in the field trial.
46 int64_t GetMinBytes() { 106 int64_t GetMinBytes() {
47 int64_t min_bytes = -1; 107 int64_t min_bytes = -1;
48 std::string variation_value = variations::GetVariationParamValue( 108 const std::string variation_value = variations::GetVariationParamValue(
49 chrome::android::ExternalDataUseObserver:: 109 chrome::android::ExternalDataUseObserver::
50 kExternalDataUseObserverFieldTrial, 110 kExternalDataUseObserverFieldTrial,
51 "data_use_report_min_bytes"); 111 "data_use_report_min_bytes");
52 if (!variation_value.empty() && 112 if (!variation_value.empty() &&
53 base::StringToInt64(variation_value, &min_bytes)) { 113 base::StringToInt64(variation_value, &min_bytes)) {
54 DCHECK_LE(0, min_bytes); 114 DCHECK_LE(0, min_bytes);
55 return min_bytes; 115 return min_bytes;
56 } 116 }
57 return kDefaultDataUseReportMinBytes; 117 return kDefaultDataUseReportMinBytes;
58 } 118 }
59 119
60 } // namespace 120 } // namespace
61 121
62 namespace chrome {
63
64 namespace android {
65
66 // static 122 // static
67 const char ExternalDataUseObserver::kExternalDataUseObserverFieldTrial[] = 123 const char ExternalDataUseObserver::kExternalDataUseObserverFieldTrial[] =
68 "ExternalDataUseObserver"; 124 "ExternalDataUseObserver";
69 125
70 // static 126 // static
71 const size_t ExternalDataUseObserver::kMaxBufferSize = 100; 127 const size_t ExternalDataUseObserver::kMaxBufferSize = 100;
72 128
73 ExternalDataUseObserver::ExternalDataUseObserver( 129 ExternalDataUseObserver::ExternalDataUseObserver(
74 data_usage::DataUseAggregator* data_use_aggregator, 130 data_usage::DataUseAggregator* data_use_aggregator,
75 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 131 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
76 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) 132 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
77 : data_use_aggregator_(data_use_aggregator), 133 : data_use_aggregator_(data_use_aggregator),
78 matching_rules_fetch_pending_(false), 134 matching_rules_fetch_pending_(false),
79 submit_data_report_pending_(false), 135 last_data_report_submitted_ticks_(base::TimeTicks()),
136 pending_report_bytes_(0),
80 ui_task_runner_(ui_task_runner), 137 ui_task_runner_(ui_task_runner),
81 previous_report_time_(base::Time::Now()), 138 previous_report_time_(base::Time::Now()),
82 last_matching_rules_fetch_time_(base::TimeTicks::Now()), 139 last_matching_rules_fetch_time_(base::TimeTicks::Now()),
83 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()), 140 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()),
84 total_bytes_buffered_(0), 141 total_bytes_buffered_(0),
85 fetch_matching_rules_duration_( 142 fetch_matching_rules_duration_(
86 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())), 143 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())),
87 data_use_report_min_bytes_(GetMinBytes()), 144 data_use_report_min_bytes_(GetMinBytes()),
145 data_report_submit_timeout_(
146 base::TimeDelta::FromMilliseconds(GetDataReportSubmitTimeoutMsec())),
88 weak_factory_(this) { 147 weak_factory_(this) {
89 DCHECK(data_use_aggregator_); 148 DCHECK(data_use_aggregator_);
90 DCHECK(io_task_runner); 149 DCHECK(io_task_runner);
91 DCHECK(ui_task_runner_); 150 DCHECK(ui_task_runner_);
151 DCHECK(last_data_report_submitted_ticks_.is_null());
92 152
93 // Initialize the ExternalDataUseObserverBridge object. Initialization will 153 // Initialize the ExternalDataUseObserverBridge object. Initialization will
94 // also trigger the fetching of matching rules. It is okay to use 154 // also trigger the fetching of matching rules. It is okay to use
95 // base::Unretained here since |external_data_use_observer_bridge_| is 155 // base::Unretained here since |external_data_use_observer_bridge_| is
96 // owned by |this|, and is destroyed on UI thread when |this| is destroyed. 156 // owned by |this|, and is destroyed on UI thread when |this| is destroyed.
97 ui_task_runner_->PostTask( 157 ui_task_runner_->PostTask(
98 FROM_HERE, 158 FROM_HERE,
99 base::Bind(&ExternalDataUseObserverBridge::Init, 159 base::Bind(&ExternalDataUseObserverBridge::Init,
100 base::Unretained(external_data_use_observer_bridge_), 160 base::Unretained(external_data_use_observer_bridge_),
101 io_task_runner, GetWeakPtr())); 161 io_task_runner, GetWeakPtr()));
(...skipping 25 matching lines...) Expand all
127 DCHECK(thread_checker_.CalledOnValidThread()); 187 DCHECK(thread_checker_.CalledOnValidThread());
128 188
129 data_use_tab_model_->RegisterURLRegexes(app_package_name, domain_path_regex, 189 data_use_tab_model_->RegisterURLRegexes(app_package_name, domain_path_regex,
130 label); 190 label);
131 matching_rules_fetch_pending_ = false; 191 matching_rules_fetch_pending_ = false;
132 // Process buffered reports. 192 // Process buffered reports.
133 } 193 }
134 194
135 void ExternalDataUseObserver::OnReportDataUseDone(bool success) { 195 void ExternalDataUseObserver::OnReportDataUseDone(bool success) {
136 DCHECK(thread_checker_.CalledOnValidThread()); 196 DCHECK(thread_checker_.CalledOnValidThread());
137 DCHECK(submit_data_report_pending_); 197 DCHECK(!last_data_report_submitted_ticks_.is_null());
138 198
139 // TODO(tbansal): If not successful, record UMA. 199 if (success) {
200 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL,
201 pending_report_bytes_);
202 } else {
203 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_FAILED,
204 pending_report_bytes_);
205 }
140 206
141 submit_data_report_pending_ = false; 207 last_data_report_submitted_ticks_ = base::TimeTicks();
208 pending_report_bytes_ = 0;
142 209
143 SubmitBufferedDataUseReport(); 210 SubmitBufferedDataUseReport();
144 } 211 }
145 212
146 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) { 213 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) {
147 DCHECK(thread_checker_.CalledOnValidThread()); 214 DCHECK(thread_checker_.CalledOnValidThread());
148 const base::TimeTicks now_ticks = base::TimeTicks::Now(); 215 const base::TimeTicks now_ticks = base::TimeTicks::Now();
149 const base::Time now_time = base::Time::Now(); 216 const base::Time now_time = base::Time::Now();
150 217
151 // If the time when the matching rules were last fetched is more than 218 // If the time when the matching rules were last fetched is more than
(...skipping 26 matching lines...) Expand all
178 245
179 void ExternalDataUseObserver::BufferDataUseReport( 246 void ExternalDataUseObserver::BufferDataUseReport(
180 const data_usage::DataUse& data_use, 247 const data_usage::DataUse& data_use,
181 const std::string& label, 248 const std::string& label,
182 const base::Time& start_time, 249 const base::Time& start_time,
183 const base::Time& end_time) { 250 const base::Time& end_time) {
184 DCHECK(thread_checker_.CalledOnValidThread()); 251 DCHECK(thread_checker_.CalledOnValidThread());
185 DCHECK(!label.empty()); 252 DCHECK(!label.empty());
186 DCHECK_LE(0, data_use.rx_bytes); 253 DCHECK_LE(0, data_use.rx_bytes);
187 DCHECK_LE(0, data_use.tx_bytes); 254 DCHECK_LE(0, data_use.tx_bytes);
188 if (data_use.rx_bytes < 0 || data_use.tx_bytes < 0) 255 // Skip if the |data_use| does not report any network traffic.
256 if (data_use.rx_bytes == 0 && data_use.tx_bytes == 0)
189 return; 257 return;
190 258
191 DataUseReportKey data_use_report_key = 259 DataUseReportKey data_use_report_key =
192 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc); 260 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc);
193 261
194 DataUseReport report = 262 DataUseReport report =
195 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes); 263 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes);
196 264
197 // Check if the |data_use_report_key| is already in the buffered reports. 265 // Check if the |data_use_report_key| is already in the buffered reports.
198 DataUseReports::iterator it = 266 DataUseReports::iterator it =
199 buffered_data_reports_.find(data_use_report_key); 267 buffered_data_reports_.find(data_use_report_key);
200 if (it == buffered_data_reports_.end()) { 268 if (it == buffered_data_reports_.end()) {
201 // Limit the buffer size. 269 // Limit the buffer size.
202 if (buffered_data_reports_.size() == kMaxBufferSize) { 270 if (buffered_data_reports_.size() == kMaxBufferSize) {
203 // TODO(tbansal): Add UMA to track impact of lost reports. 271 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_LOST,
272 data_use.rx_bytes + data_use.tx_bytes);
204 return; 273 return;
205 } 274 }
206 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report)); 275 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report));
207 } else { 276 } else {
208 DataUseReport existing_report = DataUseReport(it->second); 277 DataUseReport existing_report = DataUseReport(it->second);
209 DataUseReport merged_report = DataUseReport( 278 DataUseReport merged_report = DataUseReport(
210 std::min(existing_report.start_time, report.start_time), 279 std::min(existing_report.start_time, report.start_time),
211 std::max(existing_report.end_time, report.end_time), 280 std::max(existing_report.end_time, report.end_time),
212 existing_report.bytes_downloaded + report.bytes_downloaded, 281 existing_report.bytes_downloaded + report.bytes_downloaded,
213 existing_report.bytes_uploaded + report.bytes_uploaded); 282 existing_report.bytes_uploaded + report.bytes_uploaded);
214 buffered_data_reports_.erase(it); 283 buffered_data_reports_.erase(it);
215 buffered_data_reports_.insert( 284 buffered_data_reports_.insert(
216 std::make_pair(data_use_report_key, merged_report)); 285 std::make_pair(data_use_report_key, merged_report));
217 } 286 }
218 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes); 287 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes);
219 288
289 DCHECK_LT(0U, buffered_data_reports_.size());
220 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize); 290 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize);
221 } 291 }
222 292
223 void ExternalDataUseObserver::SubmitBufferedDataUseReport() { 293 void ExternalDataUseObserver::SubmitBufferedDataUseReport() {
224 DCHECK(thread_checker_.CalledOnValidThread()); 294 DCHECK(thread_checker_.CalledOnValidThread());
225 295
226 if (submit_data_report_pending_ || buffered_data_reports_.empty()) 296 const base::TimeTicks ticks_now = base::TimeTicks::Now();
297
298 // Return if a data use report has been pending for less than
299 // |data_report_submit_timeout_| duration.
300 if (!last_data_report_submitted_ticks_.is_null() &&
301 ticks_now - last_data_report_submitted_ticks_ <
302 data_report_submit_timeout_) {
303 return;
304 }
305
306 if (buffered_data_reports_.empty())
227 return; 307 return;
228 308
229 if (total_bytes_buffered_ < data_use_report_min_bytes_) 309 if (total_bytes_buffered_ < data_use_report_min_bytes_)
230 return; 310 return;
231 311
312 if (!last_data_report_submitted_ticks_.is_null()) {
313 // Mark the pending DataUsage report as timed out.
314 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT,
315 pending_report_bytes_);
316 pending_report_bytes_ = 0;
317 last_data_report_submitted_ticks_ = base::TimeTicks();
318 }
319
232 // Send one data use report. 320 // Send one data use report.
233 DataUseReports::iterator it = buffered_data_reports_.begin(); 321 DataUseReports::iterator it = buffered_data_reports_.begin();
234 DataUseReportKey key = it->first; 322 DataUseReportKey key = it->first;
235 DataUseReport report = it->second; 323 DataUseReport report = it->second;
236 324
325 DCHECK_EQ(0, pending_report_bytes_);
326 DCHECK(last_data_report_submitted_ticks_.is_null());
327 pending_report_bytes_ = report.bytes_downloaded + report.bytes_uploaded;
328 last_data_report_submitted_ticks_ = ticks_now;
329
237 // Remove the entry from the map. 330 // Remove the entry from the map.
238 buffered_data_reports_.erase(it); 331 buffered_data_reports_.erase(it);
239 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded); 332 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded);
240 333
241 submit_data_report_pending_ = true;
242
243 // It is okay to use base::Unretained here since 334 // It is okay to use base::Unretained here since
244 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed 335 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
245 // on UI thread when |this| is destroyed. 336 // on UI thread when |this| is destroyed.
246 ui_task_runner_->PostTask( 337 ui_task_runner_->PostTask(
247 FROM_HERE, 338 FROM_HERE,
248 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse, 339 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse,
249 base::Unretained(external_data_use_observer_bridge_), 340 base::Unretained(external_data_use_observer_bridge_),
250 key.label, key.connection_type, key.mcc_mnc, report.start_time, 341 key.label, key.connection_type, key.mcc_mnc, report.start_time,
251 report.end_time, report.bytes_downloaded, 342 report.end_time, report.bytes_downloaded,
252 report.bytes_uploaded)); 343 report.bytes_uploaded));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 size_t hash = 1; 388 size_t hash = 1;
298 hash = hash * 23 + hash_function(k.label); 389 hash = hash * 23 + hash_function(k.label);
299 hash = hash * 43 + k.connection_type; 390 hash = hash * 43 + k.connection_type;
300 hash = hash * 83 + hash_function(k.mcc_mnc); 391 hash = hash * 83 + hash_function(k.mcc_mnc);
301 return hash; 392 return hash;
302 } 393 }
303 394
304 } // namespace android 395 } // namespace android
305 396
306 } // namespace chrome 397 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698