Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / net / base / network_quality_estimator.cc
blob6415ee6e6d7eb36b47ab4fd568d3537283b27729
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
3 // found in the LICENSE file.
5 #include "net/base/network_quality_estimator.h"
7 #include <string>
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "net/base/net_util.h"
12 #include "net/base/network_quality.h"
13 #include "net/url_request/url_request.h"
14 #include "url/gurl.h"
16 namespace net {
18 NetworkQualityEstimator::NetworkQualityEstimator()
19 : NetworkQualityEstimator(false) {
22 NetworkQualityEstimator::NetworkQualityEstimator(
23 bool allow_local_host_requests_for_tests)
24 : allow_localhost_requests_(allow_local_host_requests_for_tests),
25 last_connection_change_(base::TimeTicks::Now()),
26 current_connection_type_(NetworkChangeNotifier::GetConnectionType()),
27 bytes_read_since_last_connection_change_(false),
28 peak_kbps_since_last_connection_change_(0) {
29 static_assert(kMinRequestDurationMicroseconds > 0,
30 "Minimum request duration must be > 0");
31 NetworkChangeNotifier::AddConnectionTypeObserver(this);
34 NetworkQualityEstimator::~NetworkQualityEstimator() {
35 DCHECK(thread_checker_.CalledOnValidThread());
36 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
39 void NetworkQualityEstimator::NotifyDataReceived(const URLRequest& request,
40 int64_t prefilter_bytes_read) {
41 DCHECK(thread_checker_.CalledOnValidThread());
42 DCHECK_GT(prefilter_bytes_read, 0);
44 if (!request.url().is_valid() ||
45 (!allow_localhost_requests_ && IsLocalhost(request.url().host())) ||
46 !request.url().SchemeIsHTTPOrHTTPS() ||
47 // Verify that response headers are received, so it can be ensured that
48 // response is not cached.
49 request.response_info().response_time.is_null() || request.was_cached() ||
50 request.creation_time() < last_connection_change_) {
51 return;
54 base::TimeTicks now = base::TimeTicks::Now();
55 base::TimeDelta request_duration = now - request.creation_time();
56 DCHECK_GE(request_duration, base::TimeDelta());
57 if (!bytes_read_since_last_connection_change_)
58 fastest_RTT_since_last_connection_change_ = request_duration;
60 bytes_read_since_last_connection_change_ = true;
61 if (request_duration < fastest_RTT_since_last_connection_change_)
62 fastest_RTT_since_last_connection_change_ = request_duration;
64 // Ignore tiny transfers which will not produce accurate rates.
65 // Ignore short duration transfers.
66 if (prefilter_bytes_read >= kMinTransferSizeInBytes &&
67 request_duration >=
68 base::TimeDelta::FromMicroseconds(kMinRequestDurationMicroseconds)) {
69 uint64_t kbps = static_cast<uint64_t>(prefilter_bytes_read * 8 * 1000 /
70 request_duration.InMicroseconds());
71 if (kbps > peak_kbps_since_last_connection_change_)
72 peak_kbps_since_last_connection_change_ = kbps;
76 void NetworkQualityEstimator::OnConnectionTypeChanged(
77 NetworkChangeNotifier::ConnectionType type) {
78 DCHECK(thread_checker_.CalledOnValidThread());
79 if (bytes_read_since_last_connection_change_) {
80 switch (current_connection_type_) {
81 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
82 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown",
83 fastest_RTT_since_last_connection_change_);
84 break;
85 case NetworkChangeNotifier::CONNECTION_ETHERNET:
86 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Ethernet",
87 fastest_RTT_since_last_connection_change_);
88 break;
89 case NetworkChangeNotifier::CONNECTION_WIFI:
90 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Wifi",
91 fastest_RTT_since_last_connection_change_);
92 break;
93 case NetworkChangeNotifier::CONNECTION_2G:
94 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.2G",
95 fastest_RTT_since_last_connection_change_);
96 break;
97 case NetworkChangeNotifier::CONNECTION_3G:
98 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.3G",
99 fastest_RTT_since_last_connection_change_);
100 break;
101 case NetworkChangeNotifier::CONNECTION_4G:
102 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.4G",
103 fastest_RTT_since_last_connection_change_);
104 break;
105 case NetworkChangeNotifier::CONNECTION_NONE:
106 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.None",
107 fastest_RTT_since_last_connection_change_);
108 break;
109 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
110 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Bluetooth",
111 fastest_RTT_since_last_connection_change_);
112 break;
113 default:
114 NOTREACHED();
115 break;
119 if (peak_kbps_since_last_connection_change_) {
120 switch (current_connection_type_) {
121 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
122 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Unknown",
123 peak_kbps_since_last_connection_change_);
124 break;
125 case NetworkChangeNotifier::CONNECTION_ETHERNET:
126 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Ethernet",
127 peak_kbps_since_last_connection_change_);
128 break;
129 case NetworkChangeNotifier::CONNECTION_WIFI:
130 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Wifi",
131 peak_kbps_since_last_connection_change_);
132 break;
133 case NetworkChangeNotifier::CONNECTION_2G:
134 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.2G",
135 peak_kbps_since_last_connection_change_);
136 break;
137 case NetworkChangeNotifier::CONNECTION_3G:
138 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.3G",
139 peak_kbps_since_last_connection_change_);
140 break;
141 case NetworkChangeNotifier::CONNECTION_4G:
142 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.4G",
143 peak_kbps_since_last_connection_change_);
144 break;
145 case NetworkChangeNotifier::CONNECTION_NONE:
146 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.None",
147 peak_kbps_since_last_connection_change_);
148 break;
149 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
150 UMA_HISTOGRAM_COUNTS("NQE.PeakKbps.Bluetooth",
151 peak_kbps_since_last_connection_change_);
152 break;
153 default:
154 NOTREACHED();
155 break;
159 last_connection_change_ = base::TimeTicks::Now();
160 bytes_read_since_last_connection_change_ = false;
161 peak_kbps_since_last_connection_change_ = 0;
162 current_connection_type_ = type;
165 NetworkQuality NetworkQualityEstimator::GetEstimate() const {
166 DCHECK(thread_checker_.CalledOnValidThread());
168 if (!bytes_read_since_last_connection_change_) {
169 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0,
170 peak_kbps_since_last_connection_change_, 0);
172 if (!peak_kbps_since_last_connection_change_) {
173 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1,
174 peak_kbps_since_last_connection_change_, 0);
176 return NetworkQuality(fastest_RTT_since_last_connection_change_, 0.1,
177 peak_kbps_since_last_connection_change_, 0.1);
180 } // namespace net