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

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

Powered by Google App Engine
This is Rietveld 408576698