blob: 4fb083cc7901bd0750c40a1b41f31cf9e8313e28 [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
Wade Guthrief22681f2013-05-31 11:46:31 -0700142const char Metrics::kMetricWiFiScanTimeInEbusyMilliseconds[] =
143 "Network.Shill.WiFi.ScanTimeInEbusy";
144
Arman Ugurayab22c162012-10-08 19:08:38 -0700145const char Metrics::kMetricTerminationActionTimeOnTerminate[] =
146 "Network.Shill.TerminationActionTime.OnTerminate";
147const char Metrics::kMetricTerminationActionResultOnTerminate[] =
148 "Network.Shill.TerminationActionResult.OnTerminate";
149const char Metrics::kMetricTerminationActionTimeOnSuspend[] =
150 "Network.Shill.TerminationActionTime.OnSuspend";
151const char Metrics::kMetricTerminationActionResultOnSuspend[] =
152 "Network.Shill.TerminationActionResult.OnSuspend";
153const int Metrics::kMetricTerminationActionTimeMillisecondsMax = 10000;
154const int Metrics::kMetricTerminationActionTimeMillisecondsMin = 1;
Arman Uguray6d528f12012-09-13 13:44:55 -0700155
Thieu Le48e6d6d2011-12-06 00:40:27 +0000156// static
Paul Stewart85aea152013-01-22 09:31:56 -0800157const char Metrics::kMetricServiceFixupEntries[] =
158 "Network.Shill.%s.ServiceFixupEntries";
159
160// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000161const uint16 Metrics::kWiFiBandwidth5MHz = 5;
162const uint16 Metrics::kWiFiBandwidth20MHz = 20;
163const uint16 Metrics::kWiFiFrequency2412 = 2412;
164const uint16 Metrics::kWiFiFrequency2472 = 2472;
165const uint16 Metrics::kWiFiFrequency2484 = 2484;
166const uint16 Metrics::kWiFiFrequency5170 = 5170;
167const uint16 Metrics::kWiFiFrequency5180 = 5180;
168const uint16 Metrics::kWiFiFrequency5230 = 5230;
169const uint16 Metrics::kWiFiFrequency5240 = 5240;
170const uint16 Metrics::kWiFiFrequency5320 = 5320;
171const uint16 Metrics::kWiFiFrequency5500 = 5500;
172const uint16 Metrics::kWiFiFrequency5700 = 5700;
173const uint16 Metrics::kWiFiFrequency5745 = 5745;
174const uint16 Metrics::kWiFiFrequency5825 = 5825;
175
Thieu Leb84ba342012-03-02 15:15:19 -0800176// static
177const char Metrics::kMetricPowerManagerKey[] = "metrics";
178
Paul Stewartff845fc2012-08-07 07:28:44 -0700179// static
180const char Metrics::kMetricLinkMonitorFailure[] =
181 "Network.Shill.%s.LinkMonitorFailure";
182const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
183 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewartf1961f82012-09-11 20:45:39 -0700184const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
185const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700186 LinkMonitor::kTestPeriodMilliseconds;
187const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700188const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
189 "Network.Shill.%s.LinkMonitorSecondsToFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700190const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
191const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
Paul Stewart0443aa52012-08-09 10:43:50 -0700192const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
193const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
194 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
195const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
196 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700197const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
198const int Metrics::kMetricLinkMonitorErrorCountMax =
Paul Stewart0443aa52012-08-09 10:43:50 -0700199 LinkMonitor::kFailureThreshold;
200const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
201 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700202
Wade Guthried4977f22012-08-22 12:37:54 -0700203// static
204const char Metrics::kMetricLinkClientDisconnectReason[] =
205 "Network.Shill.WiFi.ClientDisconnectReason";
206const char Metrics::kMetricLinkApDisconnectReason[] =
207 "Network.Shill.WiFi.ApDisconnectReason";
208const char Metrics::kMetricLinkClientDisconnectType[] =
209 "Network.Shill.WiFi.ClientDisconnectType";
210const char Metrics::kMetricLinkApDisconnectType[] =
211 "Network.Shill.WiFi.ApDisconnectType";
212
Thieu Le26fc01b2013-01-28 12:08:48 -0800213// static
Thieu Le91fccf62013-04-22 15:23:16 -0700214const char Metrics::kMetricCellularAutoConnectTries[] =
215 "Network.Shill.Cellular.AutoConnectTries";
216const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
217const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
218const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
219const char Metrics::kMetricCellularAutoConnectTotalTime[] =
220 "Network.Shill.Cellular.AutoConnectTotalTime";
221const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
222 60 * 1000; // 60 seconds
223const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
224const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
Thieu Le26fc01b2013-01-28 12:08:48 -0800225const char Metrics::kMetricCellularDrop[] =
226 "Network.Shill.Cellular.Drop";
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800227const char Metrics::kMetricCellularDropsPerHour[] =
228 "Network.Shill.Cellular.DropsPerHour";
229const int Metrics::kMetricCellularDropsPerHourMax = 60;
230const int Metrics::kMetricCellularDropsPerHourMin = 1;
231const int Metrics::kMetricCellularDropsPerHourNumBuckets = 10;
Thieu Leb7aa5f72013-01-31 15:57:48 -0800232// The format of FailureReason is different to other metrics because this
233// name is prepended to the error message before the entire string is sent
234// via SendUserActionToUMA.
235const char Metrics::kMetricCellularFailureReason[] =
236 "Network.Shill.Cellular.FailureReason: ";
Thieu Le91fccf62013-04-22 15:23:16 -0700237const char Metrics::kMetricCellularOutOfCreditsReason[] =
238 "Network.Shill.Cellular.OutOfCreditsReason";
Thieu Le26fc01b2013-01-28 12:08:48 -0800239const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
240 "Network.Shill.Cellular.SignalStrengthBeforeDrop";
241const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
242const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
243const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
244
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800245// static
Thieu Le5133b712013-02-19 14:47:21 -0800246const char Metrics::kMetricCorruptedProfile[] =
247 "Network.Shill.CorruptedProfile";
248
249// static
Paul Stewart91a43cb2013-03-02 21:34:15 -0800250const char Metrics::kMetricVpnDriver[] =
251 "Network.Shill.Vpn.Driver";
252const int Metrics::kMetricVpnDriverMax = Metrics::kVpnDriverMax;
253const char Metrics::kMetricVpnRemoteAuthenticationType[] =
254 "Network.Shill.Vpn.RemoteAuthenticationType";
255const int Metrics::kMetricVpnRemoteAuthenticationTypeMax =
256 Metrics::kVpnRemoteAuthenticationTypeMax;
257const char Metrics::kMetricVpnUserAuthenticationType[] =
258 "Network.Shill.Vpn.UserAuthenticationType";
259const int Metrics::kMetricVpnUserAuthenticationTypeMax =
260 Metrics::kVpnUserAuthenticationTypeMax;
261
262// static
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800263const int Metrics::kHourlyTimeoutMilliseconds = 3600 * 1000; // One hour
Wade Guthried4977f22012-08-22 12:37:54 -0700264
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800265
266Metrics::Metrics(EventDispatcher *dispatcher)
267 : dispatcher_(dispatcher),
268 library_(&metrics_library_),
Thieu Lea20cbc22012-01-09 22:01:43 +0000269 last_default_technology_(Technology::kUnknown),
270 was_online_(false),
271 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800272 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200273 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
Arman Ugurayab22c162012-10-08 19:08:38 -0700274 time_termination_actions_timer(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200275 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000276 metrics_library_.Init();
277 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
278}
279
280Metrics::~Metrics() {}
281
282// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000283Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
284 WiFiChannel channel = kWiFiChannelUndef;
285 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
286 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
287 channel = static_cast<WiFiChannel>(
288 kWiFiChannel2412 +
289 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
290 } else if (frequency == kWiFiFrequency2484) {
291 channel = kWiFiChannel2484;
292 } else if (kWiFiFrequency5170 <= frequency &&
293 frequency <= kWiFiFrequency5230) {
294 if ((frequency % kWiFiBandwidth20MHz) == 0)
295 channel = static_cast<WiFiChannel>(
296 kWiFiChannel5180 +
297 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
298 if ((frequency % kWiFiBandwidth20MHz) == 10)
299 channel = static_cast<WiFiChannel>(
300 kWiFiChannel5170 +
301 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
302 } else if (kWiFiFrequency5240 <= frequency &&
303 frequency <= kWiFiFrequency5320) {
304 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
305 channel = static_cast<WiFiChannel>(
306 kWiFiChannel5180 +
307 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
308 } else if (kWiFiFrequency5500 <= frequency &&
309 frequency <= kWiFiFrequency5700) {
310 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
311 channel = static_cast<WiFiChannel>(
312 kWiFiChannel5500 +
313 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
314 } else if (kWiFiFrequency5745 <= frequency &&
315 frequency <= kWiFiFrequency5825) {
316 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
317 channel = static_cast<WiFiChannel>(
318 kWiFiChannel5745 +
319 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
320 }
321 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
322
323 if (channel == kWiFiChannelUndef)
324 LOG(WARNING) << "no mapping for frequency " << frequency;
325 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700326 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000327
328 return channel;
329}
330
Thieu Lead1ec2c2012-01-05 23:39:48 +0000331// static
332Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
333 const std::string &security) {
334 if (security == flimflam::kSecurityNone) {
335 return kWiFiSecurityNone;
336 } else if (security == flimflam::kSecurityWep) {
337 return kWiFiSecurityWep;
338 } else if (security == flimflam::kSecurityWpa) {
339 return kWiFiSecurityWpa;
340 } else if (security == flimflam::kSecurityRsn) {
341 return kWiFiSecurityRsn;
342 } else if (security == flimflam::kSecurity8021x) {
343 return kWiFiSecurity8021x;
344 } else if (security == flimflam::kSecurityPsk) {
345 return kWiFiSecurityPsk;
346 } else {
347 return kWiFiSecurityUnknown;
348 }
349}
350
Thieu Le85e050b2012-03-13 15:04:38 -0700351// static
Paul Stewart21f40962013-03-01 14:27:28 -0800352Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
353 const std::string &outer) {
354 if (outer == flimflam::kEapMethodPEAP) {
355 return kEapOuterProtocolPeap;
356 } else if (outer == flimflam::kEapMethodTLS) {
357 return kEapOuterProtocolTls;
358 } else if (outer == flimflam::kEapMethodTTLS) {
359 return kEapOuterProtocolTtls;
360 } else if (outer == flimflam::kEapMethodLEAP) {
361 return kEapOuterProtocolLeap;
362 } else {
363 return kEapOuterProtocolUnknown;
364 }
365}
366
367// static
368Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
369 const std::string &inner) {
370 if (inner.empty()) {
371 return kEapInnerProtocolNone;
372 } else if (inner == flimflam::kEapPhase2AuthPEAPMD5) {
373 return kEapInnerProtocolPeapMd5;
374 } else if (inner == flimflam::kEapPhase2AuthPEAPMSCHAPV2) {
375 return kEapInnerProtocolPeapMschapv2;
376 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMD5) {
377 return kEapInnerProtocolTtlsEapMd5;
378 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMSCHAPV2) {
379 return kEapInnerProtocolTtlsEapMschapv2;
380 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAPV2) {
381 return kEapInnerProtocolTtlsMschapv2;
382 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAP) {
383 return kEapInnerProtocolTtlsMschap;
384 } else if (inner == flimflam::kEapPhase2AuthTTLSPAP) {
385 return kEapInnerProtocolTtlsPap;
386 } else if (inner == flimflam::kEapPhase2AuthTTLSCHAP) {
387 return kEapInnerProtocolTtlsChap;
388 } else {
389 return kEapInnerProtocolUnknown;
390 }
391}
392
393// static
Thieu Le85e050b2012-03-13 15:04:38 -0700394Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
395 const PortalDetector::Result &result) {
396 DCHECK(result.final);
397 PortalResult retval = kPortalResultUnknown;
398 // The only time we should end a successful portal detection is when we're
399 // in the Content phase. If we end with kStatusSuccess in any other phase,
400 // then this indicates that something bad has happened.
401 switch (result.phase) {
402 case PortalDetector::kPhaseDNS:
403 if (result.status == PortalDetector::kStatusFailure)
404 retval = kPortalResultDNSFailure;
405 else if (result.status == PortalDetector::kStatusTimeout)
406 retval = kPortalResultDNSTimeout;
407 else
408 LOG(DFATAL) << __func__ << ": Final result status " << result.status
409 << " is not allowed in the DNS phase";
410 break;
411
412 case PortalDetector::kPhaseConnection:
413 if (result.status == PortalDetector::kStatusFailure)
414 retval = kPortalResultConnectionFailure;
415 else if (result.status == PortalDetector::kStatusTimeout)
416 retval = kPortalResultConnectionTimeout;
417 else
418 LOG(DFATAL) << __func__ << ": Final result status " << result.status
419 << " is not allowed in the Connection phase";
420 break;
421
422 case PortalDetector::kPhaseHTTP:
423 if (result.status == PortalDetector::kStatusFailure)
424 retval = kPortalResultHTTPFailure;
425 else if (result.status == PortalDetector::kStatusTimeout)
426 retval = kPortalResultHTTPTimeout;
427 else
428 LOG(DFATAL) << __func__ << ": Final result status " << result.status
429 << " is not allowed in the HTTP phase";
430 break;
431
432 case PortalDetector::kPhaseContent:
433 if (result.status == PortalDetector::kStatusSuccess)
434 retval = kPortalResultSuccess;
435 else if (result.status == PortalDetector::kStatusFailure)
436 retval = kPortalResultContentFailure;
437 else if (result.status == PortalDetector::kStatusTimeout)
438 retval = kPortalResultContentTimeout;
439 else
440 LOG(DFATAL) << __func__ << ": Final result status " << result.status
441 << " is not allowed in the Content phase";
442 break;
443
444 case PortalDetector::kPhaseUnknown:
445 retval = kPortalResultUnknown;
446 break;
447
448 default:
449 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
450 break;
451 }
452
453 return retval;
454}
455
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800456void Metrics::Start() {
457 SLOG(Metrics, 2) << __func__;
458 hourly_timeout_handler_.Reset(
459 Bind(&Metrics::HourlyTimeoutHandler, Unretained(this)));
460 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
461 kHourlyTimeoutMilliseconds);
462}
463
464void Metrics::Stop() {
465 SLOG(Metrics, 2) << __func__;
466 hourly_timeout_handler_.Cancel();
467}
468
Thieu Le48e6d6d2011-12-06 00:40:27 +0000469void Metrics::RegisterService(const Service *service) {
470 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
471 services_metrics_[service] = service_metrics;
472 service_metrics->service = service;
473 InitializeCommonServiceMetrics(service);
474 service->InitializeCustomMetrics();
475}
476
477void Metrics::DeregisterService(const Service *service) {
478 services_metrics_.erase(service);
479}
480
481void Metrics::AddServiceStateTransitionTimer(
482 const Service *service,
483 const string &histogram_name,
484 Service::ConnectState start_state,
485 Service::ConnectState stop_state) {
486 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
487 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700488 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000489 DCHECK(false);
490 return;
491 }
492 ServiceMetrics *service_metrics = it->second.get();
493 CHECK(start_state < stop_state);
494 chromeos_metrics::TimerReporter *timer =
495 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000496 kTimerHistogramMillisecondsMin,
497 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000498 kTimerHistogramNumBuckets);
499 service_metrics->timers.push_back(timer); // passes ownership.
500 service_metrics->start_on_state[start_state].push_back(timer);
501 service_metrics->stop_on_state[stop_state].push_back(timer);
502}
503
Thieu Lea20cbc22012-01-09 22:01:43 +0000504void Metrics::NotifyDefaultServiceChanged(const Service *service) {
505 base::TimeDelta elapsed_seconds;
506
507 Technology::Identifier technology = (service) ? service->technology() :
508 Technology::kUnknown;
509 if (technology != last_default_technology_) {
510 if (last_default_technology_ != Technology::kUnknown) {
511 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
512 last_default_technology_);
513 time_online_timer_->GetElapsedTime(&elapsed_seconds);
514 SendToUMA(histogram,
515 elapsed_seconds.InSeconds(),
516 kMetricTimeOnlineSecondsMin,
517 kMetricTimeOnlineSecondsMax,
518 kTimerHistogramNumBuckets);
519 }
520 last_default_technology_ = technology;
521 time_online_timer_->Start();
522 }
523
Thieu Lea20cbc22012-01-09 22:01:43 +0000524 // Ignore changes that are not online/offline transitions; e.g.
525 // switching between wired and wireless. TimeToDrop measures
526 // time online regardless of how we are connected.
527 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
528 return;
529
530 if (service == NULL) {
531 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
532 SendToUMA(kMetricTimeToDropSeconds,
533 elapsed_seconds.InSeconds(),
534 kMetricTimeToDropSecondsMin,
535 kMetricTimeToDropSecondsMax,
536 kTimerHistogramNumBuckets);
537 } else {
538 time_to_drop_timer_->Start();
539 }
540
541 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000542}
543
544void Metrics::NotifyServiceStateChanged(const Service *service,
545 Service::ConnectState new_state) {
546 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
547 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700548 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000549 DCHECK(false);
550 return;
551 }
552 ServiceMetrics *service_metrics = it->second.get();
553 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
554
555 if (new_state == Service::kStateFailure)
556 SendServiceFailure(service);
557
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200558 if (collect_bootstats_) {
559 bootstat_log(
560 StringPrintf("network-%s-%s",
561 Technology::NameFromIdentifier(
562 service->technology()).c_str(),
563 service->GetStateString().c_str()).c_str());
564 }
565
Paul Stewart20088d82012-02-16 06:58:55 -0800566 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000567 return;
568
Thieu Leb84ba342012-03-02 15:15:19 -0800569 base::TimeDelta time_resume_to_ready;
570 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
571 time_resume_to_ready_timer_->Reset();
572 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000573}
574
575string Metrics::GetFullMetricName(const char *metric_name,
576 Technology::Identifier technology_id) {
577 string technology = Technology::NameFromIdentifier(technology_id);
578 technology[0] = base::ToUpperASCII(technology[0]);
579 return base::StringPrintf(metric_name, technology.c_str());
580}
581
Thieu Le67370f62012-02-14 23:01:42 +0000582void Metrics::NotifyServiceDisconnect(const Service *service) {
583 Technology::Identifier technology = service->technology();
584 string histogram = GetFullMetricName(kMetricDisconnect, technology);
585 SendToUMA(histogram,
586 service->explicitly_disconnected(),
587 kMetricDisconnectMin,
588 kMetricDisconnectMax,
589 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000590}
591
Thieu Leb84ba342012-03-02 15:15:19 -0800592void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
593 if (new_state == PowerManagerProxyDelegate::kOn) {
594 time_resume_to_ready_timer_->Start();
595 } else {
596 time_resume_to_ready_timer_->Reset();
597 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000598}
599
Arman Ugurayab22c162012-10-08 19:08:38 -0700600void Metrics::NotifyTerminationActionsStarted(
601 TerminationActionReason /*reason*/) {
602 if (time_termination_actions_timer->HasStarted())
603 return;
604 time_termination_actions_timer->Start();
605}
606
607void Metrics::NotifyTerminationActionsCompleted(
608 TerminationActionReason reason, bool success) {
609 if (!time_termination_actions_timer->HasStarted())
610 return;
611
612 int result = success ? kTerminationActionResultSuccess :
613 kTerminationActionResultFailure;
614
615 base::TimeDelta elapsed_time;
616 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
617 time_termination_actions_timer->Reset();
618 string time_metric, result_metric;
619 switch (reason) {
620 case kTerminationActionReasonSuspend:
621 time_metric = kMetricTerminationActionTimeOnSuspend;
622 result_metric = kMetricTerminationActionResultOnSuspend;
623 break;
624 case kTerminationActionReasonTerminate:
625 time_metric = kMetricTerminationActionTimeOnTerminate;
626 result_metric = kMetricTerminationActionResultOnTerminate;
627 break;
628 }
629
630 SendToUMA(time_metric,
631 elapsed_time.InMilliseconds(),
632 kMetricTerminationActionTimeMillisecondsMin,
633 kMetricTerminationActionTimeMillisecondsMax,
634 kTimerHistogramNumBuckets);
635
636 SendEnumToUMA(result_metric,
637 result,
638 kTerminationActionResultMax);
639}
640
Paul Stewartff845fc2012-08-07 07:28:44 -0700641void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700642 Technology::Identifier technology,
643 LinkMonitorFailure failure,
Paul Stewartf1961f82012-09-11 20:45:39 -0700644 int seconds_to_failure,
645 int broadcast_error_count,
646 int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700647 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
648 technology);
649 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700650
651 if (failure == kLinkMonitorFailureThresholdReached) {
652 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
653 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
654 }
655 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
656 technology);
657 SendToUMA(histogram,
658 seconds_to_failure,
659 kMetricLinkMonitorSecondsToFailureMin,
660 kMetricLinkMonitorSecondsToFailureMax,
661 kMetricLinkMonitorSecondsToFailureNumBuckets);
662 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
663 technology);
664 SendToUMA(histogram,
665 broadcast_error_count,
666 kMetricLinkMonitorErrorCountMin,
667 kMetricLinkMonitorErrorCountMax,
668 kMetricLinkMonitorErrorCountNumBuckets);
669 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
670 technology);
671 SendToUMA(histogram,
672 unicast_error_count,
673 kMetricLinkMonitorErrorCountMin,
674 kMetricLinkMonitorErrorCountMax,
675 kMetricLinkMonitorErrorCountNumBuckets);
676 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700677}
678
679void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
680 Technology::Identifier technology,
Paul Stewartf1961f82012-09-11 20:45:39 -0700681 int response_time_milliseconds) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700682 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
683 technology);
684 SendToUMA(histogram,
685 response_time_milliseconds,
686 kMetricLinkMonitorResponseTimeSampleMin,
687 kMetricLinkMonitorResponseTimeSampleMax,
688 kMetricLinkMonitorResponseTimeSampleNumBuckets);
689}
690
Wade Guthried4977f22012-08-22 12:37:54 -0700691void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
692 IEEE_80211::WiFiReasonCode reason) {
693 string metric_disconnect_reason;
694 string metric_disconnect_type;
695 WiFiStatusType type;
696
697 if (by_whom == kDisconnectedByAp) {
698 metric_disconnect_reason = kMetricLinkApDisconnectReason;
699 metric_disconnect_type = kMetricLinkApDisconnectType;
700 type = kStatusCodeTypeByAp;
701 } else {
702 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
703 metric_disconnect_type = kMetricLinkClientDisconnectType;
Wade Guthrie60a37062013-04-02 11:39:09 -0700704 switch (reason) {
Wade Guthried4977f22012-08-22 12:37:54 -0700705 case IEEE_80211::kReasonCodeSenderHasLeft:
706 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
707 type = kStatusCodeTypeByUser;
708 break;
709
710 case IEEE_80211::kReasonCodeInactivity:
711 type = kStatusCodeTypeConsideredDead;
712 break;
713
714 default:
715 type = kStatusCodeTypeByClient;
716 break;
717 }
718 }
719 SendEnumToUMA(metric_disconnect_reason, reason,
720 IEEE_80211::kStatusCodeMax);
721 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
722}
723
Thieu Lec8078a62013-01-22 18:01:12 -0800724void Metrics::RegisterDevice(int interface_index,
725 Technology::Identifier technology) {
Thieu Le9abd6742013-01-23 23:35:37 -0800726 SLOG(Metrics, 2) << __func__ << ": " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800727 shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
728 devices_metrics_[interface_index] = device_metrics;
Thieu Le9abd6742013-01-23 23:35:37 -0800729 device_metrics->technology = technology;
Thieu Lec8078a62013-01-22 18:01:12 -0800730 string histogram = GetFullMetricName(kMetricTimeToInitializeMilliseconds,
731 technology);
732 device_metrics->initialization_timer.reset(
733 new chromeos_metrics::TimerReporter(
734 histogram,
735 kMetricTimeToInitializeMillisecondsMin,
736 kMetricTimeToInitializeMillisecondsMax,
737 kMetricTimeToInitializeMillisecondsNumBuckets));
738 device_metrics->initialization_timer->Start();
Thieu Lece4483e2013-01-23 15:12:03 -0800739 histogram = GetFullMetricName(kMetricTimeToEnableMilliseconds,
740 technology);
741 device_metrics->enable_timer.reset(
742 new chromeos_metrics::TimerReporter(
743 histogram,
744 kMetricTimeToEnableMillisecondsMin,
745 kMetricTimeToEnableMillisecondsMax,
746 kMetricTimeToEnableMillisecondsNumBuckets));
Thieu Lea2519bf2013-01-23 16:51:54 -0800747 histogram = GetFullMetricName(kMetricTimeToDisableMilliseconds,
748 technology);
749 device_metrics->disable_timer.reset(
750 new chromeos_metrics::TimerReporter(
751 histogram,
752 kMetricTimeToDisableMillisecondsMin,
753 kMetricTimeToDisableMillisecondsMax,
754 kMetricTimeToDisableMillisecondsNumBuckets));
Thieu Le18c11072013-01-28 17:21:37 -0800755 histogram = GetFullMetricName(kMetricTimeToScanMilliseconds,
756 technology);
757 device_metrics->scan_timer.reset(
758 new chromeos_metrics::TimerReporter(
759 histogram,
760 kMetricTimeToScanMillisecondsMin,
761 kMetricTimeToScanMillisecondsMax,
762 kMetricTimeToScanMillisecondsNumBuckets));
Thieu Lecdb5a212013-01-25 11:17:18 -0800763 histogram = GetFullMetricName(kMetricTimeToConnectMilliseconds,
764 technology);
765 device_metrics->connect_timer.reset(
766 new chromeos_metrics::TimerReporter(
767 histogram,
768 kMetricTimeToConnectMillisecondsMin,
769 kMetricTimeToConnectMillisecondsMax,
770 kMetricTimeToConnectMillisecondsNumBuckets));
Thieu Le7cf36b02013-01-30 17:15:56 -0800771 device_metrics->auto_connect_timer.reset(
772 new chromeos_metrics::TimerReporter(
773 kMetricCellularAutoConnectTotalTime,
774 kMetricCellularAutoConnectTotalTimeMin,
775 kMetricCellularAutoConnectTotalTimeMax,
776 kMetricCellularAutoConnectTotalTimeNumBuckets));
Thieu Lec8078a62013-01-22 18:01:12 -0800777}
778
Thieu Le9abd6742013-01-23 23:35:37 -0800779bool Metrics::IsDeviceRegistered(int interface_index,
780 Technology::Identifier technology) {
781 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index
782 << ", technology: " << technology;
783 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
784 if (device_metrics == NULL)
785 return false;
786 // Make sure the device technologies match.
787 return (technology == device_metrics->technology);
788}
789
Thieu Lec8078a62013-01-22 18:01:12 -0800790void Metrics::DeregisterDevice(int interface_index) {
Thieu Le9abd6742013-01-23 23:35:37 -0800791 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800792 devices_metrics_.erase(interface_index);
793}
794
795void Metrics::NotifyDeviceInitialized(int interface_index) {
Thieu Lece4483e2013-01-23 15:12:03 -0800796 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
797 if (device_metrics == NULL)
Thieu Lec8078a62013-01-22 18:01:12 -0800798 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700799 if (!device_metrics->initialization_timer->Stop())
800 return;
Thieu Lec8078a62013-01-22 18:01:12 -0800801 device_metrics->initialization_timer->ReportMilliseconds();
802}
803
Thieu Lece4483e2013-01-23 15:12:03 -0800804void Metrics::NotifyDeviceEnableStarted(int interface_index) {
805 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
806 if (device_metrics == NULL)
807 return;
808 device_metrics->enable_timer->Start();
809}
810
811void Metrics::NotifyDeviceEnableFinished(int interface_index) {
812 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
813 if (device_metrics == NULL)
814 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700815 if (!device_metrics->enable_timer->Stop())
816 return;
Thieu Lece4483e2013-01-23 15:12:03 -0800817 device_metrics->enable_timer->ReportMilliseconds();
818}
819
Thieu Lea2519bf2013-01-23 16:51:54 -0800820void Metrics::NotifyDeviceDisableStarted(int interface_index) {
821 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
822 if (device_metrics == NULL)
823 return;
824 device_metrics->disable_timer->Start();
825}
826
827void Metrics::NotifyDeviceDisableFinished(int interface_index) {
828 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
829 if (device_metrics == NULL)
830 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700831 if (!device_metrics->disable_timer->Stop())
832 return;
Thieu Lea2519bf2013-01-23 16:51:54 -0800833 device_metrics->disable_timer->ReportMilliseconds();
834}
835
Thieu Le18c11072013-01-28 17:21:37 -0800836void Metrics::NotifyDeviceScanStarted(int interface_index) {
837 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
838 if (device_metrics == NULL)
839 return;
Thieu Le18c11072013-01-28 17:21:37 -0800840 device_metrics->scan_timer->Start();
841}
842
843void Metrics::NotifyDeviceScanFinished(int interface_index) {
844 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
845 if (device_metrics == NULL)
846 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700847 if (!device_metrics->scan_timer->Stop())
848 return;
Wade Guthrie68d41092013-04-02 12:56:02 -0700849 // Don't send TimeToScan metrics if the elapsed time exceeds the max metrics
850 // value. Huge scan times usually mean something's gone awry; for cellular,
851 // for instance, this usually means that the modem is in an area without
852 // service and we're not interested in this scenario.
Thieu Le18c11072013-01-28 17:21:37 -0800853 base::TimeDelta elapsed_time;
854 device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
855 if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
856 device_metrics->scan_timer->ReportMilliseconds();
857}
858
Thieu Le7cf36b02013-01-30 17:15:56 -0800859void Metrics::NotifyDeviceConnectStarted(int interface_index,
860 bool is_auto_connecting) {
Thieu Lecdb5a212013-01-25 11:17:18 -0800861 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
862 if (device_metrics == NULL)
863 return;
864 device_metrics->connect_timer->Start();
Thieu Le7cf36b02013-01-30 17:15:56 -0800865
866 if (is_auto_connecting) {
867 device_metrics->auto_connect_tries++;
868 if (device_metrics->auto_connect_tries == 1)
869 device_metrics->auto_connect_timer->Start();
870 } else {
871 AutoConnectMetricsReset(device_metrics);
872 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800873}
874
875void Metrics::NotifyDeviceConnectFinished(int interface_index) {
876 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
877 if (device_metrics == NULL)
878 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700879 if (!device_metrics->connect_timer->Stop())
880 return;
Thieu Lecdb5a212013-01-25 11:17:18 -0800881 device_metrics->connect_timer->ReportMilliseconds();
Thieu Le7cf36b02013-01-30 17:15:56 -0800882
883 if (device_metrics->auto_connect_tries > 0) {
Wade Guthrie091c41c2013-03-22 15:48:53 -0700884 if (!device_metrics->auto_connect_timer->Stop())
885 return;
Thieu Le7cf36b02013-01-30 17:15:56 -0800886 base::TimeDelta elapsed_time;
887 device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
888 if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
889 return;
890 device_metrics->auto_connect_timer->ReportMilliseconds();
891 SendToUMA(kMetricCellularAutoConnectTries,
892 device_metrics->auto_connect_tries,
893 kMetricCellularAutoConnectTriesMin,
894 kMetricCellularAutoConnectTriesMax,
895 kMetricCellularAutoConnectTriesNumBuckets);
896 AutoConnectMetricsReset(device_metrics);
897 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800898}
899
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800900void Metrics::NotifyCellularDeviceDrop(int interface_index,
901 const string &network_technology,
Thieu Le26fc01b2013-01-28 12:08:48 -0800902 uint16 signal_strength) {
903 SLOG(Metrics, 2) << __func__ << ": " << network_technology
904 << ", " << signal_strength;
905 CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
906 if (network_technology == flimflam::kNetworkTechnology1Xrtt) {
907 drop_technology = kCellularDropTechnology1Xrtt;
908 } else if (network_technology == flimflam::kNetworkTechnologyEdge) {
909 drop_technology = kCellularDropTechnologyEdge;
910 } else if (network_technology == flimflam::kNetworkTechnologyEvdo) {
911 drop_technology = kCellularDropTechnologyEvdo;
912 } else if (network_technology == flimflam::kNetworkTechnologyGprs) {
913 drop_technology = kCellularDropTechnologyGprs;
914 } else if (network_technology == flimflam::kNetworkTechnologyGsm) {
915 drop_technology = kCellularDropTechnologyGsm;
916 } else if (network_technology == flimflam::kNetworkTechnologyHspa) {
917 drop_technology = kCellularDropTechnologyHspa;
918 } else if (network_technology == flimflam::kNetworkTechnologyHspaPlus) {
919 drop_technology = kCellularDropTechnologyHspaPlus;
920 } else if (network_technology == flimflam::kNetworkTechnologyLte) {
921 drop_technology = kCellularDropTechnologyLte;
922 } else if (network_technology == flimflam::kNetworkTechnologyUmts) {
923 drop_technology = kCellularDropTechnologyUmts;
924 }
925 SendEnumToUMA(kMetricCellularDrop,
926 drop_technology,
927 kCellularDropTechnologyMax);
928 SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
929 signal_strength,
930 kMetricCellularSignalStrengthBeforeDropMin,
931 kMetricCellularSignalStrengthBeforeDropMax,
932 kMetricCellularSignalStrengthBeforeDropNumBuckets);
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800933
934 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
935 if (device_metrics == NULL)
936 return;
937 device_metrics->num_drops++;
Thieu Le26fc01b2013-01-28 12:08:48 -0800938}
939
Thieu Leb7aa5f72013-01-31 15:57:48 -0800940void Metrics::NotifyCellularDeviceFailure(const Error &error) {
941 library_->SendUserActionToUMA(
942 kMetricCellularFailureReason + error.message());
943}
944
Thieu Le91fccf62013-04-22 15:23:16 -0700945void Metrics::NotifyCellularOutOfCredits(
946 Metrics::CellularOutOfCreditsReason reason) {
947 SendEnumToUMA(kMetricCellularOutOfCreditsReason,
948 reason,
949 kCellularOutOfCreditsReasonMax);
950}
951
Thieu Le5133b712013-02-19 14:47:21 -0800952void Metrics::NotifyCorruptedProfile() {
953 SendEnumToUMA(kMetricCorruptedProfile,
954 kCorruptedProfile,
955 kCorruptedProfileMax);
956}
957
Thieu Le48e6d6d2011-12-06 00:40:27 +0000958bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
959 return library_->SendEnumToUMA(name, sample, max);
960}
961
Thieu Lea20cbc22012-01-09 22:01:43 +0000962bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
963 int num_buckets) {
964 return library_->SendToUMA(name, sample, min, max, num_buckets);
965}
966
Thieu Le48e6d6d2011-12-06 00:40:27 +0000967void Metrics::InitializeCommonServiceMetrics(const Service *service) {
968 Technology::Identifier technology = service->technology();
969 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
970 technology);
971 AddServiceStateTransitionTimer(
972 service,
973 histogram,
974 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800975 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000976 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
977 AddServiceStateTransitionTimer(
978 service,
979 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800980 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000981 Service::kStatePortal);
982 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
983 AddServiceStateTransitionTimer(
984 service,
985 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800986 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000987 Service::kStateOnline);
988}
989
990void Metrics::UpdateServiceStateTransitionMetrics(
991 ServiceMetrics *service_metrics,
992 Service::ConnectState new_state) {
993 TimerReportersList::iterator it;
994 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
995 for (it = start_timers.begin(); it != start_timers.end(); ++it)
996 (*it)->Start();
997
998 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
999 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
Wade Guthrie091c41c2013-03-22 15:48:53 -07001000 if ((*it)->Stop())
1001 (*it)->ReportMilliseconds();
Thieu Le48e6d6d2011-12-06 00:40:27 +00001002 }
1003}
1004
1005void Metrics::SendServiceFailure(const Service *service) {
1006 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
1007 service->failure(),
1008 kMetricNetworkServiceErrorsMax);
1009}
1010
Thieu Le9abd6742013-01-23 23:35:37 -08001011Metrics::DeviceMetrics *Metrics::GetDeviceMetrics(int interface_index) const {
1012 DeviceMetricsLookupMap::const_iterator it =
1013 devices_metrics_.find(interface_index);
Thieu Lece4483e2013-01-23 15:12:03 -08001014 if (it == devices_metrics_.end()) {
Thieu Le9abd6742013-01-23 23:35:37 -08001015 SLOG(Metrics, 2) << __func__ << ": device " << interface_index
1016 << " not found";
Thieu Lece4483e2013-01-23 15:12:03 -08001017 return NULL;
1018 }
1019 return it->second.get();
1020}
1021
Thieu Le7cf36b02013-01-30 17:15:56 -08001022void Metrics::AutoConnectMetricsReset(DeviceMetrics *device_metrics) {
1023 device_metrics->auto_connect_tries = 0;
1024 device_metrics->auto_connect_timer->Reset();
1025}
1026
Thieu Le6c1e3bb2013-02-06 15:20:35 -08001027void Metrics::HourlyTimeoutHandler() {
1028 SLOG(Metrics, 2) << __func__;
1029 DeviceMetricsLookupMap::iterator it;
1030 for (it = devices_metrics_.begin(); it != devices_metrics_.end(); ++it) {
1031 if (it->second->technology != Technology::kCellular ||
1032 it->second->num_drops == 0)
1033 continue;
1034 SendToUMA(kMetricCellularDropsPerHour,
1035 it->second->num_drops,
1036 kMetricCellularDropsPerHourMin,
1037 kMetricCellularDropsPerHourMax,
1038 kMetricCellularDropsPerHourNumBuckets);
1039 it->second->num_drops = 0;
1040 }
1041 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
1042 kHourlyTimeoutMilliseconds);
1043}
1044
Thieu Le48e6d6d2011-12-06 00:40:27 +00001045void Metrics::set_library(MetricsLibraryInterface *library) {
1046 chromeos_metrics::TimerReporter::set_metrics_lib(library);
1047 library_ = library;
1048}
1049
1050} // namespace shill