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

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: Addressed sclittle comments and some cleanup 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/android/context_utils.h" 9 #include "base/android/context_utils.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
11 #include "base/containers/hash_tables.h" 11 #include "base/containers/hash_tables.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/field_trial.h" 13 #include "base/metrics/field_trial.h"
14 #include "base/metrics/histogram_base.h"
15 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
15 #include "chrome/browser/android/data_usage/data_use_tab_model.h" 17 #include "chrome/browser/android/data_usage/data_use_tab_model.h"
16 #include "components/data_usage/core/data_use.h" 18 #include "components/data_usage/core/data_use.h"
17 #include "components/variations/variations_associated_data.h" 19 #include "components/variations/variations_associated_data.h"
18 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
19 #include "jni/ExternalDataUseObserver_jni.h" 21 #include "jni/ExternalDataUseObserver_jni.h"
20 #include "third_party/re2/re2/re2.h" 22 #include "third_party/re2/re2/re2.h"
21 #include "url/gurl.h" 23 #include "url/gurl.h"
22 24
23 using base::android::ConvertUTF8ToJavaString; 25 using base::android::ConvertUTF8ToJavaString;
24 using base::android::ToJavaArrayOfStrings; 26 using base::android::ToJavaArrayOfStrings;
25 27
26 namespace { 28 namespace {
27 29
30 // Result of data usage report submission.
31 enum DataUsageReportSubmissionResult {
32 // Submission of data use report to the external observer was successful.
33 DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL = 0,
34 // Submission of data use report to the external observer returned error.
35 DATAUSAGE_REPORT_SUBMISSION_FAILED = 1,
36 // Submission of data use report to the external observer timed out.
37 DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT = 2,
38 // Data use report was lost before an attempt was made to submit it.
39 DATAUSAGE_REPORT_SUBMISSION_LOST = 3,
40 DATAUSAGE_REPORT_SUBMISSION_BOUNDARY = 4
41 };
42
43 // Record the result of data use report submission. |bytes| is the sum of send
44 // and received bytes in the report.
45 void RecordDataUsageReportSubmission(DataUsageReportSubmissionResult result,
46 int64_t bytes) {
sclittle 2015/12/07 21:44:08 nit: just for clarity, could you add a DCHECK_LE(0
tbansal1 2015/12/08 00:08:16 Done.
47 UMA_HISTOGRAM_ENUMERATION("DataUsage.ReportSubmissionResult", result,
48 DATAUSAGE_REPORT_SUBMISSION_BOUNDARY);
49 // Cap to the maximum sample value.
50 const int32_t bytes_capped = bytes <= base::HistogramBase::kSampleType_MAX - 1
sclittle 2015/12/07 21:44:08 optional nit: You could use std::min here.
tbansal1 2015/12/08 00:08:16 I tried that before but it does not work because o
51 ? bytes
52 : base::HistogramBase::kSampleType_MAX - 1;
53 switch (result) {
54 case DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL:
55 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Successful.Bytes",
56 bytes_capped);
57 break;
58 case DATAUSAGE_REPORT_SUBMISSION_FAILED:
59 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Failed.Bytes",
60 bytes_capped);
61 break;
62 case DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT:
63 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.TimedOut.Bytes",
64 bytes_capped);
65 break;
66 case DATAUSAGE_REPORT_SUBMISSION_LOST:
67 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Lost.Bytes",
68 bytes_capped);
69 break;
70 default:
71 NOTIMPLEMENTED();
72 break;
73 }
74 }
75
28 // Default duration after which matching rules are periodically fetched. May be 76 // Default duration after which matching rules are periodically fetched. May be
29 // overridden by the field trial. 77 // overridden by the field trial.
30 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes. 78 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes.
31 79
80 // Default duration after which a pending data use report is considered timed
81 // out. May be overridden by the field trial.
82 const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes.
83
32 // Default value of the minimum number of bytes that should be buffered before 84 // Default value of the minimum number of bytes that should be buffered before
33 // a data use report is submitted. May be overridden by the field trial. 85 // a data use report is submitted. May be overridden by the field trial.
34 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB. 86 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB.
35 87
36 // Populates various parameters from the values specified in the field trial. 88 // Populates various parameters from the values specified in the field trial.
37 int32_t GetFetchMatchingRulesDurationSeconds() { 89 int32_t GetFetchMatchingRulesDurationSeconds() {
38 int32_t duration_seconds = -1; 90 int32_t duration_seconds = -1;
39 std::string variation_value = variations::GetVariationParamValue( 91 const std::string variation_value = variations::GetVariationParamValue(
40 chrome::android::ExternalDataUseObserver:: 92 chrome::android::ExternalDataUseObserver::
41 kExternalDataUseObserverFieldTrial, 93 kExternalDataUseObserverFieldTrial,
42 "fetch_matching_rules_duration_seconds"); 94 "fetch_matching_rules_duration_seconds");
43 if (!variation_value.empty() && 95 if (!variation_value.empty() &&
44 base::StringToInt(variation_value, &duration_seconds)) { 96 base::StringToInt(variation_value, &duration_seconds)) {
45 DCHECK_LE(0, duration_seconds); 97 DCHECK_LE(0, duration_seconds);
46 return duration_seconds; 98 return duration_seconds;
47 } 99 }
48 return kDefaultFetchMatchingRulesDurationSeconds; 100 return kDefaultFetchMatchingRulesDurationSeconds;
49 } 101 }
50 102
51 // Populates various parameters from the values specified in the field trial. 103 // Populates various parameters from the values specified in the field trial.
104 int32_t GetDataReportSubmitTimeoutMsec() {
105 int32_t duration_seconds = -1;
106 const std::string variation_value = variations::GetVariationParamValue(
107 chrome::android::ExternalDataUseObserver::
108 kExternalDataUseObserverFieldTrial,
109 "data_report_submit_timeout_msec");
110 if (!variation_value.empty() &&
111 base::StringToInt(variation_value, &duration_seconds)) {
112 DCHECK_LE(0, duration_seconds);
113 return duration_seconds;
114 }
115 return kDefaultDataUseReportSubmitTimeoutMsec;
116 }
117
118 // Populates various parameters from the values specified in the field trial.
52 int64_t GetMinBytes() { 119 int64_t GetMinBytes() {
53 int64_t min_bytes = -1; 120 int64_t min_bytes = -1;
54 std::string variation_value = variations::GetVariationParamValue( 121 const std::string variation_value = variations::GetVariationParamValue(
55 chrome::android::ExternalDataUseObserver:: 122 chrome::android::ExternalDataUseObserver::
56 kExternalDataUseObserverFieldTrial, 123 kExternalDataUseObserverFieldTrial,
57 "data_use_report_min_bytes"); 124 "data_use_report_min_bytes");
58 if (!variation_value.empty() && 125 if (!variation_value.empty() &&
59 base::StringToInt64(variation_value, &min_bytes)) { 126 base::StringToInt64(variation_value, &min_bytes)) {
60 DCHECK_LE(0, min_bytes); 127 DCHECK_LE(0, min_bytes);
61 return min_bytes; 128 return min_bytes;
62 } 129 }
63 return kDefaultDataUseReportMinBytes; 130 return kDefaultDataUseReportMinBytes;
64 } 131 }
(...skipping 10 matching lines...) Expand all
75 142
76 // static 143 // static
77 const size_t ExternalDataUseObserver::kMaxBufferSize = 100; 144 const size_t ExternalDataUseObserver::kMaxBufferSize = 100;
78 145
79 ExternalDataUseObserver::ExternalDataUseObserver( 146 ExternalDataUseObserver::ExternalDataUseObserver(
80 data_usage::DataUseAggregator* data_use_aggregator, 147 data_usage::DataUseAggregator* data_use_aggregator,
81 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 148 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
82 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) 149 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
83 : data_use_aggregator_(data_use_aggregator), 150 : data_use_aggregator_(data_use_aggregator),
84 matching_rules_fetch_pending_(false), 151 matching_rules_fetch_pending_(false),
85 submit_data_report_pending_(false), 152 last_data_report_submitted_ticks_(base::TimeTicks()),
153 pending_report_bytes_(0),
86 registered_as_observer_(false), 154 registered_as_observer_(false),
87 io_task_runner_(io_task_runner), 155 io_task_runner_(io_task_runner),
88 ui_task_runner_(ui_task_runner), 156 ui_task_runner_(ui_task_runner),
89 previous_report_time_(base::Time::Now()), 157 previous_report_time_(base::Time::Now()),
90 last_matching_rules_fetch_time_(base::TimeTicks::Now()), 158 last_matching_rules_fetch_time_(base::TimeTicks::Now()),
91 total_bytes_buffered_(0), 159 total_bytes_buffered_(0),
92 fetch_matching_rules_duration_( 160 fetch_matching_rules_duration_(
93 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())), 161 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())),
94 data_use_report_min_bytes_(GetMinBytes()), 162 data_use_report_min_bytes_(GetMinBytes()),
163 data_report_submit_timeout_(
164 base::TimeDelta::FromMilliseconds(GetDataReportSubmitTimeoutMsec())),
95 io_weak_factory_(this), 165 io_weak_factory_(this),
96 ui_weak_factory_(this) { 166 ui_weak_factory_(this) {
97 DCHECK(data_use_aggregator_); 167 DCHECK(data_use_aggregator_);
98 DCHECK(io_task_runner_); 168 DCHECK(io_task_runner_);
99 DCHECK(ui_task_runner_); 169 DCHECK(ui_task_runner_);
170 DCHECK(last_data_report_submitted_ticks_.is_null());
100 171
101 ui_task_runner_->PostTask( 172 ui_task_runner_->PostTask(
102 FROM_HERE, 173 FROM_HERE,
103 base::Bind(&ExternalDataUseObserver::CreateJavaObjectOnUIThread, 174 base::Bind(&ExternalDataUseObserver::CreateJavaObjectOnUIThread,
104 GetUIWeakPtr())); 175 GetUIWeakPtr()));
105 176
106 ui_task_runner_->PostTask( 177 ui_task_runner_->PostTask(
107 FROM_HERE, 178 FROM_HERE,
108 base::Bind(&ExternalDataUseObserver::FetchMatchingRulesOnUIThread, 179 base::Bind(&ExternalDataUseObserver::FetchMatchingRulesOnUIThread,
109 GetUIWeakPtr())); 180 GetUIWeakPtr()));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetIOWeakPtr() { 269 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetIOWeakPtr() {
199 return io_weak_factory_.GetWeakPtr(); 270 return io_weak_factory_.GetWeakPtr();
200 } 271 }
201 272
202 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetUIWeakPtr() { 273 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetUIWeakPtr() {
203 return ui_weak_factory_.GetWeakPtr(); 274 return ui_weak_factory_.GetWeakPtr();
204 } 275 }
205 276
206 void ExternalDataUseObserver::OnReportDataUseDoneOnIOThread(bool success) { 277 void ExternalDataUseObserver::OnReportDataUseDoneOnIOThread(bool success) {
207 DCHECK(thread_checker_.CalledOnValidThread()); 278 DCHECK(thread_checker_.CalledOnValidThread());
208 DCHECK(submit_data_report_pending_); 279 DCHECK(!last_data_report_submitted_ticks_.is_null());
209 280
210 // TODO(tbansal): If not successful, record UMA. 281 if (success) {
282 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL,
283 pending_report_bytes_);
284 } else {
285 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_FAILED,
286 pending_report_bytes_);
287 }
211 288
212 submit_data_report_pending_ = false; 289 last_data_report_submitted_ticks_ = base::TimeTicks();
290 pending_report_bytes_ = 0;
213 291
214 SubmitBufferedDataUseReport(); 292 SubmitBufferedDataUseReport();
215 } 293 }
216 294
217 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) { 295 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) {
218 DCHECK(thread_checker_.CalledOnValidThread()); 296 DCHECK(thread_checker_.CalledOnValidThread());
219 const base::TimeTicks now_ticks = base::TimeTicks::Now(); 297 const base::TimeTicks now_ticks = base::TimeTicks::Now();
220 const base::Time now_time = base::Time::Now(); 298 const base::Time now_time = base::Time::Now();
221 299
222 // If the time when the matching rules were last fetched is more than 300 // If the time when the matching rules were last fetched is more than
(...skipping 24 matching lines...) Expand all
247 325
248 void ExternalDataUseObserver::BufferDataUseReport( 326 void ExternalDataUseObserver::BufferDataUseReport(
249 const data_usage::DataUse& data_use, 327 const data_usage::DataUse& data_use,
250 const std::string& label, 328 const std::string& label,
251 const base::Time& start_time, 329 const base::Time& start_time,
252 const base::Time& end_time) { 330 const base::Time& end_time) {
253 DCHECK(thread_checker_.CalledOnValidThread()); 331 DCHECK(thread_checker_.CalledOnValidThread());
254 DCHECK(!label.empty()); 332 DCHECK(!label.empty());
255 DCHECK_LE(0, data_use.rx_bytes); 333 DCHECK_LE(0, data_use.rx_bytes);
256 DCHECK_LE(0, data_use.tx_bytes); 334 DCHECK_LE(0, data_use.tx_bytes);
257 if (data_use.rx_bytes < 0 || data_use.tx_bytes < 0) 335 if (data_use.rx_bytes < 0 || data_use.tx_bytes < 0 ||
sclittle 2015/12/07 21:44:08 nit: The < 0 checks here aren't necessary, and dis
tbansal1 2015/12/08 00:08:16 Right, removed.
336 (data_use.rx_bytes == 0 && data_use.tx_bytes == 0)) {
258 return; 337 return;
338 }
259 339
260 DataUseReportKey data_use_report_key = 340 DataUseReportKey data_use_report_key =
261 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc); 341 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc);
262 342
263 DataUseReport report = 343 DataUseReport report =
264 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes); 344 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes);
265 345
266 // Check if the |data_use_report_key| is already in the buffered reports. 346 // Check if the |data_use_report_key| is already in the buffered reports.
267 DataUseReports::iterator it = 347 DataUseReports::iterator it =
268 buffered_data_reports_.find(data_use_report_key); 348 buffered_data_reports_.find(data_use_report_key);
269 if (it == buffered_data_reports_.end()) { 349 if (it == buffered_data_reports_.end()) {
270 // Limit the buffer size. 350 // Limit the buffer size.
271 if (buffered_data_reports_.size() == kMaxBufferSize) { 351 if (buffered_data_reports_.size() == kMaxBufferSize) {
272 // TODO(tbansal): Add UMA to track impact of lost reports. 352 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_LOST,
353 data_use.rx_bytes + data_use.tx_bytes);
273 return; 354 return;
274 } 355 }
275 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report)); 356 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report));
276 } else { 357 } else {
277 DataUseReport existing_report = DataUseReport(it->second); 358 DataUseReport existing_report = DataUseReport(it->second);
278 DataUseReport merged_report = DataUseReport( 359 DataUseReport merged_report = DataUseReport(
279 std::min(existing_report.start_time, report.start_time), 360 std::min(existing_report.start_time, report.start_time),
280 std::max(existing_report.end_time, report.end_time), 361 std::max(existing_report.end_time, report.end_time),
281 existing_report.bytes_downloaded + report.bytes_downloaded, 362 existing_report.bytes_downloaded + report.bytes_downloaded,
282 existing_report.bytes_uploaded + report.bytes_uploaded); 363 existing_report.bytes_uploaded + report.bytes_uploaded);
283 buffered_data_reports_.erase(it); 364 buffered_data_reports_.erase(it);
284 buffered_data_reports_.insert( 365 buffered_data_reports_.insert(
285 std::make_pair(data_use_report_key, merged_report)); 366 std::make_pair(data_use_report_key, merged_report));
286 } 367 }
287 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes); 368 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes);
288 369
370 DCHECK_LT(0U, buffered_data_reports_.size());
289 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize); 371 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize);
290 } 372 }
291 373
292 void ExternalDataUseObserver::SubmitBufferedDataUseReport() { 374 void ExternalDataUseObserver::SubmitBufferedDataUseReport() {
293 DCHECK(thread_checker_.CalledOnValidThread()); 375 DCHECK(thread_checker_.CalledOnValidThread());
294 376
295 if (submit_data_report_pending_ || buffered_data_reports_.empty()) 377 const base::TimeTicks ticks_now = base::TimeTicks::Now();
378
379 // Return if a data use report has been pending for less than
380 // |data_report_submit_timeout_| duration.
381 if (!last_data_report_submitted_ticks_.is_null() &&
382 ticks_now - last_data_report_submitted_ticks_ <
383 data_report_submit_timeout_) {
384 return;
385 }
386
387 if (buffered_data_reports_.empty())
296 return; 388 return;
297 389
298 if (total_bytes_buffered_ < data_use_report_min_bytes_) 390 if (total_bytes_buffered_ < data_use_report_min_bytes_)
299 return; 391 return;
300 392
393 if (!last_data_report_submitted_ticks_.is_null()) {
sclittle 2015/12/07 21:44:08 nit: add a comment like "Cancel a pending DataUsag
tbansal1 2015/12/08 00:08:16 Done.
394 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT,
395 pending_report_bytes_);
396 pending_report_bytes_ = 0;
397 last_data_report_submitted_ticks_ = base::TimeTicks();
398 }
399
301 // Send one data use report. 400 // Send one data use report.
302 DataUseReports::iterator it = buffered_data_reports_.begin(); 401 DataUseReports::iterator it = buffered_data_reports_.begin();
303 DataUseReportKey key = it->first; 402 DataUseReportKey key = it->first;
304 DataUseReport report = it->second; 403 DataUseReport report = it->second;
305 404
405 DCHECK_EQ(0, pending_report_bytes_);
406 DCHECK(last_data_report_submitted_ticks_.is_null());
407 pending_report_bytes_ = report.bytes_downloaded + report.bytes_uploaded;
408 last_data_report_submitted_ticks_ = ticks_now;
409
306 // Remove the entry from the map. 410 // Remove the entry from the map.
307 buffered_data_reports_.erase(it); 411 buffered_data_reports_.erase(it);
308 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded); 412 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded);
309 413
310 submit_data_report_pending_ = true;
311
312 ui_task_runner_->PostTask( 414 ui_task_runner_->PostTask(
313 FROM_HERE, base::Bind(&ExternalDataUseObserver::ReportDataUseOnUIThread, 415 FROM_HERE, base::Bind(&ExternalDataUseObserver::ReportDataUseOnUIThread,
314 GetIOWeakPtr(), key, report)); 416 GetIOWeakPtr(), key, report));
315 } 417 }
316 418
317 void ExternalDataUseObserver::ReportDataUseOnUIThread( 419 void ExternalDataUseObserver::ReportDataUseOnUIThread(
318 const DataUseReportKey& key, 420 const DataUseReportKey& key,
319 const DataUseReport& report) const { 421 const DataUseReport& report) const {
320 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 422 DCHECK(ui_task_runner_->BelongsToCurrentThread());
321 JNIEnv* env = base::android::AttachCurrentThread(); 423 JNIEnv* env = base::android::AttachCurrentThread();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 return label_; 586 return label_;
485 } 587 }
486 588
487 bool RegisterExternalDataUseObserver(JNIEnv* env) { 589 bool RegisterExternalDataUseObserver(JNIEnv* env) {
488 return RegisterNativesImpl(env); 590 return RegisterNativesImpl(env);
489 } 591 }
490 592
491 } // namespace android 593 } // namespace android
492 594
493 } // namespace chrome 595 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698