shill: Add support for device metrics.
Also add first device metrics, TimeToInitialize, which is the time
between when the kernel notifies shill about a link to when a Device
object is created for that link.
BUG=chromium-os:38086
TEST=New unit test and checking chrome://histograms for new metrics
Change-Id: If42081a42eb39b1782e0d7603e5d79116645ebad
Reviewed-on: https://gerrit.chromium.org/gerrit/41794
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
Commit-Queue: Thieu Le <thieule@chromium.org>
diff --git a/device_info.cc b/device_info.cc
index 2e8df1b..75ab479 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -149,6 +149,7 @@
if (Technology::IsPrimaryConnectivityTechnology(device->technology())) {
manager_->RegisterDevice(device);
}
+ metrics_->NotifyDeviceInitialized(device->interface_index());
}
void DeviceInfo::DeregisterDevice(const DeviceRefPtr &device) {
@@ -169,6 +170,7 @@
// for the index. That will be cleaned up by an RTNL message.
iter->second.device = NULL;
}
+ metrics_->DeregisterDevice(device->interface_index());
}
FilePath DeviceInfo::GetDeviceInfoPath(const string &iface_name,
@@ -528,6 +530,7 @@
LOG(ERROR) << "Add Link message does not have IFLA_ADDRESS!";
return;
}
+ metrics_->RegisterDevice(dev_index, technology);
device = CreateDevice(link_name, address, dev_index, technology);
if (device) {
RegisterDevice(device);
diff --git a/metrics.cc b/metrics.cc
index 2d59720..541f761 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -57,6 +57,12 @@
const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
const int Metrics::kMetricTimeToDropSecondsMin = 1;
+const char Metrics::kMetricTimeToInitializeMilliseconds[] =
+ "Network.Shill.%s.TimeToInitialize";
+const int Metrics::kMetricTimeToInitializeMillisecondsMin = 1;
+const int Metrics::kMetricTimeToInitializeMillisecondsMax = 20 * 1000;
+const int Metrics::kMetricTimeToInitializeMillisecondsNumBuckets = 20;
+
const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
"Network.Shill.%s.TimeResumeToReady";
const char Metrics::kMetricTimeToConfigMilliseconds[] =
@@ -554,6 +560,37 @@
SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
}
+void Metrics::RegisterDevice(int interface_index,
+ Technology::Identifier technology) {
+ shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
+ devices_metrics_[interface_index] = device_metrics;
+ string histogram = GetFullMetricName(kMetricTimeToInitializeMilliseconds,
+ technology);
+ device_metrics->initialization_timer.reset(
+ new chromeos_metrics::TimerReporter(
+ histogram,
+ kMetricTimeToInitializeMillisecondsMin,
+ kMetricTimeToInitializeMillisecondsMax,
+ kMetricTimeToInitializeMillisecondsNumBuckets));
+ device_metrics->initialization_timer->Start();
+}
+
+void Metrics::DeregisterDevice(int interface_index) {
+ devices_metrics_.erase(interface_index);
+}
+
+void Metrics::NotifyDeviceInitialized(int interface_index) {
+ DeviceMetricsLookupMap::iterator it = devices_metrics_.find(interface_index);
+ if (it == devices_metrics_.end()) {
+ SLOG(Metrics, 1) << "device " << interface_index << " not found";
+ DCHECK(false);
+ return;
+ }
+ DeviceMetrics *device_metrics = it->second.get();
+ device_metrics->initialization_timer->Stop();
+ device_metrics->initialization_timer->ReportMilliseconds();
+}
+
bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
return library_->SendEnumToUMA(name, sample, max);
}
diff --git a/metrics.h b/metrics.h
index ec40c2e..1cad04a 100644
--- a/metrics.h
+++ b/metrics.h
@@ -176,6 +176,10 @@
static const char kMetricTimeToDropSeconds[];
static const int kMetricTimeToDropSecondsMax;
static const int kMetricTimeToDropSecondsMin;
+ static const char kMetricTimeToInitializeMilliseconds[];
+ static const int kMetricTimeToInitializeMillisecondsMin;
+ static const int kMetricTimeToInitializeMillisecondsMax;
+ static const int kMetricTimeToInitializeMillisecondsNumBuckets;
static const char kMetricTimeToJoinMilliseconds[];
static const char kMetricTimeToOnlineMilliseconds[];
static const char kMetricTimeToPortalMilliseconds[];
@@ -305,6 +309,18 @@
void Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
IEEE_80211::WiFiReasonCode reason);
+ // Registers a device with this object so the device can use the timers to
+ // track state transition metrics.
+ void RegisterDevice(int interface_index,
+ Technology::Identifier technology);
+
+ // Deregisters the device from this class. All state transition timers
+ // will be removed.
+ void DeregisterDevice(int interface_index);
+
+ // Notifies this object that a device has been initialized.
+ void NotifyDeviceInitialized(int interface_index);
+
// Sends linear histogram data to UMA.
virtual bool SendEnumToUMA(const std::string &name, int sample, int max);
@@ -343,6 +359,13 @@
typedef std::map<const Service *, std::tr1::shared_ptr<ServiceMetrics> >
ServiceMetricsLookupMap;
+ struct DeviceMetrics {
+ DeviceMetrics() {}
+ scoped_ptr<chromeos_metrics::TimerReporter> initialization_timer;
+ };
+ typedef std::map<const int, std::tr1::shared_ptr<DeviceMetrics> >
+ DeviceMetricsLookupMap;
+
static const uint16 kWiFiBandwidth5MHz;
static const uint16 kWiFiBandwidth20MHz;
static const uint16 kWiFiFrequency2412;
@@ -392,6 +415,7 @@
scoped_ptr<chromeos_metrics::Timer> time_resume_to_ready_timer_;
scoped_ptr<chromeos_metrics::Timer> time_termination_actions_timer;
bool collect_bootstats_;
+ DeviceMetricsLookupMap devices_metrics_;
DISALLOW_COPY_AND_ASSIGN(Metrics);
};
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index 864b121..9988e09 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -330,6 +330,18 @@
Metrics::PortalDetectionResultToEnum(result));
}
+TEST_F(MetricsTest, TimeToInitialize) {
+ EXPECT_CALL(library_,
+ SendToUMA("Network.Shill.Cellular.TimeToInitialize",
+ Ge(0),
+ Metrics::kMetricTimeToInitializeMillisecondsMin,
+ Metrics::kMetricTimeToInitializeMillisecondsMax,
+ Metrics::kMetricTimeToInitializeMillisecondsNumBuckets));
+ const int kInterfaceIndex = 1;
+ metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
+ metrics_.NotifyDeviceInitialized(kInterfaceIndex);
+}
+
#ifndef NDEBUG
typedef MetricsTest MetricsDeathTest;