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

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 #include "third_party/re2/re2/re2.h" 20 #include "third_party/re2/re2/re2.h"
20 #include "url/gurl.h" 21 #include "url/gurl.h"
21 22
22 namespace { 23 namespace {
Alexei Svitkine (slow) 2015/12/09 18:15:47 Nit: Move this anon namespace to be inside of chro
tbansal1 2015/12/10 00:41:39 Done.
23 24
25 // Record the result of data use report submission. |bytes| is the sum of send
26 // and received bytes in the report.
27 void RecordDataUsageReportSubmission(
28 chrome::android::ExternalDataUseObserver::DataUsageReportSubmissionResult
29 result,
30 int64_t bytes) {
31 DCHECK_LE(0, bytes);
32 UMA_HISTOGRAM_ENUMERATION("DataUsage.ReportSubmissionResult", result,
33 chrome::android::ExternalDataUseObserver::
34 DATAUSAGE_REPORT_SUBMISSION_MAX);
35 // Cap to the maximum sample value.
36 const int32_t bytes_capped = bytes <= base::HistogramBase::kSampleType_MAX - 1
37 ? bytes
38 : base::HistogramBase::kSampleType_MAX - 1;
39 switch (result) {
40 case chrome::android::ExternalDataUseObserver::
41 DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL:
42 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Successful.Bytes",
43 bytes_capped);
44 break;
45 case chrome::android::ExternalDataUseObserver::
46 DATAUSAGE_REPORT_SUBMISSION_FAILED:
47 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Failed.Bytes",
48 bytes_capped);
49 break;
50 case chrome::android::ExternalDataUseObserver::
51 DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT:
52 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.TimedOut.Bytes",
53 bytes_capped);
54 break;
55 case chrome::android::ExternalDataUseObserver::
56 DATAUSAGE_REPORT_SUBMISSION_LOST:
57 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Lost.Bytes",
58 bytes_capped);
59 break;
60 default:
61 NOTIMPLEMENTED();
62 break;
63 }
64 }
65
24 // Default duration after which matching rules are periodically fetched. May be 66 // Default duration after which matching rules are periodically fetched. May be
25 // overridden by the field trial. 67 // overridden by the field trial.
26 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes. 68 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes.
27 69
70 // Default duration after which a pending data use report is considered timed
71 // out. May be overridden by the field trial.
72 const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes.
73
28 // Default value of the minimum number of bytes that should be buffered before 74 // Default value of the minimum number of bytes that should be buffered before
29 // a data use report is submitted. May be overridden by the field trial. 75 // a data use report is submitted. May be overridden by the field trial.
30 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB. 76 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB.
31 77
32 // Populates various parameters from the values specified in the field trial. 78 // Populates various parameters from the values specified in the field trial.
33 int32_t GetFetchMatchingRulesDurationSeconds() { 79 int32_t GetFetchMatchingRulesDurationSeconds() {
34 int32_t duration_seconds = -1; 80 int32_t duration_seconds = -1;
35 std::string variation_value = variations::GetVariationParamValue( 81 const std::string variation_value = variations::GetVariationParamValue(
36 chrome::android::ExternalDataUseObserver:: 82 chrome::android::ExternalDataUseObserver::
37 kExternalDataUseObserverFieldTrial, 83 kExternalDataUseObserverFieldTrial,
38 "fetch_matching_rules_duration_seconds"); 84 "fetch_matching_rules_duration_seconds");
39 if (!variation_value.empty() && 85 if (!variation_value.empty() &&
40 base::StringToInt(variation_value, &duration_seconds)) { 86 base::StringToInt(variation_value, &duration_seconds)) {
41 DCHECK_LE(0, duration_seconds); 87 DCHECK_LE(0, duration_seconds);
42 return duration_seconds; 88 return duration_seconds;
43 } 89 }
44 return kDefaultFetchMatchingRulesDurationSeconds; 90 return kDefaultFetchMatchingRulesDurationSeconds;
45 } 91 }
46 92
47 // Populates various parameters from the values specified in the field trial. 93 // Populates various parameters from the values specified in the field trial.
94 int32_t GetDataReportSubmitTimeoutMsec() {
95 int32_t duration_seconds = -1;
96 const std::string variation_value = variations::GetVariationParamValue(
97 chrome::android::ExternalDataUseObserver::
98 kExternalDataUseObserverFieldTrial,
99 "data_report_submit_timeout_msec");
100 if (!variation_value.empty() &&
101 base::StringToInt(variation_value, &duration_seconds)) {
102 DCHECK_LE(0, duration_seconds);
103 return duration_seconds;
104 }
105 return kDefaultDataUseReportSubmitTimeoutMsec;
106 }
107
108 // Populates various parameters from the values specified in the field trial.
48 int64_t GetMinBytes() { 109 int64_t GetMinBytes() {
49 int64_t min_bytes = -1; 110 int64_t min_bytes = -1;
50 std::string variation_value = variations::GetVariationParamValue( 111 const std::string variation_value = variations::GetVariationParamValue(
51 chrome::android::ExternalDataUseObserver:: 112 chrome::android::ExternalDataUseObserver::
52 kExternalDataUseObserverFieldTrial, 113 kExternalDataUseObserverFieldTrial,
53 "data_use_report_min_bytes"); 114 "data_use_report_min_bytes");
54 if (!variation_value.empty() && 115 if (!variation_value.empty() &&
55 base::StringToInt64(variation_value, &min_bytes)) { 116 base::StringToInt64(variation_value, &min_bytes)) {
56 DCHECK_LE(0, min_bytes); 117 DCHECK_LE(0, min_bytes);
57 return min_bytes; 118 return min_bytes;
58 } 119 }
59 return kDefaultDataUseReportMinBytes; 120 return kDefaultDataUseReportMinBytes;
60 } 121 }
(...skipping 10 matching lines...) Expand all
71 132
72 // static 133 // static
73 const size_t ExternalDataUseObserver::kMaxBufferSize = 100; 134 const size_t ExternalDataUseObserver::kMaxBufferSize = 100;
74 135
75 ExternalDataUseObserver::ExternalDataUseObserver( 136 ExternalDataUseObserver::ExternalDataUseObserver(
76 data_usage::DataUseAggregator* data_use_aggregator, 137 data_usage::DataUseAggregator* data_use_aggregator,
77 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 138 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
78 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) 139 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
79 : data_use_aggregator_(data_use_aggregator), 140 : data_use_aggregator_(data_use_aggregator),
80 matching_rules_fetch_pending_(false), 141 matching_rules_fetch_pending_(false),
81 submit_data_report_pending_(false), 142 last_data_report_submitted_ticks_(base::TimeTicks()),
143 pending_report_bytes_(0),
82 registered_as_observer_(false), 144 registered_as_observer_(false),
83 ui_task_runner_(ui_task_runner), 145 ui_task_runner_(ui_task_runner),
84 previous_report_time_(base::Time::Now()), 146 previous_report_time_(base::Time::Now()),
85 last_matching_rules_fetch_time_(base::TimeTicks::Now()), 147 last_matching_rules_fetch_time_(base::TimeTicks::Now()),
86 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()), 148 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()),
87 total_bytes_buffered_(0), 149 total_bytes_buffered_(0),
88 fetch_matching_rules_duration_( 150 fetch_matching_rules_duration_(
89 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())), 151 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())),
90 data_use_report_min_bytes_(GetMinBytes()), 152 data_use_report_min_bytes_(GetMinBytes()),
153 data_report_submit_timeout_(
154 base::TimeDelta::FromMilliseconds(GetDataReportSubmitTimeoutMsec())),
91 weak_factory_(this) { 155 weak_factory_(this) {
92 DCHECK(data_use_aggregator_); 156 DCHECK(data_use_aggregator_);
93 DCHECK(io_task_runner); 157 DCHECK(io_task_runner);
94 DCHECK(ui_task_runner_); 158 DCHECK(ui_task_runner_);
159 DCHECK(last_data_report_submitted_ticks_.is_null());
95 160
96 // Initialize the ExternalDataUseObserverBridge object. Initialization will 161 // Initialize the ExternalDataUseObserverBridge object. Initialization will
97 // also trigger the fetching of matching rules. It is okay to use 162 // also trigger the fetching of matching rules. It is okay to use
98 // base::Unretained here since |external_data_use_observer_bridge_| is 163 // base::Unretained here since |external_data_use_observer_bridge_| is
99 // owned by |this|, and is destroyed on UI thread when |this| is destroyed. 164 // owned by |this|, and is destroyed on UI thread when |this| is destroyed.
100 ui_task_runner_->PostTask( 165 ui_task_runner_->PostTask(
101 FROM_HERE, 166 FROM_HERE,
102 base::Bind(&ExternalDataUseObserverBridge::Init, 167 base::Bind(&ExternalDataUseObserverBridge::Init,
103 base::Unretained(external_data_use_observer_bridge_), 168 base::Unretained(external_data_use_observer_bridge_),
104 io_task_runner, GetWeakPtr())); 169 io_task_runner, GetWeakPtr()));
(...skipping 26 matching lines...) Expand all
131 const std::vector<std::string>* label) { 196 const std::vector<std::string>* label) {
132 DCHECK(thread_checker_.CalledOnValidThread()); 197 DCHECK(thread_checker_.CalledOnValidThread());
133 198
134 RegisterURLRegexes(app_package_name, domain_path_regex, label); 199 RegisterURLRegexes(app_package_name, domain_path_regex, label);
135 matching_rules_fetch_pending_ = false; 200 matching_rules_fetch_pending_ = false;
136 // Process buffered reports. 201 // Process buffered reports.
137 } 202 }
138 203
139 void ExternalDataUseObserver::OnReportDataUseDone(bool success) { 204 void ExternalDataUseObserver::OnReportDataUseDone(bool success) {
140 DCHECK(thread_checker_.CalledOnValidThread()); 205 DCHECK(thread_checker_.CalledOnValidThread());
141 DCHECK(submit_data_report_pending_); 206 DCHECK(!last_data_report_submitted_ticks_.is_null());
142 207
143 // TODO(tbansal): If not successful, record UMA. 208 if (success) {
209 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL,
210 pending_report_bytes_);
211 } else {
212 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_FAILED,
213 pending_report_bytes_);
214 }
144 215
145 submit_data_report_pending_ = false; 216 last_data_report_submitted_ticks_ = base::TimeTicks();
217 pending_report_bytes_ = 0;
146 218
147 SubmitBufferedDataUseReport(); 219 SubmitBufferedDataUseReport();
148 } 220 }
149 221
150 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) { 222 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) {
151 DCHECK(thread_checker_.CalledOnValidThread()); 223 DCHECK(thread_checker_.CalledOnValidThread());
152 const base::TimeTicks now_ticks = base::TimeTicks::Now(); 224 const base::TimeTicks now_ticks = base::TimeTicks::Now();
153 const base::Time now_time = base::Time::Now(); 225 const base::Time now_time = base::Time::Now();
154 226
155 // If the time when the matching rules were last fetched is more than 227 // If the time when the matching rules were last fetched is more than
(...skipping 26 matching lines...) Expand all
182 254
183 void ExternalDataUseObserver::BufferDataUseReport( 255 void ExternalDataUseObserver::BufferDataUseReport(
184 const data_usage::DataUse& data_use, 256 const data_usage::DataUse& data_use,
185 const std::string& label, 257 const std::string& label,
186 const base::Time& start_time, 258 const base::Time& start_time,
187 const base::Time& end_time) { 259 const base::Time& end_time) {
188 DCHECK(thread_checker_.CalledOnValidThread()); 260 DCHECK(thread_checker_.CalledOnValidThread());
189 DCHECK(!label.empty()); 261 DCHECK(!label.empty());
190 DCHECK_LE(0, data_use.rx_bytes); 262 DCHECK_LE(0, data_use.rx_bytes);
191 DCHECK_LE(0, data_use.tx_bytes); 263 DCHECK_LE(0, data_use.tx_bytes);
192 if (data_use.rx_bytes < 0 || data_use.tx_bytes < 0) 264 // Skip if the |data_use| does not report any network traffic.
265 if (data_use.rx_bytes == 0 && data_use.tx_bytes == 0)
193 return; 266 return;
194 267
195 DataUseReportKey data_use_report_key = 268 DataUseReportKey data_use_report_key =
196 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc); 269 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc);
197 270
198 DataUseReport report = 271 DataUseReport report =
199 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes); 272 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes);
200 273
201 // Check if the |data_use_report_key| is already in the buffered reports. 274 // Check if the |data_use_report_key| is already in the buffered reports.
202 DataUseReports::iterator it = 275 DataUseReports::iterator it =
203 buffered_data_reports_.find(data_use_report_key); 276 buffered_data_reports_.find(data_use_report_key);
204 if (it == buffered_data_reports_.end()) { 277 if (it == buffered_data_reports_.end()) {
205 // Limit the buffer size. 278 // Limit the buffer size.
206 if (buffered_data_reports_.size() == kMaxBufferSize) { 279 if (buffered_data_reports_.size() == kMaxBufferSize) {
207 // TODO(tbansal): Add UMA to track impact of lost reports. 280 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_LOST,
281 data_use.rx_bytes + data_use.tx_bytes);
208 return; 282 return;
209 } 283 }
210 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report)); 284 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report));
211 } else { 285 } else {
212 DataUseReport existing_report = DataUseReport(it->second); 286 DataUseReport existing_report = DataUseReport(it->second);
213 DataUseReport merged_report = DataUseReport( 287 DataUseReport merged_report = DataUseReport(
214 std::min(existing_report.start_time, report.start_time), 288 std::min(existing_report.start_time, report.start_time),
215 std::max(existing_report.end_time, report.end_time), 289 std::max(existing_report.end_time, report.end_time),
216 existing_report.bytes_downloaded + report.bytes_downloaded, 290 existing_report.bytes_downloaded + report.bytes_downloaded,
217 existing_report.bytes_uploaded + report.bytes_uploaded); 291 existing_report.bytes_uploaded + report.bytes_uploaded);
218 buffered_data_reports_.erase(it); 292 buffered_data_reports_.erase(it);
219 buffered_data_reports_.insert( 293 buffered_data_reports_.insert(
220 std::make_pair(data_use_report_key, merged_report)); 294 std::make_pair(data_use_report_key, merged_report));
221 } 295 }
222 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes); 296 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes);
223 297
298 DCHECK_LT(0U, buffered_data_reports_.size());
224 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize); 299 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize);
225 } 300 }
226 301
227 void ExternalDataUseObserver::SubmitBufferedDataUseReport() { 302 void ExternalDataUseObserver::SubmitBufferedDataUseReport() {
228 DCHECK(thread_checker_.CalledOnValidThread()); 303 DCHECK(thread_checker_.CalledOnValidThread());
229 304
230 if (submit_data_report_pending_ || buffered_data_reports_.empty()) 305 const base::TimeTicks ticks_now = base::TimeTicks::Now();
306
307 // Return if a data use report has been pending for less than
308 // |data_report_submit_timeout_| duration.
309 if (!last_data_report_submitted_ticks_.is_null() &&
310 ticks_now - last_data_report_submitted_ticks_ <
311 data_report_submit_timeout_) {
312 return;
313 }
314
315 if (buffered_data_reports_.empty())
231 return; 316 return;
232 317
233 if (total_bytes_buffered_ < data_use_report_min_bytes_) 318 if (total_bytes_buffered_ < data_use_report_min_bytes_)
234 return; 319 return;
235 320
321 if (!last_data_report_submitted_ticks_.is_null()) {
322 // Mark the pending DataUsage report as timed out.
323 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT,
324 pending_report_bytes_);
325 pending_report_bytes_ = 0;
326 last_data_report_submitted_ticks_ = base::TimeTicks();
327 }
328
236 // Send one data use report. 329 // Send one data use report.
237 DataUseReports::iterator it = buffered_data_reports_.begin(); 330 DataUseReports::iterator it = buffered_data_reports_.begin();
238 DataUseReportKey key = it->first; 331 DataUseReportKey key = it->first;
239 DataUseReport report = it->second; 332 DataUseReport report = it->second;
240 333
334 DCHECK_EQ(0, pending_report_bytes_);
335 DCHECK(last_data_report_submitted_ticks_.is_null());
336 pending_report_bytes_ = report.bytes_downloaded + report.bytes_uploaded;
337 last_data_report_submitted_ticks_ = ticks_now;
338
241 // Remove the entry from the map. 339 // Remove the entry from the map.
242 buffered_data_reports_.erase(it); 340 buffered_data_reports_.erase(it);
243 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded); 341 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded);
244 342
245 submit_data_report_pending_ = true;
246
247 // It is okay to use base::Unretained here since 343 // It is okay to use base::Unretained here since
248 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed 344 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
249 // on UI thread when |this| is destroyed. 345 // on UI thread when |this| is destroyed.
250 ui_task_runner_->PostTask( 346 ui_task_runner_->PostTask(
251 FROM_HERE, 347 FROM_HERE,
252 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse, 348 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse,
253 base::Unretained(external_data_use_observer_bridge_), 349 base::Unretained(external_data_use_observer_bridge_),
254 key.label, key.connection_type, key.mcc_mnc, report.start_time, 350 key.label, key.connection_type, key.mcc_mnc, report.start_time,
255 report.end_time, report.bytes_downloaded, 351 report.end_time, report.bytes_downloaded,
256 report.bytes_uploaded)); 352 report.bytes_uploaded));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 return app_package_name_; 503 return app_package_name_;
408 } 504 }
409 505
410 const std::string& ExternalDataUseObserver::MatchingRule::label() const { 506 const std::string& ExternalDataUseObserver::MatchingRule::label() const {
411 return label_; 507 return label_;
412 } 508 }
413 509
414 } // namespace android 510 } // namespace android
415 511
416 } // namespace chrome 512 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698