shill: cellular: Track auto-connect metrics.
Network.Shill.Cellular.AutoConnectTries and
Network.Shill.Cellular.AutoConnectTotalTime.
BUG=chromium-os:38406
TEST=Connect modem via auto-connect and check chrome://histograms
Change-Id: I79c2db2b8f4897779275675c9c0fb6278298d462
Reviewed-on: https://gerrit.chromium.org/gerrit/42361
Commit-Queue: Thieu Le <thieule@chromium.org>
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 6a685a5..6189942 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -447,8 +447,11 @@
weak_ptr_factory_.GetWeakPtr());
OnConnecting();
capability_->Connect(properties, error, cb);
- if (error->IsSuccess())
- metrics()->NotifyDeviceConnectStarted(interface_index());
+ if (!error->IsSuccess())
+ return;
+
+ bool is_auto_connecting = service_.get() && service_->is_auto_connecting();
+ metrics()->NotifyDeviceConnectStarted(interface_index(), is_auto_connecting);
}
// Note that there's no ResultCallback argument to this,
diff --git a/cellular_service.cc b/cellular_service.cc
index 24bc7b3..c916b9e 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -93,7 +93,8 @@
: Service(control_interface, dispatcher, metrics, manager,
Technology::kCellular),
activate_over_non_cellular_network_(false),
- cellular_(device) {
+ cellular_(device),
+ is_auto_connecting_(false) {
set_connectable(true);
PropertyStore *store = this->mutable_store();
store->RegisterConstBool(kActivateOverNonCellularNetworkProperty,
@@ -275,6 +276,12 @@
storage->DeleteKey(storage_group, key);
}
+void CellularService::AutoConnect() {
+ is_auto_connecting_ = true;
+ Service::AutoConnect();
+ is_auto_connecting_ = false;
+}
+
void CellularService::Connect(Error *error) {
Service::Connect(error);
cellular_->Connect(error);
diff --git a/cellular_service.h b/cellular_service.h
index 8af31e1..e665e56 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -61,6 +61,7 @@
virtual ~CellularService();
// Inherited from Service.
+ virtual void AutoConnect();
virtual void Connect(Error *error);
virtual void Disconnect(Error *error);
virtual void ActivateCellularModem(const std::string &carrier,
@@ -95,6 +96,10 @@
void SetRoamingState(const std::string &state);
const std::string &roaming_state() const { return roaming_state_; }
+ bool is_auto_connecting() const {
+ return is_auto_connecting_;
+ }
+
// Overrides Load and Save from parent Service class. We will call
// the parent method.
virtual bool Load(StoreInterface *storage);
@@ -168,6 +173,12 @@
CellularRefPtr cellular_;
+ // Flag indicating that a connect request is an auto-connect request.
+ // Note: Since Connect() is asynchronous, this flag is only set during the
+ // call to Connect(). It does not remain set while the async request is
+ // in flight.
+ bool is_auto_connecting_;
+
DISALLOW_COPY_AND_ASSIGN(CellularService);
};
diff --git a/metrics.cc b/metrics.cc
index abd5c7a..5220a25 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -198,6 +198,17 @@
const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
+const char Metrics::kMetricCellularAutoConnectTries[] =
+ "Network.Shill.Cellular.AutoConnectTries";
+const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
+const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
+const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
+const char Metrics::kMetricCellularAutoConnectTotalTime[] =
+ "Network.Shill.Cellular.AutoConnectTotalTime";
+const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
+ 60 * 1000; // 60 seconds
+const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
+const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
Metrics::Metrics()
@@ -649,6 +660,13 @@
kMetricTimeToConnectMillisecondsMin,
kMetricTimeToConnectMillisecondsMax,
kMetricTimeToConnectMillisecondsNumBuckets));
+ device_metrics->auto_connect_tries = 0;
+ device_metrics->auto_connect_timer.reset(
+ new chromeos_metrics::TimerReporter(
+ kMetricCellularAutoConnectTotalTime,
+ kMetricCellularAutoConnectTotalTimeMin,
+ kMetricCellularAutoConnectTotalTimeMax,
+ kMetricCellularAutoConnectTotalTimeNumBuckets));
}
bool Metrics::IsDeviceRegistered(int interface_index,
@@ -732,11 +750,20 @@
device_metrics->scan_timer->ReportMilliseconds();
}
-void Metrics::NotifyDeviceConnectStarted(int interface_index) {
+void Metrics::NotifyDeviceConnectStarted(int interface_index,
+ bool is_auto_connecting) {
DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
if (device_metrics == NULL)
return;
device_metrics->connect_timer->Start();
+
+ if (is_auto_connecting) {
+ device_metrics->auto_connect_tries++;
+ if (device_metrics->auto_connect_tries == 1)
+ device_metrics->auto_connect_timer->Start();
+ } else {
+ AutoConnectMetricsReset(device_metrics);
+ }
}
void Metrics::NotifyDeviceConnectFinished(int interface_index) {
@@ -745,6 +772,21 @@
return;
device_metrics->connect_timer->Stop();
device_metrics->connect_timer->ReportMilliseconds();
+
+ if (device_metrics->auto_connect_tries > 0) {
+ device_metrics->auto_connect_timer->Stop();
+ base::TimeDelta elapsed_time;
+ device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
+ if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
+ return;
+ device_metrics->auto_connect_timer->ReportMilliseconds();
+ SendToUMA(kMetricCellularAutoConnectTries,
+ device_metrics->auto_connect_tries,
+ kMetricCellularAutoConnectTriesMin,
+ kMetricCellularAutoConnectTriesMax,
+ kMetricCellularAutoConnectTriesNumBuckets);
+ AutoConnectMetricsReset(device_metrics);
+ }
}
void Metrics::NotifyCellularDeviceDrop(const string &network_technology,
@@ -845,6 +887,11 @@
return it->second.get();
}
+void Metrics::AutoConnectMetricsReset(DeviceMetrics *device_metrics) {
+ device_metrics->auto_connect_tries = 0;
+ device_metrics->auto_connect_timer->Reset();
+}
+
void Metrics::set_library(MetricsLibraryInterface *library) {
chromeos_metrics::TimerReporter::set_metrics_lib(library);
library_ = library;
diff --git a/metrics.h b/metrics.h
index bd81924..57c1ce7 100644
--- a/metrics.h
+++ b/metrics.h
@@ -282,6 +282,14 @@
static const int kMetricCellularSignalStrengthBeforeDropMax;
static const int kMetricCellularSignalStrengthBeforeDropMin;
static const int kMetricCellularSignalStrengthBeforeDropNumBuckets;
+ static const char kMetricCellularAutoConnectTries[];
+ static const int kMetricCellularAutoConnectTriesMax;
+ static const int kMetricCellularAutoConnectTriesMin;
+ static const int kMetricCellularAutoConnectTriesNumBuckets;
+ static const char kMetricCellularAutoConnectTotalTime[];
+ static const int kMetricCellularAutoConnectTotalTimeMax;
+ static const int kMetricCellularAutoConnectTotalTimeMin;
+ static const int kMetricCellularAutoConnectTotalTimeNumBuckets;
Metrics();
virtual ~Metrics();
@@ -390,7 +398,8 @@
void NotifyDeviceScanFinished(int interface_index);
// Notifies this object that a device has started the connect process.
- void NotifyDeviceConnectStarted(int interface_index);
+ void NotifyDeviceConnectStarted(int interface_index,
+ bool is_auto_connecting);
// Notifies this object that a device has completed the connect process.
void NotifyDeviceConnectFinished(int interface_index);
@@ -447,6 +456,8 @@
scoped_ptr<chromeos_metrics::TimerReporter> disable_timer;
scoped_ptr<chromeos_metrics::TimerReporter> scan_timer;
scoped_ptr<chromeos_metrics::TimerReporter> connect_timer;
+ int auto_connect_tries;
+ scoped_ptr<chromeos_metrics::TimerReporter> auto_connect_timer;
};
typedef std::map<const int, std::tr1::shared_ptr<DeviceMetrics> >
DeviceMetricsLookupMap;
@@ -472,6 +483,7 @@
void SendServiceFailure(const Service *service);
DeviceMetrics *GetDeviceMetrics (int interface_index) const;
+ void AutoConnectMetricsReset(DeviceMetrics *device_metrics);
// For unit test purposes.
void set_library(MetricsLibraryInterface *library);
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index cf99050..ab8875f 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -343,7 +343,7 @@
Metrics::kMetricTimeToConnectMillisecondsNumBuckets));
const int kInterfaceIndex = 1;
metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
- metrics_.NotifyDeviceConnectStarted(kInterfaceIndex);
+ metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, false);
metrics_.NotifyDeviceConnectFinished(kInterfaceIndex);
}
@@ -417,6 +417,32 @@
metrics_.NotifyDeviceScanFinished(kInterfaceIndex);
}
+TEST_F(MetricsTest, CellularAutoConnect) {
+ EXPECT_CALL(library_,
+ SendToUMA("Network.Shill.Cellular.TimeToConnect",
+ Ge(0),
+ Metrics::kMetricTimeToConnectMillisecondsMin,
+ Metrics::kMetricTimeToConnectMillisecondsMax,
+ Metrics::kMetricTimeToConnectMillisecondsNumBuckets));
+ EXPECT_CALL(library_,
+ SendToUMA(Metrics::kMetricCellularAutoConnectTotalTime,
+ Ge(0),
+ Metrics::kMetricCellularAutoConnectTotalTimeMin,
+ Metrics::kMetricCellularAutoConnectTotalTimeMax,
+ Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets));
+ EXPECT_CALL(library_,
+ SendToUMA(Metrics::kMetricCellularAutoConnectTries,
+ 2,
+ Metrics::kMetricCellularAutoConnectTriesMin,
+ Metrics::kMetricCellularAutoConnectTriesMax,
+ Metrics::kMetricCellularAutoConnectTriesNumBuckets));
+ const int kInterfaceIndex = 1;
+ metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
+ metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, true);
+ metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, true);
+ metrics_.NotifyDeviceConnectFinished(kInterfaceIndex);
+}
+
TEST_F(MetricsTest, CellularDrop) {
const char *kUMATechnologyStrings[] = {
flimflam::kNetworkTechnology1Xrtt,