blob: 903bd0dbe2c3ca6fc8876d87238d530edfbe6a89 [file] [log] [blame]
Thieu Lead1ec2c2012-01-05 23:39:48 +00001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Thieu Le48e6d6d2011-12-06 00:40:27 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/metrics.h"
6
Thieu Le6c1e3bb2013-02-06 15:20:35 -08007#include <base/bind.h>
Thieu Le48e6d6d2011-12-06 00:40:27 +00008#include <base/string_util.h>
9#include <base/stringprintf.h>
Thieu Lead1ec2c2012-01-05 23:39:48 +000010#include <chromeos/dbus/service_constants.h>
Darin Petkov58f0b6d2012-06-12 12:52:30 +020011#include <metrics/bootstat.h>
Thieu Le48e6d6d2011-12-06 00:40:27 +000012
Wade Guthried4977f22012-08-22 12:37:54 -070013#include "shill/ieee80211.h"
Paul Stewartff845fc2012-08-07 07:28:44 -070014#include "shill/link_monitor.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070015#include "shill/logging.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000016#include "shill/wifi_service.h"
17
Thieu Le6c1e3bb2013-02-06 15:20:35 -080018using base::Bind;
19using base::Unretained;
Thieu Le48e6d6d2011-12-06 00:40:27 +000020using std::string;
21using std::tr1::shared_ptr;
22
23namespace shill {
24
Thieu Le48e6d6d2011-12-06 00:40:27 +000025// static
Thieu Lec31e6f92012-08-03 13:08:58 -070026// Our disconnect enumeration values are 0 (System Disconnect) and
27// 1 (User Disconnect), see histograms.xml, but Chrome needs a minimum
28// enum value of 1 and the minimum number of buckets needs to be 3 (see
29// histogram.h). Instead of remapping System Disconnect to 1 and
30// User Disconnect to 2, we can just leave the enumerated values as-is
31// because Chrome implicitly creates a [0-1) bucket for us. Using Min=1,
32// Max=2 and NumBuckets=3 gives us the following three buckets:
33// [0-1), [1-2), [2-INT_MAX). We end up with an extra bucket [2-INT_MAX)
34// that we can safely ignore.
Thieu Le67370f62012-02-14 23:01:42 +000035const char Metrics::kMetricDisconnect[] = "Network.Shill.%s.Disconnect";
Thieu Lec31e6f92012-08-03 13:08:58 -070036const int Metrics::kMetricDisconnectMax = 2;
37const int Metrics::kMetricDisconnectMin = 1;
38const int Metrics::kMetricDisconnectNumBuckets = 3;
Thieu Le67370f62012-02-14 23:01:42 +000039
Paul Stewarte4cedde2013-07-17 08:56:44 -070040const char Metrics::kMetricNetworkApMode[] = "Network.Shill.%s.ApMode";
Thieu Le48e6d6d2011-12-06 00:40:27 +000041const char Metrics::kMetricNetworkChannel[] = "Network.Shill.%s.Channel";
42const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
Paul Stewart21f40962013-03-01 14:27:28 -080043const char Metrics::kMetricNetworkEapInnerProtocol[] =
44 "Network.Shill.%s.EapInnerProtocol";
45const int Metrics::kMetricNetworkEapInnerProtocolMax =
46 Metrics::kEapInnerProtocolMax;
47const char Metrics::kMetricNetworkEapOuterProtocol[] =
48 "Network.Shill.%s.EapOuterProtocol";
49const int Metrics::kMetricNetworkEapOuterProtocolMax =
50 Metrics::kEapOuterProtocolMax;
Thieu Lead1ec2c2012-01-05 23:39:48 +000051const char Metrics::kMetricNetworkPhyMode[] = "Network.Shill.%s.PhyMode";
52const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
53const char Metrics::kMetricNetworkSecurity[] = "Network.Shill.%s.Security";
54const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
Thieu Le48e6d6d2011-12-06 00:40:27 +000055const char Metrics::kMetricNetworkServiceErrors[] =
56 "Network.Shill.ServiceErrors";
57const int Metrics::kMetricNetworkServiceErrorsMax = Service::kFailureMax;
Paul Stewart23b393a2012-09-25 21:21:06 -070058const char Metrics::kMetricNetworkSignalStrength[] =
59 "Network.Shill.%s.SignalStrength";
60const int Metrics::kMetricNetworkSignalStrengthMax = 200;
61const int Metrics::kMetricNetworkSignalStrengthMin = 0;
62const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
Thieu Lea20cbc22012-01-09 22:01:43 +000063
64const char Metrics::kMetricTimeOnlineSeconds[] = "Network.Shill.%s.TimeOnline";
65const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
66const int Metrics::kMetricTimeOnlineSecondsMin = 1;
67
Thieu Lecdb5a212013-01-25 11:17:18 -080068const char Metrics::kMetricTimeToConnectMilliseconds[] =
69 "Network.Shill.%s.TimeToConnect";
70const int Metrics::kMetricTimeToConnectMillisecondsMax =
71 60 * 1000; // 60 seconds
72const int Metrics::kMetricTimeToConnectMillisecondsMin = 1;
73const int Metrics::kMetricTimeToConnectMillisecondsNumBuckets = 60;
74
Wade Guthrie44f290d2013-05-28 10:16:25 -070075const char Metrics::kMetricTimeToScanAndConnectMilliseconds[] =
76 "Network.Shill.%s.TimeToScanAndConnect";
77
Thieu Lea20cbc22012-01-09 22:01:43 +000078const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
79const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
80const int Metrics::kMetricTimeToDropSecondsMin = 1;
81
Thieu Lea2519bf2013-01-23 16:51:54 -080082const char Metrics::kMetricTimeToDisableMilliseconds[] =
83 "Network.Shill.%s.TimeToDisable";
84const int Metrics::kMetricTimeToDisableMillisecondsMax =
85 60 * 1000; // 60 seconds
86const int Metrics::kMetricTimeToDisableMillisecondsMin = 1;
87const int Metrics::kMetricTimeToDisableMillisecondsNumBuckets = 60;
88
Thieu Lece4483e2013-01-23 15:12:03 -080089const char Metrics::kMetricTimeToEnableMilliseconds[] =
90 "Network.Shill.%s.TimeToEnable";
91const int Metrics::kMetricTimeToEnableMillisecondsMax =
92 60 * 1000; // 60 seconds
93const int Metrics::kMetricTimeToEnableMillisecondsMin = 1;
94const int Metrics::kMetricTimeToEnableMillisecondsNumBuckets = 60;
95
Thieu Lec8078a62013-01-22 18:01:12 -080096const char Metrics::kMetricTimeToInitializeMilliseconds[] =
97 "Network.Shill.%s.TimeToInitialize";
Thieu Le769d50d2013-01-23 17:11:59 -080098const int Metrics::kMetricTimeToInitializeMillisecondsMax =
99 30 * 1000; // 30 seconds
Thieu Lece4483e2013-01-23 15:12:03 -0800100const int Metrics::kMetricTimeToInitializeMillisecondsMin = 1;
Thieu Le769d50d2013-01-23 17:11:59 -0800101const int Metrics::kMetricTimeToInitializeMillisecondsNumBuckets = 30;
Thieu Lec8078a62013-01-22 18:01:12 -0800102
Thieu Leb84ba342012-03-02 15:15:19 -0800103const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
104 "Network.Shill.%s.TimeResumeToReady";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000105const char Metrics::kMetricTimeToConfigMilliseconds[] =
106 "Network.Shill.%s.TimeToConfig";
107const char Metrics::kMetricTimeToJoinMilliseconds[] =
108 "Network.Shill.%s.TimeToJoin";
109const char Metrics::kMetricTimeToOnlineMilliseconds[] =
110 "Network.Shill.%s.TimeToOnline";
111const char Metrics::kMetricTimeToPortalMilliseconds[] =
112 "Network.Shill.%s.TimeToPortal";
Thieu Le18c11072013-01-28 17:21:37 -0800113
114const char Metrics::kMetricTimeToScanMilliseconds[] =
115 "Network.Shill.%s.TimeToScan";
116const int Metrics::kMetricTimeToScanMillisecondsMax = 180 * 1000; // 3 minutes
117const int Metrics::kMetricTimeToScanMillisecondsMin = 1;
118const int Metrics::kMetricTimeToScanMillisecondsNumBuckets = 90;
119
Thieu Lea20cbc22012-01-09 22:01:43 +0000120const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
121const int Metrics::kTimerHistogramMillisecondsMin = 1;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000122const int Metrics::kTimerHistogramNumBuckets = 50;
123
Thieu Le85e050b2012-03-13 15:04:38 -0700124const char Metrics::kMetricPortalAttempts[] =
125 "Network.Shill.%s.PortalAttempts";
126const int Metrics::kMetricPortalAttemptsMax =
127 PortalDetector::kMaxRequestAttempts;
128const int Metrics::kMetricPortalAttemptsMin = 1;
129const int Metrics::kMetricPortalAttemptsNumBuckets =
130 Metrics::kMetricPortalAttemptsMax;
131
132const char Metrics::kMetricPortalAttemptsToOnline[] =
133 "Network.Shill.%s.PortalAttemptsToOnline";
134const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
135const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
136const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
137
138const char Metrics::kMetricPortalResult[] = "Network.Shill.%s.PortalResult";
139
Wade Guthrie60a37062013-04-02 11:39:09 -0700140const char Metrics::kMetricFrequenciesConnectedEver[] =
141 "Network.Shill.WiFi.FrequenciesConnectedEver";
142const int Metrics::kMetricFrequenciesConnectedMax = 50;
143const int Metrics::kMetricFrequenciesConnectedMin = 1;
144const int Metrics::kMetricFrequenciesConnectedNumBuckets = 50;
145
Wade Guthrieb9e0ee72013-05-31 09:23:30 -0700146const char Metrics::kMetricScanResult[] =
147 "Network.Shill.WiFi.ScanResult";
Wade Guthrief22681f2013-05-31 11:46:31 -0700148const char Metrics::kMetricWiFiScanTimeInEbusyMilliseconds[] =
149 "Network.Shill.WiFi.ScanTimeInEbusy";
150
Arman Ugurayab22c162012-10-08 19:08:38 -0700151const char Metrics::kMetricTerminationActionTimeOnTerminate[] =
152 "Network.Shill.TerminationActionTime.OnTerminate";
153const char Metrics::kMetricTerminationActionResultOnTerminate[] =
154 "Network.Shill.TerminationActionResult.OnTerminate";
155const char Metrics::kMetricTerminationActionTimeOnSuspend[] =
156 "Network.Shill.TerminationActionTime.OnSuspend";
157const char Metrics::kMetricTerminationActionResultOnSuspend[] =
158 "Network.Shill.TerminationActionResult.OnSuspend";
159const int Metrics::kMetricTerminationActionTimeMillisecondsMax = 10000;
160const int Metrics::kMetricTerminationActionTimeMillisecondsMin = 1;
Arman Uguray6d528f12012-09-13 13:44:55 -0700161
Thieu Le48e6d6d2011-12-06 00:40:27 +0000162// static
Paul Stewart85aea152013-01-22 09:31:56 -0800163const char Metrics::kMetricServiceFixupEntries[] =
164 "Network.Shill.%s.ServiceFixupEntries";
165
166// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000167const uint16 Metrics::kWiFiBandwidth5MHz = 5;
168const uint16 Metrics::kWiFiBandwidth20MHz = 20;
169const uint16 Metrics::kWiFiFrequency2412 = 2412;
170const uint16 Metrics::kWiFiFrequency2472 = 2472;
171const uint16 Metrics::kWiFiFrequency2484 = 2484;
172const uint16 Metrics::kWiFiFrequency5170 = 5170;
173const uint16 Metrics::kWiFiFrequency5180 = 5180;
174const uint16 Metrics::kWiFiFrequency5230 = 5230;
175const uint16 Metrics::kWiFiFrequency5240 = 5240;
176const uint16 Metrics::kWiFiFrequency5320 = 5320;
177const uint16 Metrics::kWiFiFrequency5500 = 5500;
178const uint16 Metrics::kWiFiFrequency5700 = 5700;
179const uint16 Metrics::kWiFiFrequency5745 = 5745;
180const uint16 Metrics::kWiFiFrequency5825 = 5825;
181
Thieu Leb84ba342012-03-02 15:15:19 -0800182// static
183const char Metrics::kMetricPowerManagerKey[] = "metrics";
184
Paul Stewartff845fc2012-08-07 07:28:44 -0700185// static
186const char Metrics::kMetricLinkMonitorFailure[] =
187 "Network.Shill.%s.LinkMonitorFailure";
188const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
189 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewartf1961f82012-09-11 20:45:39 -0700190const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
191const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700192 LinkMonitor::kTestPeriodMilliseconds;
193const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700194const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
195 "Network.Shill.%s.LinkMonitorSecondsToFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700196const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
197const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
Paul Stewart0443aa52012-08-09 10:43:50 -0700198const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
199const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
200 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
201const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
202 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700203const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
204const int Metrics::kMetricLinkMonitorErrorCountMax =
Paul Stewart0443aa52012-08-09 10:43:50 -0700205 LinkMonitor::kFailureThreshold;
206const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
207 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700208
Wade Guthried4977f22012-08-22 12:37:54 -0700209// static
210const char Metrics::kMetricLinkClientDisconnectReason[] =
211 "Network.Shill.WiFi.ClientDisconnectReason";
212const char Metrics::kMetricLinkApDisconnectReason[] =
213 "Network.Shill.WiFi.ApDisconnectReason";
214const char Metrics::kMetricLinkClientDisconnectType[] =
215 "Network.Shill.WiFi.ClientDisconnectType";
216const char Metrics::kMetricLinkApDisconnectType[] =
217 "Network.Shill.WiFi.ApDisconnectType";
218
Thieu Le26fc01b2013-01-28 12:08:48 -0800219// static
Prathmesh Prabhu08757aa2013-05-15 17:17:33 -0700220const char Metrics::kMetricCellular3GPPRegistrationDelayedDrop[] =
221 "Network.Shill.Cellular.3GPPRegistrationDelayedDrop";
Thieu Le91fccf62013-04-22 15:23:16 -0700222const char Metrics::kMetricCellularAutoConnectTries[] =
223 "Network.Shill.Cellular.AutoConnectTries";
224const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
225const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
226const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
227const char Metrics::kMetricCellularAutoConnectTotalTime[] =
228 "Network.Shill.Cellular.AutoConnectTotalTime";
229const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
230 60 * 1000; // 60 seconds
231const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
232const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
Thieu Le26fc01b2013-01-28 12:08:48 -0800233const char Metrics::kMetricCellularDrop[] =
234 "Network.Shill.Cellular.Drop";
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800235const char Metrics::kMetricCellularDropsPerHour[] =
236 "Network.Shill.Cellular.DropsPerHour";
237const int Metrics::kMetricCellularDropsPerHourMax = 60;
238const int Metrics::kMetricCellularDropsPerHourMin = 1;
239const int Metrics::kMetricCellularDropsPerHourNumBuckets = 10;
Thieu Leb7aa5f72013-01-31 15:57:48 -0800240// The format of FailureReason is different to other metrics because this
241// name is prepended to the error message before the entire string is sent
242// via SendUserActionToUMA.
243const char Metrics::kMetricCellularFailureReason[] =
244 "Network.Shill.Cellular.FailureReason: ";
Thieu Le91fccf62013-04-22 15:23:16 -0700245const char Metrics::kMetricCellularOutOfCreditsReason[] =
246 "Network.Shill.Cellular.OutOfCreditsReason";
Thieu Le26fc01b2013-01-28 12:08:48 -0800247const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
248 "Network.Shill.Cellular.SignalStrengthBeforeDrop";
249const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
250const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
251const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
252
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800253// static
Thieu Le5133b712013-02-19 14:47:21 -0800254const char Metrics::kMetricCorruptedProfile[] =
255 "Network.Shill.CorruptedProfile";
256
257// static
Paul Stewart91a43cb2013-03-02 21:34:15 -0800258const char Metrics::kMetricVpnDriver[] =
259 "Network.Shill.Vpn.Driver";
260const int Metrics::kMetricVpnDriverMax = Metrics::kVpnDriverMax;
261const char Metrics::kMetricVpnRemoteAuthenticationType[] =
262 "Network.Shill.Vpn.RemoteAuthenticationType";
263const int Metrics::kMetricVpnRemoteAuthenticationTypeMax =
264 Metrics::kVpnRemoteAuthenticationTypeMax;
265const char Metrics::kMetricVpnUserAuthenticationType[] =
266 "Network.Shill.Vpn.UserAuthenticationType";
267const int Metrics::kMetricVpnUserAuthenticationTypeMax =
268 Metrics::kVpnUserAuthenticationTypeMax;
269
270// static
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800271const int Metrics::kHourlyTimeoutMilliseconds = 3600 * 1000; // One hour
Wade Guthried4977f22012-08-22 12:37:54 -0700272
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800273
274Metrics::Metrics(EventDispatcher *dispatcher)
275 : dispatcher_(dispatcher),
276 library_(&metrics_library_),
Thieu Lea20cbc22012-01-09 22:01:43 +0000277 last_default_technology_(Technology::kUnknown),
278 was_online_(false),
279 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800280 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200281 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
Arman Ugurayab22c162012-10-08 19:08:38 -0700282 time_termination_actions_timer(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200283 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000284 metrics_library_.Init();
285 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
286}
287
288Metrics::~Metrics() {}
289
290// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000291Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
292 WiFiChannel channel = kWiFiChannelUndef;
293 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
294 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
295 channel = static_cast<WiFiChannel>(
296 kWiFiChannel2412 +
297 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
298 } else if (frequency == kWiFiFrequency2484) {
299 channel = kWiFiChannel2484;
300 } else if (kWiFiFrequency5170 <= frequency &&
301 frequency <= kWiFiFrequency5230) {
302 if ((frequency % kWiFiBandwidth20MHz) == 0)
303 channel = static_cast<WiFiChannel>(
304 kWiFiChannel5180 +
305 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
306 if ((frequency % kWiFiBandwidth20MHz) == 10)
307 channel = static_cast<WiFiChannel>(
308 kWiFiChannel5170 +
309 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
310 } else if (kWiFiFrequency5240 <= frequency &&
311 frequency <= kWiFiFrequency5320) {
312 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
313 channel = static_cast<WiFiChannel>(
314 kWiFiChannel5180 +
315 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
316 } else if (kWiFiFrequency5500 <= frequency &&
317 frequency <= kWiFiFrequency5700) {
318 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
319 channel = static_cast<WiFiChannel>(
320 kWiFiChannel5500 +
321 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
322 } else if (kWiFiFrequency5745 <= frequency &&
323 frequency <= kWiFiFrequency5825) {
324 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
325 channel = static_cast<WiFiChannel>(
326 kWiFiChannel5745 +
327 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
328 }
329 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
330
331 if (channel == kWiFiChannelUndef)
332 LOG(WARNING) << "no mapping for frequency " << frequency;
333 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700334 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000335
336 return channel;
337}
338
Thieu Lead1ec2c2012-01-05 23:39:48 +0000339// static
340Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
Paul Stewarte4cedde2013-07-17 08:56:44 -0700341 const string &security) {
Thieu Lead1ec2c2012-01-05 23:39:48 +0000342 if (security == flimflam::kSecurityNone) {
343 return kWiFiSecurityNone;
344 } else if (security == flimflam::kSecurityWep) {
345 return kWiFiSecurityWep;
346 } else if (security == flimflam::kSecurityWpa) {
347 return kWiFiSecurityWpa;
348 } else if (security == flimflam::kSecurityRsn) {
349 return kWiFiSecurityRsn;
350 } else if (security == flimflam::kSecurity8021x) {
351 return kWiFiSecurity8021x;
352 } else if (security == flimflam::kSecurityPsk) {
353 return kWiFiSecurityPsk;
354 } else {
355 return kWiFiSecurityUnknown;
356 }
357}
358
Thieu Le85e050b2012-03-13 15:04:38 -0700359// static
Paul Stewarte4cedde2013-07-17 08:56:44 -0700360Metrics::WiFiApMode Metrics::WiFiApModeStringToEnum(const string &ap_mode) {
361 if (ap_mode == flimflam::kModeManaged) {
362 return kWiFiApModeManaged;
363 } else if (ap_mode == flimflam::kModeAdhoc) {
364 return kWiFiApModeAdHoc;
365 } else {
366 return kWiFiApModeUnknown;
367 }
368}
369
370// static
Paul Stewart21f40962013-03-01 14:27:28 -0800371Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
Paul Stewarte4cedde2013-07-17 08:56:44 -0700372 const string &outer) {
Paul Stewart21f40962013-03-01 14:27:28 -0800373 if (outer == flimflam::kEapMethodPEAP) {
374 return kEapOuterProtocolPeap;
375 } else if (outer == flimflam::kEapMethodTLS) {
376 return kEapOuterProtocolTls;
377 } else if (outer == flimflam::kEapMethodTTLS) {
378 return kEapOuterProtocolTtls;
379 } else if (outer == flimflam::kEapMethodLEAP) {
380 return kEapOuterProtocolLeap;
381 } else {
382 return kEapOuterProtocolUnknown;
383 }
384}
385
386// static
387Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
Paul Stewarte4cedde2013-07-17 08:56:44 -0700388 const string &inner) {
Paul Stewart21f40962013-03-01 14:27:28 -0800389 if (inner.empty()) {
390 return kEapInnerProtocolNone;
391 } else if (inner == flimflam::kEapPhase2AuthPEAPMD5) {
392 return kEapInnerProtocolPeapMd5;
393 } else if (inner == flimflam::kEapPhase2AuthPEAPMSCHAPV2) {
394 return kEapInnerProtocolPeapMschapv2;
395 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMD5) {
396 return kEapInnerProtocolTtlsEapMd5;
397 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMSCHAPV2) {
398 return kEapInnerProtocolTtlsEapMschapv2;
399 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAPV2) {
400 return kEapInnerProtocolTtlsMschapv2;
401 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAP) {
402 return kEapInnerProtocolTtlsMschap;
403 } else if (inner == flimflam::kEapPhase2AuthTTLSPAP) {
404 return kEapInnerProtocolTtlsPap;
405 } else if (inner == flimflam::kEapPhase2AuthTTLSCHAP) {
406 return kEapInnerProtocolTtlsChap;
407 } else {
408 return kEapInnerProtocolUnknown;
409 }
410}
411
412// static
Thieu Le85e050b2012-03-13 15:04:38 -0700413Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
414 const PortalDetector::Result &result) {
415 DCHECK(result.final);
416 PortalResult retval = kPortalResultUnknown;
417 // The only time we should end a successful portal detection is when we're
418 // in the Content phase. If we end with kStatusSuccess in any other phase,
419 // then this indicates that something bad has happened.
420 switch (result.phase) {
421 case PortalDetector::kPhaseDNS:
422 if (result.status == PortalDetector::kStatusFailure)
423 retval = kPortalResultDNSFailure;
424 else if (result.status == PortalDetector::kStatusTimeout)
425 retval = kPortalResultDNSTimeout;
426 else
427 LOG(DFATAL) << __func__ << ": Final result status " << result.status
428 << " is not allowed in the DNS phase";
429 break;
430
431 case PortalDetector::kPhaseConnection:
432 if (result.status == PortalDetector::kStatusFailure)
433 retval = kPortalResultConnectionFailure;
434 else if (result.status == PortalDetector::kStatusTimeout)
435 retval = kPortalResultConnectionTimeout;
436 else
437 LOG(DFATAL) << __func__ << ": Final result status " << result.status
438 << " is not allowed in the Connection phase";
439 break;
440
441 case PortalDetector::kPhaseHTTP:
442 if (result.status == PortalDetector::kStatusFailure)
443 retval = kPortalResultHTTPFailure;
444 else if (result.status == PortalDetector::kStatusTimeout)
445 retval = kPortalResultHTTPTimeout;
446 else
447 LOG(DFATAL) << __func__ << ": Final result status " << result.status
448 << " is not allowed in the HTTP phase";
449 break;
450
451 case PortalDetector::kPhaseContent:
452 if (result.status == PortalDetector::kStatusSuccess)
453 retval = kPortalResultSuccess;
454 else if (result.status == PortalDetector::kStatusFailure)
455 retval = kPortalResultContentFailure;
456 else if (result.status == PortalDetector::kStatusTimeout)
457 retval = kPortalResultContentTimeout;
458 else
459 LOG(DFATAL) << __func__ << ": Final result status " << result.status
460 << " is not allowed in the Content phase";
461 break;
462
463 case PortalDetector::kPhaseUnknown:
464 retval = kPortalResultUnknown;
465 break;
466
467 default:
468 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
469 break;
470 }
471
472 return retval;
473}
474
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800475void Metrics::Start() {
476 SLOG(Metrics, 2) << __func__;
477 hourly_timeout_handler_.Reset(
478 Bind(&Metrics::HourlyTimeoutHandler, Unretained(this)));
479 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
480 kHourlyTimeoutMilliseconds);
481}
482
483void Metrics::Stop() {
484 SLOG(Metrics, 2) << __func__;
485 hourly_timeout_handler_.Cancel();
486}
487
Thieu Le48e6d6d2011-12-06 00:40:27 +0000488void Metrics::RegisterService(const Service *service) {
489 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
490 services_metrics_[service] = service_metrics;
491 service_metrics->service = service;
492 InitializeCommonServiceMetrics(service);
493 service->InitializeCustomMetrics();
494}
495
496void Metrics::DeregisterService(const Service *service) {
497 services_metrics_.erase(service);
498}
499
500void Metrics::AddServiceStateTransitionTimer(
501 const Service *service,
502 const string &histogram_name,
503 Service::ConnectState start_state,
504 Service::ConnectState stop_state) {
505 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
506 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700507 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000508 DCHECK(false);
509 return;
510 }
511 ServiceMetrics *service_metrics = it->second.get();
512 CHECK(start_state < stop_state);
513 chromeos_metrics::TimerReporter *timer =
514 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000515 kTimerHistogramMillisecondsMin,
516 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000517 kTimerHistogramNumBuckets);
518 service_metrics->timers.push_back(timer); // passes ownership.
519 service_metrics->start_on_state[start_state].push_back(timer);
520 service_metrics->stop_on_state[stop_state].push_back(timer);
521}
522
Thieu Lea20cbc22012-01-09 22:01:43 +0000523void Metrics::NotifyDefaultServiceChanged(const Service *service) {
524 base::TimeDelta elapsed_seconds;
525
526 Technology::Identifier technology = (service) ? service->technology() :
527 Technology::kUnknown;
528 if (technology != last_default_technology_) {
529 if (last_default_technology_ != Technology::kUnknown) {
530 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
531 last_default_technology_);
532 time_online_timer_->GetElapsedTime(&elapsed_seconds);
533 SendToUMA(histogram,
534 elapsed_seconds.InSeconds(),
535 kMetricTimeOnlineSecondsMin,
536 kMetricTimeOnlineSecondsMax,
537 kTimerHistogramNumBuckets);
538 }
539 last_default_technology_ = technology;
540 time_online_timer_->Start();
541 }
542
Thieu Lea20cbc22012-01-09 22:01:43 +0000543 // Ignore changes that are not online/offline transitions; e.g.
544 // switching between wired and wireless. TimeToDrop measures
545 // time online regardless of how we are connected.
546 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
547 return;
548
549 if (service == NULL) {
550 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
551 SendToUMA(kMetricTimeToDropSeconds,
552 elapsed_seconds.InSeconds(),
553 kMetricTimeToDropSecondsMin,
554 kMetricTimeToDropSecondsMax,
555 kTimerHistogramNumBuckets);
556 } else {
557 time_to_drop_timer_->Start();
558 }
559
560 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000561}
562
563void Metrics::NotifyServiceStateChanged(const Service *service,
564 Service::ConnectState new_state) {
565 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
566 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700567 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000568 DCHECK(false);
569 return;
570 }
571 ServiceMetrics *service_metrics = it->second.get();
572 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
573
574 if (new_state == Service::kStateFailure)
575 SendServiceFailure(service);
576
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200577 if (collect_bootstats_) {
578 bootstat_log(
579 StringPrintf("network-%s-%s",
580 Technology::NameFromIdentifier(
581 service->technology()).c_str(),
582 service->GetStateString().c_str()).c_str());
583 }
584
Paul Stewart20088d82012-02-16 06:58:55 -0800585 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000586 return;
587
Thieu Leb84ba342012-03-02 15:15:19 -0800588 base::TimeDelta time_resume_to_ready;
589 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
590 time_resume_to_ready_timer_->Reset();
591 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000592}
593
594string Metrics::GetFullMetricName(const char *metric_name,
595 Technology::Identifier technology_id) {
596 string technology = Technology::NameFromIdentifier(technology_id);
597 technology[0] = base::ToUpperASCII(technology[0]);
598 return base::StringPrintf(metric_name, technology.c_str());
599}
600
Thieu Le67370f62012-02-14 23:01:42 +0000601void Metrics::NotifyServiceDisconnect(const Service *service) {
602 Technology::Identifier technology = service->technology();
603 string histogram = GetFullMetricName(kMetricDisconnect, technology);
604 SendToUMA(histogram,
605 service->explicitly_disconnected(),
606 kMetricDisconnectMin,
607 kMetricDisconnectMax,
608 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000609}
610
Thieu Leb84ba342012-03-02 15:15:19 -0800611void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
612 if (new_state == PowerManagerProxyDelegate::kOn) {
613 time_resume_to_ready_timer_->Start();
614 } else {
615 time_resume_to_ready_timer_->Reset();
616 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000617}
618
Arman Ugurayab22c162012-10-08 19:08:38 -0700619void Metrics::NotifyTerminationActionsStarted(
620 TerminationActionReason /*reason*/) {
621 if (time_termination_actions_timer->HasStarted())
622 return;
623 time_termination_actions_timer->Start();
624}
625
626void Metrics::NotifyTerminationActionsCompleted(
627 TerminationActionReason reason, bool success) {
628 if (!time_termination_actions_timer->HasStarted())
629 return;
630
631 int result = success ? kTerminationActionResultSuccess :
632 kTerminationActionResultFailure;
633
634 base::TimeDelta elapsed_time;
635 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
636 time_termination_actions_timer->Reset();
637 string time_metric, result_metric;
638 switch (reason) {
639 case kTerminationActionReasonSuspend:
640 time_metric = kMetricTerminationActionTimeOnSuspend;
641 result_metric = kMetricTerminationActionResultOnSuspend;
642 break;
643 case kTerminationActionReasonTerminate:
644 time_metric = kMetricTerminationActionTimeOnTerminate;
645 result_metric = kMetricTerminationActionResultOnTerminate;
646 break;
647 }
648
649 SendToUMA(time_metric,
650 elapsed_time.InMilliseconds(),
651 kMetricTerminationActionTimeMillisecondsMin,
652 kMetricTerminationActionTimeMillisecondsMax,
653 kTimerHistogramNumBuckets);
654
655 SendEnumToUMA(result_metric,
656 result,
657 kTerminationActionResultMax);
658}
659
Paul Stewartff845fc2012-08-07 07:28:44 -0700660void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700661 Technology::Identifier technology,
662 LinkMonitorFailure failure,
Paul Stewartf1961f82012-09-11 20:45:39 -0700663 int seconds_to_failure,
664 int broadcast_error_count,
665 int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700666 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
667 technology);
668 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700669
670 if (failure == kLinkMonitorFailureThresholdReached) {
671 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
672 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
673 }
674 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
675 technology);
676 SendToUMA(histogram,
677 seconds_to_failure,
678 kMetricLinkMonitorSecondsToFailureMin,
679 kMetricLinkMonitorSecondsToFailureMax,
680 kMetricLinkMonitorSecondsToFailureNumBuckets);
681 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
682 technology);
683 SendToUMA(histogram,
684 broadcast_error_count,
685 kMetricLinkMonitorErrorCountMin,
686 kMetricLinkMonitorErrorCountMax,
687 kMetricLinkMonitorErrorCountNumBuckets);
688 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
689 technology);
690 SendToUMA(histogram,
691 unicast_error_count,
692 kMetricLinkMonitorErrorCountMin,
693 kMetricLinkMonitorErrorCountMax,
694 kMetricLinkMonitorErrorCountNumBuckets);
695 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700696}
697
698void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
699 Technology::Identifier technology,
Paul Stewartf1961f82012-09-11 20:45:39 -0700700 int response_time_milliseconds) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700701 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
702 technology);
703 SendToUMA(histogram,
704 response_time_milliseconds,
705 kMetricLinkMonitorResponseTimeSampleMin,
706 kMetricLinkMonitorResponseTimeSampleMax,
707 kMetricLinkMonitorResponseTimeSampleNumBuckets);
708}
709
Wade Guthried4977f22012-08-22 12:37:54 -0700710void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
711 IEEE_80211::WiFiReasonCode reason) {
712 string metric_disconnect_reason;
713 string metric_disconnect_type;
714 WiFiStatusType type;
715
716 if (by_whom == kDisconnectedByAp) {
717 metric_disconnect_reason = kMetricLinkApDisconnectReason;
718 metric_disconnect_type = kMetricLinkApDisconnectType;
719 type = kStatusCodeTypeByAp;
720 } else {
721 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
722 metric_disconnect_type = kMetricLinkClientDisconnectType;
Wade Guthrie60a37062013-04-02 11:39:09 -0700723 switch (reason) {
Wade Guthried4977f22012-08-22 12:37:54 -0700724 case IEEE_80211::kReasonCodeSenderHasLeft:
725 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
726 type = kStatusCodeTypeByUser;
727 break;
728
729 case IEEE_80211::kReasonCodeInactivity:
730 type = kStatusCodeTypeConsideredDead;
731 break;
732
733 default:
734 type = kStatusCodeTypeByClient;
735 break;
736 }
737 }
738 SendEnumToUMA(metric_disconnect_reason, reason,
739 IEEE_80211::kStatusCodeMax);
740 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
741}
742
Thieu Lec8078a62013-01-22 18:01:12 -0800743void Metrics::RegisterDevice(int interface_index,
744 Technology::Identifier technology) {
Thieu Le9abd6742013-01-23 23:35:37 -0800745 SLOG(Metrics, 2) << __func__ << ": " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800746 shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
747 devices_metrics_[interface_index] = device_metrics;
Thieu Le9abd6742013-01-23 23:35:37 -0800748 device_metrics->technology = technology;
Thieu Lec8078a62013-01-22 18:01:12 -0800749 string histogram = GetFullMetricName(kMetricTimeToInitializeMilliseconds,
750 technology);
751 device_metrics->initialization_timer.reset(
752 new chromeos_metrics::TimerReporter(
753 histogram,
754 kMetricTimeToInitializeMillisecondsMin,
755 kMetricTimeToInitializeMillisecondsMax,
756 kMetricTimeToInitializeMillisecondsNumBuckets));
757 device_metrics->initialization_timer->Start();
Thieu Lece4483e2013-01-23 15:12:03 -0800758 histogram = GetFullMetricName(kMetricTimeToEnableMilliseconds,
759 technology);
760 device_metrics->enable_timer.reset(
761 new chromeos_metrics::TimerReporter(
762 histogram,
763 kMetricTimeToEnableMillisecondsMin,
764 kMetricTimeToEnableMillisecondsMax,
765 kMetricTimeToEnableMillisecondsNumBuckets));
Thieu Lea2519bf2013-01-23 16:51:54 -0800766 histogram = GetFullMetricName(kMetricTimeToDisableMilliseconds,
767 technology);
768 device_metrics->disable_timer.reset(
769 new chromeos_metrics::TimerReporter(
770 histogram,
771 kMetricTimeToDisableMillisecondsMin,
772 kMetricTimeToDisableMillisecondsMax,
773 kMetricTimeToDisableMillisecondsNumBuckets));
Thieu Le18c11072013-01-28 17:21:37 -0800774 histogram = GetFullMetricName(kMetricTimeToScanMilliseconds,
775 technology);
776 device_metrics->scan_timer.reset(
777 new chromeos_metrics::TimerReporter(
778 histogram,
779 kMetricTimeToScanMillisecondsMin,
780 kMetricTimeToScanMillisecondsMax,
781 kMetricTimeToScanMillisecondsNumBuckets));
Thieu Lecdb5a212013-01-25 11:17:18 -0800782 histogram = GetFullMetricName(kMetricTimeToConnectMilliseconds,
783 technology);
784 device_metrics->connect_timer.reset(
785 new chromeos_metrics::TimerReporter(
786 histogram,
787 kMetricTimeToConnectMillisecondsMin,
788 kMetricTimeToConnectMillisecondsMax,
789 kMetricTimeToConnectMillisecondsNumBuckets));
Wade Guthrie44f290d2013-05-28 10:16:25 -0700790 histogram = GetFullMetricName(kMetricTimeToScanAndConnectMilliseconds,
791 technology);
792 device_metrics->scan_connect_timer.reset(
793 new chromeos_metrics::TimerReporter(
794 histogram,
795 kMetricTimeToScanMillisecondsMin,
796 kMetricTimeToScanMillisecondsMax +
797 kMetricTimeToConnectMillisecondsMax,
798 kMetricTimeToScanMillisecondsNumBuckets +
799 kMetricTimeToConnectMillisecondsNumBuckets));
Thieu Le7cf36b02013-01-30 17:15:56 -0800800 device_metrics->auto_connect_timer.reset(
801 new chromeos_metrics::TimerReporter(
802 kMetricCellularAutoConnectTotalTime,
803 kMetricCellularAutoConnectTotalTimeMin,
804 kMetricCellularAutoConnectTotalTimeMax,
805 kMetricCellularAutoConnectTotalTimeNumBuckets));
Thieu Lec8078a62013-01-22 18:01:12 -0800806}
807
Thieu Le9abd6742013-01-23 23:35:37 -0800808bool Metrics::IsDeviceRegistered(int interface_index,
809 Technology::Identifier technology) {
810 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index
811 << ", technology: " << technology;
812 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
813 if (device_metrics == NULL)
814 return false;
815 // Make sure the device technologies match.
816 return (technology == device_metrics->technology);
817}
818
Thieu Lec8078a62013-01-22 18:01:12 -0800819void Metrics::DeregisterDevice(int interface_index) {
Thieu Le9abd6742013-01-23 23:35:37 -0800820 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800821 devices_metrics_.erase(interface_index);
822}
823
824void Metrics::NotifyDeviceInitialized(int interface_index) {
Thieu Lece4483e2013-01-23 15:12:03 -0800825 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
826 if (device_metrics == NULL)
Thieu Lec8078a62013-01-22 18:01:12 -0800827 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700828 if (!device_metrics->initialization_timer->Stop())
829 return;
Thieu Lec8078a62013-01-22 18:01:12 -0800830 device_metrics->initialization_timer->ReportMilliseconds();
831}
832
Thieu Lece4483e2013-01-23 15:12:03 -0800833void Metrics::NotifyDeviceEnableStarted(int interface_index) {
834 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
835 if (device_metrics == NULL)
836 return;
837 device_metrics->enable_timer->Start();
838}
839
840void Metrics::NotifyDeviceEnableFinished(int interface_index) {
841 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
842 if (device_metrics == NULL)
843 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700844 if (!device_metrics->enable_timer->Stop())
845 return;
Thieu Lece4483e2013-01-23 15:12:03 -0800846 device_metrics->enable_timer->ReportMilliseconds();
847}
848
Thieu Lea2519bf2013-01-23 16:51:54 -0800849void Metrics::NotifyDeviceDisableStarted(int interface_index) {
850 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
851 if (device_metrics == NULL)
852 return;
853 device_metrics->disable_timer->Start();
854}
855
856void Metrics::NotifyDeviceDisableFinished(int interface_index) {
857 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
858 if (device_metrics == NULL)
859 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700860 if (!device_metrics->disable_timer->Stop())
861 return;
Thieu Lea2519bf2013-01-23 16:51:54 -0800862 device_metrics->disable_timer->ReportMilliseconds();
863}
864
Thieu Le18c11072013-01-28 17:21:37 -0800865void Metrics::NotifyDeviceScanStarted(int interface_index) {
866 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
867 if (device_metrics == NULL)
868 return;
Thieu Le18c11072013-01-28 17:21:37 -0800869 device_metrics->scan_timer->Start();
Wade Guthrie44f290d2013-05-28 10:16:25 -0700870 device_metrics->scan_connect_timer->Start();
Thieu Le18c11072013-01-28 17:21:37 -0800871}
872
873void Metrics::NotifyDeviceScanFinished(int interface_index) {
874 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
875 if (device_metrics == NULL)
876 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700877 if (!device_metrics->scan_timer->Stop())
878 return;
Wade Guthrie68d41092013-04-02 12:56:02 -0700879 // Don't send TimeToScan metrics if the elapsed time exceeds the max metrics
880 // value. Huge scan times usually mean something's gone awry; for cellular,
881 // for instance, this usually means that the modem is in an area without
882 // service and we're not interested in this scenario.
Thieu Le18c11072013-01-28 17:21:37 -0800883 base::TimeDelta elapsed_time;
884 device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
885 if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
886 device_metrics->scan_timer->ReportMilliseconds();
887}
888
Wade Guthrie44f290d2013-05-28 10:16:25 -0700889void Metrics::ResetScanTimer(int interface_index) {
890 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
891 if (device_metrics == NULL)
892 return;
893 device_metrics->scan_timer->Reset();
894}
895
Thieu Le7cf36b02013-01-30 17:15:56 -0800896void Metrics::NotifyDeviceConnectStarted(int interface_index,
897 bool is_auto_connecting) {
Thieu Lecdb5a212013-01-25 11:17:18 -0800898 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
899 if (device_metrics == NULL)
900 return;
901 device_metrics->connect_timer->Start();
Thieu Le7cf36b02013-01-30 17:15:56 -0800902
903 if (is_auto_connecting) {
904 device_metrics->auto_connect_tries++;
905 if (device_metrics->auto_connect_tries == 1)
906 device_metrics->auto_connect_timer->Start();
907 } else {
908 AutoConnectMetricsReset(device_metrics);
909 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800910}
911
912void Metrics::NotifyDeviceConnectFinished(int interface_index) {
913 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
914 if (device_metrics == NULL)
915 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700916 if (!device_metrics->connect_timer->Stop())
917 return;
Thieu Lecdb5a212013-01-25 11:17:18 -0800918 device_metrics->connect_timer->ReportMilliseconds();
Thieu Le7cf36b02013-01-30 17:15:56 -0800919
920 if (device_metrics->auto_connect_tries > 0) {
Wade Guthrie091c41c2013-03-22 15:48:53 -0700921 if (!device_metrics->auto_connect_timer->Stop())
922 return;
Thieu Le7cf36b02013-01-30 17:15:56 -0800923 base::TimeDelta elapsed_time;
924 device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
925 if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
926 return;
927 device_metrics->auto_connect_timer->ReportMilliseconds();
928 SendToUMA(kMetricCellularAutoConnectTries,
929 device_metrics->auto_connect_tries,
930 kMetricCellularAutoConnectTriesMin,
931 kMetricCellularAutoConnectTriesMax,
932 kMetricCellularAutoConnectTriesNumBuckets);
933 AutoConnectMetricsReset(device_metrics);
934 }
Wade Guthrie44f290d2013-05-28 10:16:25 -0700935
936 if (!device_metrics->scan_connect_timer->Stop())
937 return;
938 base::TimeDelta elapsed_time;
939 device_metrics->scan_connect_timer->GetElapsedTime(&elapsed_time);
940 device_metrics->scan_connect_timer->ReportMilliseconds();
941}
942
943void Metrics::ResetConnectTimer(int interface_index) {
944 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
945 if (device_metrics == NULL)
946 return;
947 device_metrics->connect_timer->Reset();
948 device_metrics->scan_connect_timer->Reset();
Thieu Lecdb5a212013-01-25 11:17:18 -0800949}
950
Prathmesh Prabhu08757aa2013-05-15 17:17:33 -0700951void Metrics::Notify3GPPRegistrationDelayedDropPosted() {
952 SendEnumToUMA(kMetricCellular3GPPRegistrationDelayedDrop,
953 kCellular3GPPRegistrationDelayedDropPosted,
954 kCellular3GPPRegistrationDelayedDropMax);
955}
956
957void Metrics::Notify3GPPRegistrationDelayedDropCanceled() {
958 SendEnumToUMA(kMetricCellular3GPPRegistrationDelayedDrop,
959 kCellular3GPPRegistrationDelayedDropCanceled,
960 kCellular3GPPRegistrationDelayedDropMax);
961}
962
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800963void Metrics::NotifyCellularDeviceDrop(int interface_index,
964 const string &network_technology,
Thieu Le26fc01b2013-01-28 12:08:48 -0800965 uint16 signal_strength) {
966 SLOG(Metrics, 2) << __func__ << ": " << network_technology
967 << ", " << signal_strength;
968 CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
969 if (network_technology == flimflam::kNetworkTechnology1Xrtt) {
970 drop_technology = kCellularDropTechnology1Xrtt;
971 } else if (network_technology == flimflam::kNetworkTechnologyEdge) {
972 drop_technology = kCellularDropTechnologyEdge;
973 } else if (network_technology == flimflam::kNetworkTechnologyEvdo) {
974 drop_technology = kCellularDropTechnologyEvdo;
975 } else if (network_technology == flimflam::kNetworkTechnologyGprs) {
976 drop_technology = kCellularDropTechnologyGprs;
977 } else if (network_technology == flimflam::kNetworkTechnologyGsm) {
978 drop_technology = kCellularDropTechnologyGsm;
979 } else if (network_technology == flimflam::kNetworkTechnologyHspa) {
980 drop_technology = kCellularDropTechnologyHspa;
981 } else if (network_technology == flimflam::kNetworkTechnologyHspaPlus) {
982 drop_technology = kCellularDropTechnologyHspaPlus;
983 } else if (network_technology == flimflam::kNetworkTechnologyLte) {
984 drop_technology = kCellularDropTechnologyLte;
985 } else if (network_technology == flimflam::kNetworkTechnologyUmts) {
986 drop_technology = kCellularDropTechnologyUmts;
987 }
988 SendEnumToUMA(kMetricCellularDrop,
989 drop_technology,
990 kCellularDropTechnologyMax);
991 SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
992 signal_strength,
993 kMetricCellularSignalStrengthBeforeDropMin,
994 kMetricCellularSignalStrengthBeforeDropMax,
995 kMetricCellularSignalStrengthBeforeDropNumBuckets);
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800996
997 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
998 if (device_metrics == NULL)
999 return;
1000 device_metrics->num_drops++;
Thieu Le26fc01b2013-01-28 12:08:48 -08001001}
1002
Thieu Leb7aa5f72013-01-31 15:57:48 -08001003void Metrics::NotifyCellularDeviceFailure(const Error &error) {
1004 library_->SendUserActionToUMA(
1005 kMetricCellularFailureReason + error.message());
1006}
1007
Thieu Le91fccf62013-04-22 15:23:16 -07001008void Metrics::NotifyCellularOutOfCredits(
1009 Metrics::CellularOutOfCreditsReason reason) {
1010 SendEnumToUMA(kMetricCellularOutOfCreditsReason,
1011 reason,
1012 kCellularOutOfCreditsReasonMax);
1013}
1014
Thieu Le5133b712013-02-19 14:47:21 -08001015void Metrics::NotifyCorruptedProfile() {
1016 SendEnumToUMA(kMetricCorruptedProfile,
1017 kCorruptedProfile,
1018 kCorruptedProfileMax);
1019}
1020
Thieu Le48e6d6d2011-12-06 00:40:27 +00001021bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
1022 return library_->SendEnumToUMA(name, sample, max);
1023}
1024
Thieu Lea20cbc22012-01-09 22:01:43 +00001025bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
1026 int num_buckets) {
1027 return library_->SendToUMA(name, sample, min, max, num_buckets);
1028}
1029
Thieu Le48e6d6d2011-12-06 00:40:27 +00001030void Metrics::InitializeCommonServiceMetrics(const Service *service) {
1031 Technology::Identifier technology = service->technology();
1032 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
1033 technology);
1034 AddServiceStateTransitionTimer(
1035 service,
1036 histogram,
1037 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -08001038 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +00001039 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
1040 AddServiceStateTransitionTimer(
1041 service,
1042 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -08001043 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +00001044 Service::kStatePortal);
1045 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
1046 AddServiceStateTransitionTimer(
1047 service,
1048 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -08001049 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +00001050 Service::kStateOnline);
1051}
1052
1053void Metrics::UpdateServiceStateTransitionMetrics(
1054 ServiceMetrics *service_metrics,
1055 Service::ConnectState new_state) {
1056 TimerReportersList::iterator it;
1057 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
1058 for (it = start_timers.begin(); it != start_timers.end(); ++it)
1059 (*it)->Start();
1060
1061 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
1062 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
Wade Guthrie091c41c2013-03-22 15:48:53 -07001063 if ((*it)->Stop())
1064 (*it)->ReportMilliseconds();
Thieu Le48e6d6d2011-12-06 00:40:27 +00001065 }
1066}
1067
1068void Metrics::SendServiceFailure(const Service *service) {
1069 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
1070 service->failure(),
1071 kMetricNetworkServiceErrorsMax);
1072}
1073
Thieu Le9abd6742013-01-23 23:35:37 -08001074Metrics::DeviceMetrics *Metrics::GetDeviceMetrics(int interface_index) const {
1075 DeviceMetricsLookupMap::const_iterator it =
1076 devices_metrics_.find(interface_index);
Thieu Lece4483e2013-01-23 15:12:03 -08001077 if (it == devices_metrics_.end()) {
Thieu Le9abd6742013-01-23 23:35:37 -08001078 SLOG(Metrics, 2) << __func__ << ": device " << interface_index
1079 << " not found";
Thieu Lece4483e2013-01-23 15:12:03 -08001080 return NULL;
1081 }
1082 return it->second.get();
1083}
1084
Thieu Le7cf36b02013-01-30 17:15:56 -08001085void Metrics::AutoConnectMetricsReset(DeviceMetrics *device_metrics) {
1086 device_metrics->auto_connect_tries = 0;
1087 device_metrics->auto_connect_timer->Reset();
1088}
1089
Thieu Le6c1e3bb2013-02-06 15:20:35 -08001090void Metrics::HourlyTimeoutHandler() {
1091 SLOG(Metrics, 2) << __func__;
1092 DeviceMetricsLookupMap::iterator it;
1093 for (it = devices_metrics_.begin(); it != devices_metrics_.end(); ++it) {
1094 if (it->second->technology != Technology::kCellular ||
1095 it->second->num_drops == 0)
1096 continue;
1097 SendToUMA(kMetricCellularDropsPerHour,
1098 it->second->num_drops,
1099 kMetricCellularDropsPerHourMin,
1100 kMetricCellularDropsPerHourMax,
1101 kMetricCellularDropsPerHourNumBuckets);
1102 it->second->num_drops = 0;
1103 }
1104 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
1105 kHourlyTimeoutMilliseconds);
1106}
1107
Thieu Le48e6d6d2011-12-06 00:40:27 +00001108void Metrics::set_library(MetricsLibraryInterface *library) {
1109 chromeos_metrics::TimerReporter::set_metrics_lib(library);
1110 library_ = library;
1111}
1112
1113} // namespace shill