blob: f0ffd1d363431de067b94021ef4fa3d602401d65 [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
Thieu Le48e6d6d2011-12-06 00:40:27 +000040const char Metrics::kMetricNetworkChannel[] = "Network.Shill.%s.Channel";
41const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
Paul Stewart21f40962013-03-01 14:27:28 -080042const char Metrics::kMetricNetworkEapInnerProtocol[] =
43 "Network.Shill.%s.EapInnerProtocol";
44const int Metrics::kMetricNetworkEapInnerProtocolMax =
45 Metrics::kEapInnerProtocolMax;
46const char Metrics::kMetricNetworkEapOuterProtocol[] =
47 "Network.Shill.%s.EapOuterProtocol";
48const int Metrics::kMetricNetworkEapOuterProtocolMax =
49 Metrics::kEapOuterProtocolMax;
Thieu Lead1ec2c2012-01-05 23:39:48 +000050const char Metrics::kMetricNetworkPhyMode[] = "Network.Shill.%s.PhyMode";
51const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
52const char Metrics::kMetricNetworkSecurity[] = "Network.Shill.%s.Security";
53const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
Thieu Le48e6d6d2011-12-06 00:40:27 +000054const char Metrics::kMetricNetworkServiceErrors[] =
55 "Network.Shill.ServiceErrors";
56const int Metrics::kMetricNetworkServiceErrorsMax = Service::kFailureMax;
Paul Stewart23b393a2012-09-25 21:21:06 -070057const char Metrics::kMetricNetworkSignalStrength[] =
58 "Network.Shill.%s.SignalStrength";
59const int Metrics::kMetricNetworkSignalStrengthMax = 200;
60const int Metrics::kMetricNetworkSignalStrengthMin = 0;
61const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
Thieu Lea20cbc22012-01-09 22:01:43 +000062
63const char Metrics::kMetricTimeOnlineSeconds[] = "Network.Shill.%s.TimeOnline";
64const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
65const int Metrics::kMetricTimeOnlineSecondsMin = 1;
66
Thieu Lecdb5a212013-01-25 11:17:18 -080067const char Metrics::kMetricTimeToConnectMilliseconds[] =
68 "Network.Shill.%s.TimeToConnect";
69const int Metrics::kMetricTimeToConnectMillisecondsMax =
70 60 * 1000; // 60 seconds
71const int Metrics::kMetricTimeToConnectMillisecondsMin = 1;
72const int Metrics::kMetricTimeToConnectMillisecondsNumBuckets = 60;
73
Thieu Lea20cbc22012-01-09 22:01:43 +000074const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
75const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
76const int Metrics::kMetricTimeToDropSecondsMin = 1;
77
Thieu Lea2519bf2013-01-23 16:51:54 -080078const char Metrics::kMetricTimeToDisableMilliseconds[] =
79 "Network.Shill.%s.TimeToDisable";
80const int Metrics::kMetricTimeToDisableMillisecondsMax =
81 60 * 1000; // 60 seconds
82const int Metrics::kMetricTimeToDisableMillisecondsMin = 1;
83const int Metrics::kMetricTimeToDisableMillisecondsNumBuckets = 60;
84
Thieu Lece4483e2013-01-23 15:12:03 -080085const char Metrics::kMetricTimeToEnableMilliseconds[] =
86 "Network.Shill.%s.TimeToEnable";
87const int Metrics::kMetricTimeToEnableMillisecondsMax =
88 60 * 1000; // 60 seconds
89const int Metrics::kMetricTimeToEnableMillisecondsMin = 1;
90const int Metrics::kMetricTimeToEnableMillisecondsNumBuckets = 60;
91
Thieu Lec8078a62013-01-22 18:01:12 -080092const char Metrics::kMetricTimeToInitializeMilliseconds[] =
93 "Network.Shill.%s.TimeToInitialize";
Thieu Le769d50d2013-01-23 17:11:59 -080094const int Metrics::kMetricTimeToInitializeMillisecondsMax =
95 30 * 1000; // 30 seconds
Thieu Lece4483e2013-01-23 15:12:03 -080096const int Metrics::kMetricTimeToInitializeMillisecondsMin = 1;
Thieu Le769d50d2013-01-23 17:11:59 -080097const int Metrics::kMetricTimeToInitializeMillisecondsNumBuckets = 30;
Thieu Lec8078a62013-01-22 18:01:12 -080098
Thieu Leb84ba342012-03-02 15:15:19 -080099const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
100 "Network.Shill.%s.TimeResumeToReady";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000101const char Metrics::kMetricTimeToConfigMilliseconds[] =
102 "Network.Shill.%s.TimeToConfig";
103const char Metrics::kMetricTimeToJoinMilliseconds[] =
104 "Network.Shill.%s.TimeToJoin";
105const char Metrics::kMetricTimeToOnlineMilliseconds[] =
106 "Network.Shill.%s.TimeToOnline";
107const char Metrics::kMetricTimeToPortalMilliseconds[] =
108 "Network.Shill.%s.TimeToPortal";
Thieu Le18c11072013-01-28 17:21:37 -0800109
110const char Metrics::kMetricTimeToScanMilliseconds[] =
111 "Network.Shill.%s.TimeToScan";
112const int Metrics::kMetricTimeToScanMillisecondsMax = 180 * 1000; // 3 minutes
113const int Metrics::kMetricTimeToScanMillisecondsMin = 1;
114const int Metrics::kMetricTimeToScanMillisecondsNumBuckets = 90;
115
Thieu Lea20cbc22012-01-09 22:01:43 +0000116const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
117const int Metrics::kTimerHistogramMillisecondsMin = 1;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000118const int Metrics::kTimerHistogramNumBuckets = 50;
119
Thieu Le85e050b2012-03-13 15:04:38 -0700120const char Metrics::kMetricPortalAttempts[] =
121 "Network.Shill.%s.PortalAttempts";
122const int Metrics::kMetricPortalAttemptsMax =
123 PortalDetector::kMaxRequestAttempts;
124const int Metrics::kMetricPortalAttemptsMin = 1;
125const int Metrics::kMetricPortalAttemptsNumBuckets =
126 Metrics::kMetricPortalAttemptsMax;
127
128const char Metrics::kMetricPortalAttemptsToOnline[] =
129 "Network.Shill.%s.PortalAttemptsToOnline";
130const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
131const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
132const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
133
134const char Metrics::kMetricPortalResult[] = "Network.Shill.%s.PortalResult";
135
Wade Guthrie60a37062013-04-02 11:39:09 -0700136const char Metrics::kMetricFrequenciesConnectedEver[] =
137 "Network.Shill.WiFi.FrequenciesConnectedEver";
138const int Metrics::kMetricFrequenciesConnectedMax = 50;
139const int Metrics::kMetricFrequenciesConnectedMin = 1;
140const int Metrics::kMetricFrequenciesConnectedNumBuckets = 50;
141
Arman Ugurayab22c162012-10-08 19:08:38 -0700142const char Metrics::kMetricTerminationActionTimeOnTerminate[] =
143 "Network.Shill.TerminationActionTime.OnTerminate";
144const char Metrics::kMetricTerminationActionResultOnTerminate[] =
145 "Network.Shill.TerminationActionResult.OnTerminate";
146const char Metrics::kMetricTerminationActionTimeOnSuspend[] =
147 "Network.Shill.TerminationActionTime.OnSuspend";
148const char Metrics::kMetricTerminationActionResultOnSuspend[] =
149 "Network.Shill.TerminationActionResult.OnSuspend";
150const int Metrics::kMetricTerminationActionTimeMillisecondsMax = 10000;
151const int Metrics::kMetricTerminationActionTimeMillisecondsMin = 1;
Arman Uguray6d528f12012-09-13 13:44:55 -0700152
Thieu Le48e6d6d2011-12-06 00:40:27 +0000153// static
Paul Stewart85aea152013-01-22 09:31:56 -0800154const char Metrics::kMetricServiceFixupEntries[] =
155 "Network.Shill.%s.ServiceFixupEntries";
156
157// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000158const uint16 Metrics::kWiFiBandwidth5MHz = 5;
159const uint16 Metrics::kWiFiBandwidth20MHz = 20;
160const uint16 Metrics::kWiFiFrequency2412 = 2412;
161const uint16 Metrics::kWiFiFrequency2472 = 2472;
162const uint16 Metrics::kWiFiFrequency2484 = 2484;
163const uint16 Metrics::kWiFiFrequency5170 = 5170;
164const uint16 Metrics::kWiFiFrequency5180 = 5180;
165const uint16 Metrics::kWiFiFrequency5230 = 5230;
166const uint16 Metrics::kWiFiFrequency5240 = 5240;
167const uint16 Metrics::kWiFiFrequency5320 = 5320;
168const uint16 Metrics::kWiFiFrequency5500 = 5500;
169const uint16 Metrics::kWiFiFrequency5700 = 5700;
170const uint16 Metrics::kWiFiFrequency5745 = 5745;
171const uint16 Metrics::kWiFiFrequency5825 = 5825;
172
Thieu Leb84ba342012-03-02 15:15:19 -0800173// static
174const char Metrics::kMetricPowerManagerKey[] = "metrics";
175
Paul Stewartff845fc2012-08-07 07:28:44 -0700176// static
177const char Metrics::kMetricLinkMonitorFailure[] =
178 "Network.Shill.%s.LinkMonitorFailure";
179const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
180 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewartf1961f82012-09-11 20:45:39 -0700181const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
182const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700183 LinkMonitor::kTestPeriodMilliseconds;
184const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700185const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
186 "Network.Shill.%s.LinkMonitorSecondsToFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700187const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
188const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
Paul Stewart0443aa52012-08-09 10:43:50 -0700189const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
190const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
191 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
192const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
193 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700194const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
195const int Metrics::kMetricLinkMonitorErrorCountMax =
Paul Stewart0443aa52012-08-09 10:43:50 -0700196 LinkMonitor::kFailureThreshold;
197const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
198 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700199
Wade Guthried4977f22012-08-22 12:37:54 -0700200// static
201const char Metrics::kMetricLinkClientDisconnectReason[] =
202 "Network.Shill.WiFi.ClientDisconnectReason";
203const char Metrics::kMetricLinkApDisconnectReason[] =
204 "Network.Shill.WiFi.ApDisconnectReason";
205const char Metrics::kMetricLinkClientDisconnectType[] =
206 "Network.Shill.WiFi.ClientDisconnectType";
207const char Metrics::kMetricLinkApDisconnectType[] =
208 "Network.Shill.WiFi.ApDisconnectType";
209
Thieu Le26fc01b2013-01-28 12:08:48 -0800210// static
Thieu Le91fccf62013-04-22 15:23:16 -0700211const char Metrics::kMetricCellularAutoConnectTries[] =
212 "Network.Shill.Cellular.AutoConnectTries";
213const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
214const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
215const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
216const char Metrics::kMetricCellularAutoConnectTotalTime[] =
217 "Network.Shill.Cellular.AutoConnectTotalTime";
218const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
219 60 * 1000; // 60 seconds
220const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
221const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
Thieu Le26fc01b2013-01-28 12:08:48 -0800222const char Metrics::kMetricCellularDrop[] =
223 "Network.Shill.Cellular.Drop";
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800224const char Metrics::kMetricCellularDropsPerHour[] =
225 "Network.Shill.Cellular.DropsPerHour";
226const int Metrics::kMetricCellularDropsPerHourMax = 60;
227const int Metrics::kMetricCellularDropsPerHourMin = 1;
228const int Metrics::kMetricCellularDropsPerHourNumBuckets = 10;
Thieu Leb7aa5f72013-01-31 15:57:48 -0800229// The format of FailureReason is different to other metrics because this
230// name is prepended to the error message before the entire string is sent
231// via SendUserActionToUMA.
232const char Metrics::kMetricCellularFailureReason[] =
233 "Network.Shill.Cellular.FailureReason: ";
Thieu Le91fccf62013-04-22 15:23:16 -0700234const char Metrics::kMetricCellularOutOfCreditsReason[] =
235 "Network.Shill.Cellular.OutOfCreditsReason";
Thieu Le26fc01b2013-01-28 12:08:48 -0800236const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
237 "Network.Shill.Cellular.SignalStrengthBeforeDrop";
238const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
239const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
240const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
241
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800242// static
Thieu Le5133b712013-02-19 14:47:21 -0800243const char Metrics::kMetricCorruptedProfile[] =
244 "Network.Shill.CorruptedProfile";
245
246// static
Paul Stewart91a43cb2013-03-02 21:34:15 -0800247const char Metrics::kMetricVpnDriver[] =
248 "Network.Shill.Vpn.Driver";
249const int Metrics::kMetricVpnDriverMax = Metrics::kVpnDriverMax;
250const char Metrics::kMetricVpnRemoteAuthenticationType[] =
251 "Network.Shill.Vpn.RemoteAuthenticationType";
252const int Metrics::kMetricVpnRemoteAuthenticationTypeMax =
253 Metrics::kVpnRemoteAuthenticationTypeMax;
254const char Metrics::kMetricVpnUserAuthenticationType[] =
255 "Network.Shill.Vpn.UserAuthenticationType";
256const int Metrics::kMetricVpnUserAuthenticationTypeMax =
257 Metrics::kVpnUserAuthenticationTypeMax;
258
259// static
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800260const int Metrics::kHourlyTimeoutMilliseconds = 3600 * 1000; // One hour
Wade Guthried4977f22012-08-22 12:37:54 -0700261
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800262
263Metrics::Metrics(EventDispatcher *dispatcher)
264 : dispatcher_(dispatcher),
265 library_(&metrics_library_),
Thieu Lea20cbc22012-01-09 22:01:43 +0000266 last_default_technology_(Technology::kUnknown),
267 was_online_(false),
268 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800269 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200270 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
Arman Ugurayab22c162012-10-08 19:08:38 -0700271 time_termination_actions_timer(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200272 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000273 metrics_library_.Init();
274 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
275}
276
277Metrics::~Metrics() {}
278
279// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000280Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
281 WiFiChannel channel = kWiFiChannelUndef;
282 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
283 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
284 channel = static_cast<WiFiChannel>(
285 kWiFiChannel2412 +
286 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
287 } else if (frequency == kWiFiFrequency2484) {
288 channel = kWiFiChannel2484;
289 } else if (kWiFiFrequency5170 <= frequency &&
290 frequency <= kWiFiFrequency5230) {
291 if ((frequency % kWiFiBandwidth20MHz) == 0)
292 channel = static_cast<WiFiChannel>(
293 kWiFiChannel5180 +
294 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
295 if ((frequency % kWiFiBandwidth20MHz) == 10)
296 channel = static_cast<WiFiChannel>(
297 kWiFiChannel5170 +
298 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
299 } else if (kWiFiFrequency5240 <= frequency &&
300 frequency <= kWiFiFrequency5320) {
301 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
302 channel = static_cast<WiFiChannel>(
303 kWiFiChannel5180 +
304 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
305 } else if (kWiFiFrequency5500 <= frequency &&
306 frequency <= kWiFiFrequency5700) {
307 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
308 channel = static_cast<WiFiChannel>(
309 kWiFiChannel5500 +
310 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
311 } else if (kWiFiFrequency5745 <= frequency &&
312 frequency <= kWiFiFrequency5825) {
313 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
314 channel = static_cast<WiFiChannel>(
315 kWiFiChannel5745 +
316 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
317 }
318 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
319
320 if (channel == kWiFiChannelUndef)
321 LOG(WARNING) << "no mapping for frequency " << frequency;
322 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700323 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000324
325 return channel;
326}
327
Thieu Lead1ec2c2012-01-05 23:39:48 +0000328// static
329Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
330 const std::string &security) {
331 if (security == flimflam::kSecurityNone) {
332 return kWiFiSecurityNone;
333 } else if (security == flimflam::kSecurityWep) {
334 return kWiFiSecurityWep;
335 } else if (security == flimflam::kSecurityWpa) {
336 return kWiFiSecurityWpa;
337 } else if (security == flimflam::kSecurityRsn) {
338 return kWiFiSecurityRsn;
339 } else if (security == flimflam::kSecurity8021x) {
340 return kWiFiSecurity8021x;
341 } else if (security == flimflam::kSecurityPsk) {
342 return kWiFiSecurityPsk;
343 } else {
344 return kWiFiSecurityUnknown;
345 }
346}
347
Thieu Le85e050b2012-03-13 15:04:38 -0700348// static
Paul Stewart21f40962013-03-01 14:27:28 -0800349Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
350 const std::string &outer) {
351 if (outer == flimflam::kEapMethodPEAP) {
352 return kEapOuterProtocolPeap;
353 } else if (outer == flimflam::kEapMethodTLS) {
354 return kEapOuterProtocolTls;
355 } else if (outer == flimflam::kEapMethodTTLS) {
356 return kEapOuterProtocolTtls;
357 } else if (outer == flimflam::kEapMethodLEAP) {
358 return kEapOuterProtocolLeap;
359 } else {
360 return kEapOuterProtocolUnknown;
361 }
362}
363
364// static
365Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
366 const std::string &inner) {
367 if (inner.empty()) {
368 return kEapInnerProtocolNone;
369 } else if (inner == flimflam::kEapPhase2AuthPEAPMD5) {
370 return kEapInnerProtocolPeapMd5;
371 } else if (inner == flimflam::kEapPhase2AuthPEAPMSCHAPV2) {
372 return kEapInnerProtocolPeapMschapv2;
373 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMD5) {
374 return kEapInnerProtocolTtlsEapMd5;
375 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMSCHAPV2) {
376 return kEapInnerProtocolTtlsEapMschapv2;
377 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAPV2) {
378 return kEapInnerProtocolTtlsMschapv2;
379 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAP) {
380 return kEapInnerProtocolTtlsMschap;
381 } else if (inner == flimflam::kEapPhase2AuthTTLSPAP) {
382 return kEapInnerProtocolTtlsPap;
383 } else if (inner == flimflam::kEapPhase2AuthTTLSCHAP) {
384 return kEapInnerProtocolTtlsChap;
385 } else {
386 return kEapInnerProtocolUnknown;
387 }
388}
389
390// static
Thieu Le85e050b2012-03-13 15:04:38 -0700391Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
392 const PortalDetector::Result &result) {
393 DCHECK(result.final);
394 PortalResult retval = kPortalResultUnknown;
395 // The only time we should end a successful portal detection is when we're
396 // in the Content phase. If we end with kStatusSuccess in any other phase,
397 // then this indicates that something bad has happened.
398 switch (result.phase) {
399 case PortalDetector::kPhaseDNS:
400 if (result.status == PortalDetector::kStatusFailure)
401 retval = kPortalResultDNSFailure;
402 else if (result.status == PortalDetector::kStatusTimeout)
403 retval = kPortalResultDNSTimeout;
404 else
405 LOG(DFATAL) << __func__ << ": Final result status " << result.status
406 << " is not allowed in the DNS phase";
407 break;
408
409 case PortalDetector::kPhaseConnection:
410 if (result.status == PortalDetector::kStatusFailure)
411 retval = kPortalResultConnectionFailure;
412 else if (result.status == PortalDetector::kStatusTimeout)
413 retval = kPortalResultConnectionTimeout;
414 else
415 LOG(DFATAL) << __func__ << ": Final result status " << result.status
416 << " is not allowed in the Connection phase";
417 break;
418
419 case PortalDetector::kPhaseHTTP:
420 if (result.status == PortalDetector::kStatusFailure)
421 retval = kPortalResultHTTPFailure;
422 else if (result.status == PortalDetector::kStatusTimeout)
423 retval = kPortalResultHTTPTimeout;
424 else
425 LOG(DFATAL) << __func__ << ": Final result status " << result.status
426 << " is not allowed in the HTTP phase";
427 break;
428
429 case PortalDetector::kPhaseContent:
430 if (result.status == PortalDetector::kStatusSuccess)
431 retval = kPortalResultSuccess;
432 else if (result.status == PortalDetector::kStatusFailure)
433 retval = kPortalResultContentFailure;
434 else if (result.status == PortalDetector::kStatusTimeout)
435 retval = kPortalResultContentTimeout;
436 else
437 LOG(DFATAL) << __func__ << ": Final result status " << result.status
438 << " is not allowed in the Content phase";
439 break;
440
441 case PortalDetector::kPhaseUnknown:
442 retval = kPortalResultUnknown;
443 break;
444
445 default:
446 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
447 break;
448 }
449
450 return retval;
451}
452
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800453void Metrics::Start() {
454 SLOG(Metrics, 2) << __func__;
455 hourly_timeout_handler_.Reset(
456 Bind(&Metrics::HourlyTimeoutHandler, Unretained(this)));
457 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
458 kHourlyTimeoutMilliseconds);
459}
460
461void Metrics::Stop() {
462 SLOG(Metrics, 2) << __func__;
463 hourly_timeout_handler_.Cancel();
464}
465
Thieu Le48e6d6d2011-12-06 00:40:27 +0000466void Metrics::RegisterService(const Service *service) {
467 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
468 services_metrics_[service] = service_metrics;
469 service_metrics->service = service;
470 InitializeCommonServiceMetrics(service);
471 service->InitializeCustomMetrics();
472}
473
474void Metrics::DeregisterService(const Service *service) {
475 services_metrics_.erase(service);
476}
477
478void Metrics::AddServiceStateTransitionTimer(
479 const Service *service,
480 const string &histogram_name,
481 Service::ConnectState start_state,
482 Service::ConnectState stop_state) {
483 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
484 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700485 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000486 DCHECK(false);
487 return;
488 }
489 ServiceMetrics *service_metrics = it->second.get();
490 CHECK(start_state < stop_state);
491 chromeos_metrics::TimerReporter *timer =
492 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000493 kTimerHistogramMillisecondsMin,
494 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000495 kTimerHistogramNumBuckets);
496 service_metrics->timers.push_back(timer); // passes ownership.
497 service_metrics->start_on_state[start_state].push_back(timer);
498 service_metrics->stop_on_state[stop_state].push_back(timer);
499}
500
Thieu Lea20cbc22012-01-09 22:01:43 +0000501void Metrics::NotifyDefaultServiceChanged(const Service *service) {
502 base::TimeDelta elapsed_seconds;
503
504 Technology::Identifier technology = (service) ? service->technology() :
505 Technology::kUnknown;
506 if (technology != last_default_technology_) {
507 if (last_default_technology_ != Technology::kUnknown) {
508 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
509 last_default_technology_);
510 time_online_timer_->GetElapsedTime(&elapsed_seconds);
511 SendToUMA(histogram,
512 elapsed_seconds.InSeconds(),
513 kMetricTimeOnlineSecondsMin,
514 kMetricTimeOnlineSecondsMax,
515 kTimerHistogramNumBuckets);
516 }
517 last_default_technology_ = technology;
518 time_online_timer_->Start();
519 }
520
Thieu Lea20cbc22012-01-09 22:01:43 +0000521 // Ignore changes that are not online/offline transitions; e.g.
522 // switching between wired and wireless. TimeToDrop measures
523 // time online regardless of how we are connected.
524 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
525 return;
526
527 if (service == NULL) {
528 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
529 SendToUMA(kMetricTimeToDropSeconds,
530 elapsed_seconds.InSeconds(),
531 kMetricTimeToDropSecondsMin,
532 kMetricTimeToDropSecondsMax,
533 kTimerHistogramNumBuckets);
534 } else {
535 time_to_drop_timer_->Start();
536 }
537
538 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000539}
540
541void Metrics::NotifyServiceStateChanged(const Service *service,
542 Service::ConnectState new_state) {
543 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
544 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700545 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000546 DCHECK(false);
547 return;
548 }
549 ServiceMetrics *service_metrics = it->second.get();
550 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
551
552 if (new_state == Service::kStateFailure)
553 SendServiceFailure(service);
554
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200555 if (collect_bootstats_) {
556 bootstat_log(
557 StringPrintf("network-%s-%s",
558 Technology::NameFromIdentifier(
559 service->technology()).c_str(),
560 service->GetStateString().c_str()).c_str());
561 }
562
Paul Stewart20088d82012-02-16 06:58:55 -0800563 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000564 return;
565
Thieu Leb84ba342012-03-02 15:15:19 -0800566 base::TimeDelta time_resume_to_ready;
567 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
568 time_resume_to_ready_timer_->Reset();
569 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000570}
571
572string Metrics::GetFullMetricName(const char *metric_name,
573 Technology::Identifier technology_id) {
574 string technology = Technology::NameFromIdentifier(technology_id);
575 technology[0] = base::ToUpperASCII(technology[0]);
576 return base::StringPrintf(metric_name, technology.c_str());
577}
578
Thieu Le67370f62012-02-14 23:01:42 +0000579void Metrics::NotifyServiceDisconnect(const Service *service) {
580 Technology::Identifier technology = service->technology();
581 string histogram = GetFullMetricName(kMetricDisconnect, technology);
582 SendToUMA(histogram,
583 service->explicitly_disconnected(),
584 kMetricDisconnectMin,
585 kMetricDisconnectMax,
586 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000587}
588
Thieu Leb84ba342012-03-02 15:15:19 -0800589void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
590 if (new_state == PowerManagerProxyDelegate::kOn) {
591 time_resume_to_ready_timer_->Start();
592 } else {
593 time_resume_to_ready_timer_->Reset();
594 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000595}
596
Arman Ugurayab22c162012-10-08 19:08:38 -0700597void Metrics::NotifyTerminationActionsStarted(
598 TerminationActionReason /*reason*/) {
599 if (time_termination_actions_timer->HasStarted())
600 return;
601 time_termination_actions_timer->Start();
602}
603
604void Metrics::NotifyTerminationActionsCompleted(
605 TerminationActionReason reason, bool success) {
606 if (!time_termination_actions_timer->HasStarted())
607 return;
608
609 int result = success ? kTerminationActionResultSuccess :
610 kTerminationActionResultFailure;
611
612 base::TimeDelta elapsed_time;
613 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
614 time_termination_actions_timer->Reset();
615 string time_metric, result_metric;
616 switch (reason) {
617 case kTerminationActionReasonSuspend:
618 time_metric = kMetricTerminationActionTimeOnSuspend;
619 result_metric = kMetricTerminationActionResultOnSuspend;
620 break;
621 case kTerminationActionReasonTerminate:
622 time_metric = kMetricTerminationActionTimeOnTerminate;
623 result_metric = kMetricTerminationActionResultOnTerminate;
624 break;
625 }
626
627 SendToUMA(time_metric,
628 elapsed_time.InMilliseconds(),
629 kMetricTerminationActionTimeMillisecondsMin,
630 kMetricTerminationActionTimeMillisecondsMax,
631 kTimerHistogramNumBuckets);
632
633 SendEnumToUMA(result_metric,
634 result,
635 kTerminationActionResultMax);
636}
637
Paul Stewartff845fc2012-08-07 07:28:44 -0700638void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700639 Technology::Identifier technology,
640 LinkMonitorFailure failure,
Paul Stewartf1961f82012-09-11 20:45:39 -0700641 int seconds_to_failure,
642 int broadcast_error_count,
643 int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700644 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
645 technology);
646 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700647
648 if (failure == kLinkMonitorFailureThresholdReached) {
649 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
650 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
651 }
652 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
653 technology);
654 SendToUMA(histogram,
655 seconds_to_failure,
656 kMetricLinkMonitorSecondsToFailureMin,
657 kMetricLinkMonitorSecondsToFailureMax,
658 kMetricLinkMonitorSecondsToFailureNumBuckets);
659 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
660 technology);
661 SendToUMA(histogram,
662 broadcast_error_count,
663 kMetricLinkMonitorErrorCountMin,
664 kMetricLinkMonitorErrorCountMax,
665 kMetricLinkMonitorErrorCountNumBuckets);
666 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
667 technology);
668 SendToUMA(histogram,
669 unicast_error_count,
670 kMetricLinkMonitorErrorCountMin,
671 kMetricLinkMonitorErrorCountMax,
672 kMetricLinkMonitorErrorCountNumBuckets);
673 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700674}
675
676void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
677 Technology::Identifier technology,
Paul Stewartf1961f82012-09-11 20:45:39 -0700678 int response_time_milliseconds) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700679 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
680 technology);
681 SendToUMA(histogram,
682 response_time_milliseconds,
683 kMetricLinkMonitorResponseTimeSampleMin,
684 kMetricLinkMonitorResponseTimeSampleMax,
685 kMetricLinkMonitorResponseTimeSampleNumBuckets);
686}
687
Wade Guthried4977f22012-08-22 12:37:54 -0700688void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
689 IEEE_80211::WiFiReasonCode reason) {
690 string metric_disconnect_reason;
691 string metric_disconnect_type;
692 WiFiStatusType type;
693
694 if (by_whom == kDisconnectedByAp) {
695 metric_disconnect_reason = kMetricLinkApDisconnectReason;
696 metric_disconnect_type = kMetricLinkApDisconnectType;
697 type = kStatusCodeTypeByAp;
698 } else {
699 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
700 metric_disconnect_type = kMetricLinkClientDisconnectType;
Wade Guthrie60a37062013-04-02 11:39:09 -0700701 switch (reason) {
Wade Guthried4977f22012-08-22 12:37:54 -0700702 case IEEE_80211::kReasonCodeSenderHasLeft:
703 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
704 type = kStatusCodeTypeByUser;
705 break;
706
707 case IEEE_80211::kReasonCodeInactivity:
708 type = kStatusCodeTypeConsideredDead;
709 break;
710
711 default:
712 type = kStatusCodeTypeByClient;
713 break;
714 }
715 }
716 SendEnumToUMA(metric_disconnect_reason, reason,
717 IEEE_80211::kStatusCodeMax);
718 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
719}
720
Thieu Lec8078a62013-01-22 18:01:12 -0800721void Metrics::RegisterDevice(int interface_index,
722 Technology::Identifier technology) {
Thieu Le9abd6742013-01-23 23:35:37 -0800723 SLOG(Metrics, 2) << __func__ << ": " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800724 shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
725 devices_metrics_[interface_index] = device_metrics;
Thieu Le9abd6742013-01-23 23:35:37 -0800726 device_metrics->technology = technology;
Thieu Lec8078a62013-01-22 18:01:12 -0800727 string histogram = GetFullMetricName(kMetricTimeToInitializeMilliseconds,
728 technology);
729 device_metrics->initialization_timer.reset(
730 new chromeos_metrics::TimerReporter(
731 histogram,
732 kMetricTimeToInitializeMillisecondsMin,
733 kMetricTimeToInitializeMillisecondsMax,
734 kMetricTimeToInitializeMillisecondsNumBuckets));
735 device_metrics->initialization_timer->Start();
Thieu Lece4483e2013-01-23 15:12:03 -0800736 histogram = GetFullMetricName(kMetricTimeToEnableMilliseconds,
737 technology);
738 device_metrics->enable_timer.reset(
739 new chromeos_metrics::TimerReporter(
740 histogram,
741 kMetricTimeToEnableMillisecondsMin,
742 kMetricTimeToEnableMillisecondsMax,
743 kMetricTimeToEnableMillisecondsNumBuckets));
Thieu Lea2519bf2013-01-23 16:51:54 -0800744 histogram = GetFullMetricName(kMetricTimeToDisableMilliseconds,
745 technology);
746 device_metrics->disable_timer.reset(
747 new chromeos_metrics::TimerReporter(
748 histogram,
749 kMetricTimeToDisableMillisecondsMin,
750 kMetricTimeToDisableMillisecondsMax,
751 kMetricTimeToDisableMillisecondsNumBuckets));
Thieu Le18c11072013-01-28 17:21:37 -0800752 histogram = GetFullMetricName(kMetricTimeToScanMilliseconds,
753 technology);
754 device_metrics->scan_timer.reset(
755 new chromeos_metrics::TimerReporter(
756 histogram,
757 kMetricTimeToScanMillisecondsMin,
758 kMetricTimeToScanMillisecondsMax,
759 kMetricTimeToScanMillisecondsNumBuckets));
Thieu Lecdb5a212013-01-25 11:17:18 -0800760 histogram = GetFullMetricName(kMetricTimeToConnectMilliseconds,
761 technology);
762 device_metrics->connect_timer.reset(
763 new chromeos_metrics::TimerReporter(
764 histogram,
765 kMetricTimeToConnectMillisecondsMin,
766 kMetricTimeToConnectMillisecondsMax,
767 kMetricTimeToConnectMillisecondsNumBuckets));
Thieu Le7cf36b02013-01-30 17:15:56 -0800768 device_metrics->auto_connect_timer.reset(
769 new chromeos_metrics::TimerReporter(
770 kMetricCellularAutoConnectTotalTime,
771 kMetricCellularAutoConnectTotalTimeMin,
772 kMetricCellularAutoConnectTotalTimeMax,
773 kMetricCellularAutoConnectTotalTimeNumBuckets));
Thieu Lec8078a62013-01-22 18:01:12 -0800774}
775
Thieu Le9abd6742013-01-23 23:35:37 -0800776bool Metrics::IsDeviceRegistered(int interface_index,
777 Technology::Identifier technology) {
778 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index
779 << ", technology: " << technology;
780 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
781 if (device_metrics == NULL)
782 return false;
783 // Make sure the device technologies match.
784 return (technology == device_metrics->technology);
785}
786
Thieu Lec8078a62013-01-22 18:01:12 -0800787void Metrics::DeregisterDevice(int interface_index) {
Thieu Le9abd6742013-01-23 23:35:37 -0800788 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800789 devices_metrics_.erase(interface_index);
790}
791
792void Metrics::NotifyDeviceInitialized(int interface_index) {
Thieu Lece4483e2013-01-23 15:12:03 -0800793 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
794 if (device_metrics == NULL)
Thieu Lec8078a62013-01-22 18:01:12 -0800795 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700796 if (!device_metrics->initialization_timer->Stop())
797 return;
Thieu Lec8078a62013-01-22 18:01:12 -0800798 device_metrics->initialization_timer->ReportMilliseconds();
799}
800
Thieu Lece4483e2013-01-23 15:12:03 -0800801void Metrics::NotifyDeviceEnableStarted(int interface_index) {
802 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
803 if (device_metrics == NULL)
804 return;
805 device_metrics->enable_timer->Start();
806}
807
808void Metrics::NotifyDeviceEnableFinished(int interface_index) {
809 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
810 if (device_metrics == NULL)
811 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700812 if (!device_metrics->enable_timer->Stop())
813 return;
Thieu Lece4483e2013-01-23 15:12:03 -0800814 device_metrics->enable_timer->ReportMilliseconds();
815}
816
Thieu Lea2519bf2013-01-23 16:51:54 -0800817void Metrics::NotifyDeviceDisableStarted(int interface_index) {
818 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
819 if (device_metrics == NULL)
820 return;
821 device_metrics->disable_timer->Start();
822}
823
824void Metrics::NotifyDeviceDisableFinished(int interface_index) {
825 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
826 if (device_metrics == NULL)
827 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700828 if (!device_metrics->disable_timer->Stop())
829 return;
Thieu Lea2519bf2013-01-23 16:51:54 -0800830 device_metrics->disable_timer->ReportMilliseconds();
831}
832
Thieu Le18c11072013-01-28 17:21:37 -0800833void Metrics::NotifyDeviceScanStarted(int interface_index) {
834 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
835 if (device_metrics == NULL)
836 return;
Thieu Le18c11072013-01-28 17:21:37 -0800837 device_metrics->scan_timer->Start();
838}
839
840void Metrics::NotifyDeviceScanFinished(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->scan_timer->Stop())
845 return;
Wade Guthrie68d41092013-04-02 12:56:02 -0700846 // Don't send TimeToScan metrics if the elapsed time exceeds the max metrics
847 // value. Huge scan times usually mean something's gone awry; for cellular,
848 // for instance, this usually means that the modem is in an area without
849 // service and we're not interested in this scenario.
Thieu Le18c11072013-01-28 17:21:37 -0800850 base::TimeDelta elapsed_time;
851 device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
852 if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
853 device_metrics->scan_timer->ReportMilliseconds();
854}
855
Thieu Le7cf36b02013-01-30 17:15:56 -0800856void Metrics::NotifyDeviceConnectStarted(int interface_index,
857 bool is_auto_connecting) {
Thieu Lecdb5a212013-01-25 11:17:18 -0800858 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
859 if (device_metrics == NULL)
860 return;
861 device_metrics->connect_timer->Start();
Thieu Le7cf36b02013-01-30 17:15:56 -0800862
863 if (is_auto_connecting) {
864 device_metrics->auto_connect_tries++;
865 if (device_metrics->auto_connect_tries == 1)
866 device_metrics->auto_connect_timer->Start();
867 } else {
868 AutoConnectMetricsReset(device_metrics);
869 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800870}
871
872void Metrics::NotifyDeviceConnectFinished(int interface_index) {
873 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
874 if (device_metrics == NULL)
875 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700876 if (!device_metrics->connect_timer->Stop())
877 return;
Thieu Lecdb5a212013-01-25 11:17:18 -0800878 device_metrics->connect_timer->ReportMilliseconds();
Thieu Le7cf36b02013-01-30 17:15:56 -0800879
880 if (device_metrics->auto_connect_tries > 0) {
Wade Guthrie091c41c2013-03-22 15:48:53 -0700881 if (!device_metrics->auto_connect_timer->Stop())
882 return;
Thieu Le7cf36b02013-01-30 17:15:56 -0800883 base::TimeDelta elapsed_time;
884 device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
885 if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
886 return;
887 device_metrics->auto_connect_timer->ReportMilliseconds();
888 SendToUMA(kMetricCellularAutoConnectTries,
889 device_metrics->auto_connect_tries,
890 kMetricCellularAutoConnectTriesMin,
891 kMetricCellularAutoConnectTriesMax,
892 kMetricCellularAutoConnectTriesNumBuckets);
893 AutoConnectMetricsReset(device_metrics);
894 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800895}
896
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800897void Metrics::NotifyCellularDeviceDrop(int interface_index,
898 const string &network_technology,
Thieu Le26fc01b2013-01-28 12:08:48 -0800899 uint16 signal_strength) {
900 SLOG(Metrics, 2) << __func__ << ": " << network_technology
901 << ", " << signal_strength;
902 CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
903 if (network_technology == flimflam::kNetworkTechnology1Xrtt) {
904 drop_technology = kCellularDropTechnology1Xrtt;
905 } else if (network_technology == flimflam::kNetworkTechnologyEdge) {
906 drop_technology = kCellularDropTechnologyEdge;
907 } else if (network_technology == flimflam::kNetworkTechnologyEvdo) {
908 drop_technology = kCellularDropTechnologyEvdo;
909 } else if (network_technology == flimflam::kNetworkTechnologyGprs) {
910 drop_technology = kCellularDropTechnologyGprs;
911 } else if (network_technology == flimflam::kNetworkTechnologyGsm) {
912 drop_technology = kCellularDropTechnologyGsm;
913 } else if (network_technology == flimflam::kNetworkTechnologyHspa) {
914 drop_technology = kCellularDropTechnologyHspa;
915 } else if (network_technology == flimflam::kNetworkTechnologyHspaPlus) {
916 drop_technology = kCellularDropTechnologyHspaPlus;
917 } else if (network_technology == flimflam::kNetworkTechnologyLte) {
918 drop_technology = kCellularDropTechnologyLte;
919 } else if (network_technology == flimflam::kNetworkTechnologyUmts) {
920 drop_technology = kCellularDropTechnologyUmts;
921 }
922 SendEnumToUMA(kMetricCellularDrop,
923 drop_technology,
924 kCellularDropTechnologyMax);
925 SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
926 signal_strength,
927 kMetricCellularSignalStrengthBeforeDropMin,
928 kMetricCellularSignalStrengthBeforeDropMax,
929 kMetricCellularSignalStrengthBeforeDropNumBuckets);
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800930
931 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
932 if (device_metrics == NULL)
933 return;
934 device_metrics->num_drops++;
Thieu Le26fc01b2013-01-28 12:08:48 -0800935}
936
Thieu Leb7aa5f72013-01-31 15:57:48 -0800937void Metrics::NotifyCellularDeviceFailure(const Error &error) {
938 library_->SendUserActionToUMA(
939 kMetricCellularFailureReason + error.message());
940}
941
Thieu Le91fccf62013-04-22 15:23:16 -0700942void Metrics::NotifyCellularOutOfCredits(
943 Metrics::CellularOutOfCreditsReason reason) {
944 SendEnumToUMA(kMetricCellularOutOfCreditsReason,
945 reason,
946 kCellularOutOfCreditsReasonMax);
947}
948
Thieu Le5133b712013-02-19 14:47:21 -0800949void Metrics::NotifyCorruptedProfile() {
950 SendEnumToUMA(kMetricCorruptedProfile,
951 kCorruptedProfile,
952 kCorruptedProfileMax);
953}
954
Thieu Le48e6d6d2011-12-06 00:40:27 +0000955bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
956 return library_->SendEnumToUMA(name, sample, max);
957}
958
Thieu Lea20cbc22012-01-09 22:01:43 +0000959bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
960 int num_buckets) {
961 return library_->SendToUMA(name, sample, min, max, num_buckets);
962}
963
Thieu Le48e6d6d2011-12-06 00:40:27 +0000964void Metrics::InitializeCommonServiceMetrics(const Service *service) {
965 Technology::Identifier technology = service->technology();
966 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
967 technology);
968 AddServiceStateTransitionTimer(
969 service,
970 histogram,
971 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800972 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000973 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
974 AddServiceStateTransitionTimer(
975 service,
976 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800977 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000978 Service::kStatePortal);
979 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
980 AddServiceStateTransitionTimer(
981 service,
982 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800983 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000984 Service::kStateOnline);
985}
986
987void Metrics::UpdateServiceStateTransitionMetrics(
988 ServiceMetrics *service_metrics,
989 Service::ConnectState new_state) {
990 TimerReportersList::iterator it;
991 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
992 for (it = start_timers.begin(); it != start_timers.end(); ++it)
993 (*it)->Start();
994
995 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
996 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
Wade Guthrie091c41c2013-03-22 15:48:53 -0700997 if ((*it)->Stop())
998 (*it)->ReportMilliseconds();
Thieu Le48e6d6d2011-12-06 00:40:27 +0000999 }
1000}
1001
1002void Metrics::SendServiceFailure(const Service *service) {
1003 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
1004 service->failure(),
1005 kMetricNetworkServiceErrorsMax);
1006}
1007
Thieu Le9abd6742013-01-23 23:35:37 -08001008Metrics::DeviceMetrics *Metrics::GetDeviceMetrics(int interface_index) const {
1009 DeviceMetricsLookupMap::const_iterator it =
1010 devices_metrics_.find(interface_index);
Thieu Lece4483e2013-01-23 15:12:03 -08001011 if (it == devices_metrics_.end()) {
Thieu Le9abd6742013-01-23 23:35:37 -08001012 SLOG(Metrics, 2) << __func__ << ": device " << interface_index
1013 << " not found";
Thieu Lece4483e2013-01-23 15:12:03 -08001014 return NULL;
1015 }
1016 return it->second.get();
1017}
1018
Thieu Le7cf36b02013-01-30 17:15:56 -08001019void Metrics::AutoConnectMetricsReset(DeviceMetrics *device_metrics) {
1020 device_metrics->auto_connect_tries = 0;
1021 device_metrics->auto_connect_timer->Reset();
1022}
1023
Thieu Le6c1e3bb2013-02-06 15:20:35 -08001024void Metrics::HourlyTimeoutHandler() {
1025 SLOG(Metrics, 2) << __func__;
1026 DeviceMetricsLookupMap::iterator it;
1027 for (it = devices_metrics_.begin(); it != devices_metrics_.end(); ++it) {
1028 if (it->second->technology != Technology::kCellular ||
1029 it->second->num_drops == 0)
1030 continue;
1031 SendToUMA(kMetricCellularDropsPerHour,
1032 it->second->num_drops,
1033 kMetricCellularDropsPerHourMin,
1034 kMetricCellularDropsPerHourMax,
1035 kMetricCellularDropsPerHourNumBuckets);
1036 it->second->num_drops = 0;
1037 }
1038 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
1039 kHourlyTimeoutMilliseconds);
1040}
1041
Thieu Le48e6d6d2011-12-06 00:40:27 +00001042void Metrics::set_library(MetricsLibraryInterface *library) {
1043 chromeos_metrics::TimerReporter::set_metrics_lib(library);
1044 library_ = library;
1045}
1046
1047} // namespace shill