Index: net/base/network_change_notifier.cc |
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc |
index 8c5f4461d96b66189d8de1c1a95fa7ac002830a6..0bee27b6f5dfc4255b8aaf9e9db2b5253c4f8ef0 100644 |
--- a/net/base/network_change_notifier.cc |
+++ b/net/base/network_change_notifier.cc |
@@ -4,7 +4,10 @@ |
#include "net/base/network_change_notifier.h" |
#include "net/base/network_change_notifier_factory.h" |
+#include "base/metrics/histogram.h" |
#include "build/build_config.h" |
+#include "googleurl/src/gurl.h" |
+#include "net/base/net_util.h" |
#if defined(OS_WIN) |
#include "net/base/network_change_notifier_win.h" |
#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) |
@@ -35,6 +38,111 @@ class MockNetworkChangeNotifier : public NetworkChangeNotifier { |
} // namespace |
+// The main observer class that records UMAs for network events. |
+class HistogramWatcher |
+ : public NetworkChangeNotifier::ConnectionTypeObserver, |
+ public NetworkChangeNotifier::IPAddressObserver, |
+ public NetworkChangeNotifier::DNSObserver { |
+ public: |
+ HistogramWatcher() |
+ : last_ip_address_change_(base::TimeTicks::Now()), |
+ last_connection_change_(base::TimeTicks::Now()), |
+ last_dns_change_(base::TimeTicks::Now()), |
+ last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), |
+ offline_packets_received_(0) {} |
+ |
+ // Registers our three Observer implementations. This is called from the |
+ // network thread so that our Observer implementations are also called |
+ // from the network thread. This avoids multi-threaded race conditions |
+ // because the only other interface, |NotifyDataReceived| is also |
+ // only called from the network thread. |
+ void InitHistogramWatcher(); |
szym
2012/08/08 20:41:17
You could use base::NonThreadSafe to enforce the t
pauljensen
2012/08/13 15:42:04
As we discussed this would add so much complexity
|
+ |
+ virtual ~HistogramWatcher() {} |
+ |
+ // NetworkChangeNotifier::IPAddressObserver implementation. |
+ virtual void OnIPAddressChanged() OVERRIDE { |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange", |
+ SinceLast(&last_ip_address_change_)); |
szym
2012/08/08 20:41:17
I'm a bit uneasy about using a function call with
pauljensen
2012/08/13 15:42:04
I don't like it either. I wish the histograms wer
|
+ } |
+ |
+ // NetworkChangeNotifier::ConnectionTypeObserver implementation. |
+ virtual void OnConnectionTypeChanged( |
+ NetworkChangeNotifier::ConnectionType type) OVERRIDE { |
+ if (type != NetworkChangeNotifier::CONNECTION_NONE) { |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", |
+ SinceLast(&last_connection_change_)); |
+ |
+ if (offline_packets_received_) { |
+ if ((last_connection_change_ - last_offline_packet_received_) < |
+ base::TimeDelta::FromSeconds(5)) { |
+ // we can compare this sum with the sum of NCN.OfflineDataRecv |
szym
2012/08/08 20:41:17
nit: Format like a sentence, but maybe just remove
pauljensen
2012/08/13 15:42:04
Done.
|
+ UMA_HISTOGRAM_COUNTS_10000( |
+ "NCN.OfflineDataRecvAny5sBeforeOnline", |
+ offline_packets_received_); |
+ } |
+ |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline", |
+ last_connection_change_ - |
+ last_offline_packet_received_); |
+ } |
+ } else { |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", |
+ SinceLast(&last_connection_change_)); |
+ } |
+ |
+ offline_packets_received_ = 0; |
+ last_connection_type_ = type; |
+ } |
+ |
+ // NetworkChangeNotifier::DNSObserver implementation. |
+ virtual void OnDNSChanged(unsigned detail) OVERRIDE { |
+ if (detail == NetworkChangeNotifier::CHANGE_DNS_SETTINGS) { |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange", |
+ SinceLast(&last_dns_change_)); |
+ } |
+ } |
+ |
+ // Record histogram data whenever we receive a packet but think we're |
+ // offline. Should only be called from the network thread. |
+ void NotifyDataReceived(const GURL& source) { |
+ if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE || |
+ IsLocalhost(source.host()) || |
+ !(source.SchemeIs("http") || source.SchemeIs("https"))) |
szym
2012/08/08 20:41:17
nit: This might need braces.
pauljensen
2012/08/13 15:42:04
Done.
|
+ return; |
+ base::TimeTicks current_time = base::TimeTicks::Now(); |
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv", |
+ current_time - last_connection_change_); |
+ offline_packets_received_++; |
+ last_offline_packet_received_ = current_time; |
+ } |
+ |
+ private: |
+ base::TimeTicks last_ip_address_change_; |
+ base::TimeTicks last_connection_change_; |
+ base::TimeTicks last_dns_change_; |
+ base::TimeTicks last_offline_packet_received_; |
+ NetworkChangeNotifier::ConnectionType last_connection_type_; |
+ int32 offline_packets_received_; |
+ |
+ static base::TimeDelta SinceLast(base::TimeTicks *last_time); |
szym
2012/08/08 20:41:17
Method declarations should precede field declarati
pauljensen
2012/08/13 15:42:04
Done.
|
+ |
+ DISALLOW_COPY_AND_ASSIGN(HistogramWatcher); |
+}; |
+ |
+base::TimeDelta HistogramWatcher::SinceLast(base::TimeTicks *last_time) { |
szym
2012/08/08 20:41:17
Why is this implemented here rather than inline as
pauljensen
2012/08/13 15:42:04
Done.
|
+ base::TimeTicks current_time = base::TimeTicks::Now(); |
+ base::TimeDelta delta = current_time - *last_time; |
+ *last_time = current_time; |
+ return delta; |
+} |
+ |
+void HistogramWatcher::InitHistogramWatcher() { |
szym
2012/08/08 20:41:17
ditto: why implemented out-of-line?
pauljensen
2012/08/13 15:42:04
Done.
|
+ NetworkChangeNotifier::AddConnectionTypeObserver(this); |
+ NetworkChangeNotifier::AddIPAddressObserver(this); |
+ NetworkChangeNotifier::AddDNSObserver(this); |
+} |
+ |
NetworkChangeNotifier::~NetworkChangeNotifier() { |
DCHECK_EQ(this, g_network_change_notifier); |
g_network_change_notifier = NULL; |
@@ -84,6 +192,20 @@ NetworkChangeNotifier::GetConnectionType() { |
CONNECTION_UNKNOWN; |
} |
+// static |
+void NetworkChangeNotifier::NotifyDataReceived(const GURL& source) { |
+ if (!g_network_change_notifier) |
+ return; |
+ g_network_change_notifier->histogram_watcher_->NotifyDataReceived(source); |
+} |
+ |
+// static |
+void NetworkChangeNotifier::InitHistogramWatcher() { |
+ if (!g_network_change_notifier) |
+ return; |
+ g_network_change_notifier->histogram_watcher_->InitHistogramWatcher(); |
+} |
+ |
#if defined(OS_LINUX) |
// static |
const internal::AddressTrackerLinux* |
@@ -162,6 +284,7 @@ NetworkChangeNotifier::NetworkChangeNotifier() |
watching_dns_(false) { |
DCHECK(!g_network_change_notifier); |
g_network_change_notifier = this; |
+ histogram_watcher_.reset(new HistogramWatcher()); |
szym
2012/08/08 20:41:17
nit: Put this in the initializer list.
pauljensen
2012/08/13 15:42:04
It must appear after |g_network_change_notifier =
|
} |
#if defined(OS_LINUX) |