blob: 3e420a97f98c03e0cf7c7131728748c99e4cd8d0 [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
Arman Ugurayab22c162012-10-08 19:08:38 -0700136const char Metrics::kMetricTerminationActionTimeOnTerminate[] =
137 "Network.Shill.TerminationActionTime.OnTerminate";
138const char Metrics::kMetricTerminationActionResultOnTerminate[] =
139 "Network.Shill.TerminationActionResult.OnTerminate";
140const char Metrics::kMetricTerminationActionTimeOnSuspend[] =
141 "Network.Shill.TerminationActionTime.OnSuspend";
142const char Metrics::kMetricTerminationActionResultOnSuspend[] =
143 "Network.Shill.TerminationActionResult.OnSuspend";
144const int Metrics::kMetricTerminationActionTimeMillisecondsMax = 10000;
145const int Metrics::kMetricTerminationActionTimeMillisecondsMin = 1;
Arman Uguray6d528f12012-09-13 13:44:55 -0700146
Thieu Le48e6d6d2011-12-06 00:40:27 +0000147// static
Paul Stewart85aea152013-01-22 09:31:56 -0800148const char Metrics::kMetricServiceFixupEntries[] =
149 "Network.Shill.%s.ServiceFixupEntries";
150
151// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000152const uint16 Metrics::kWiFiBandwidth5MHz = 5;
153const uint16 Metrics::kWiFiBandwidth20MHz = 20;
154const uint16 Metrics::kWiFiFrequency2412 = 2412;
155const uint16 Metrics::kWiFiFrequency2472 = 2472;
156const uint16 Metrics::kWiFiFrequency2484 = 2484;
157const uint16 Metrics::kWiFiFrequency5170 = 5170;
158const uint16 Metrics::kWiFiFrequency5180 = 5180;
159const uint16 Metrics::kWiFiFrequency5230 = 5230;
160const uint16 Metrics::kWiFiFrequency5240 = 5240;
161const uint16 Metrics::kWiFiFrequency5320 = 5320;
162const uint16 Metrics::kWiFiFrequency5500 = 5500;
163const uint16 Metrics::kWiFiFrequency5700 = 5700;
164const uint16 Metrics::kWiFiFrequency5745 = 5745;
165const uint16 Metrics::kWiFiFrequency5825 = 5825;
166
Thieu Leb84ba342012-03-02 15:15:19 -0800167// static
168const char Metrics::kMetricPowerManagerKey[] = "metrics";
169
Paul Stewartff845fc2012-08-07 07:28:44 -0700170// static
171const char Metrics::kMetricLinkMonitorFailure[] =
172 "Network.Shill.%s.LinkMonitorFailure";
173const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
174 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewartf1961f82012-09-11 20:45:39 -0700175const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
176const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700177 LinkMonitor::kTestPeriodMilliseconds;
178const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700179const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
180 "Network.Shill.%s.LinkMonitorSecondsToFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700181const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
182const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
Paul Stewart0443aa52012-08-09 10:43:50 -0700183const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
184const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
185 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
186const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
187 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700188const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
189const int Metrics::kMetricLinkMonitorErrorCountMax =
Paul Stewart0443aa52012-08-09 10:43:50 -0700190 LinkMonitor::kFailureThreshold;
191const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
192 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700193
Wade Guthried4977f22012-08-22 12:37:54 -0700194// static
195const char Metrics::kMetricLinkClientDisconnectReason[] =
196 "Network.Shill.WiFi.ClientDisconnectReason";
197const char Metrics::kMetricLinkApDisconnectReason[] =
198 "Network.Shill.WiFi.ApDisconnectReason";
199const char Metrics::kMetricLinkClientDisconnectType[] =
200 "Network.Shill.WiFi.ClientDisconnectType";
201const char Metrics::kMetricLinkApDisconnectType[] =
202 "Network.Shill.WiFi.ApDisconnectType";
203
Thieu Le26fc01b2013-01-28 12:08:48 -0800204// static
205const char Metrics::kMetricCellularDrop[] =
206 "Network.Shill.Cellular.Drop";
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800207const char Metrics::kMetricCellularDropsPerHour[] =
208 "Network.Shill.Cellular.DropsPerHour";
209const int Metrics::kMetricCellularDropsPerHourMax = 60;
210const int Metrics::kMetricCellularDropsPerHourMin = 1;
211const int Metrics::kMetricCellularDropsPerHourNumBuckets = 10;
Thieu Leb7aa5f72013-01-31 15:57:48 -0800212// The format of FailureReason is different to other metrics because this
213// name is prepended to the error message before the entire string is sent
214// via SendUserActionToUMA.
215const char Metrics::kMetricCellularFailureReason[] =
216 "Network.Shill.Cellular.FailureReason: ";
Thieu Le26fc01b2013-01-28 12:08:48 -0800217const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
218 "Network.Shill.Cellular.SignalStrengthBeforeDrop";
219const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
220const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
221const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
Thieu Le7cf36b02013-01-30 17:15:56 -0800222const char Metrics::kMetricCellularAutoConnectTries[] =
223 "Network.Shill.Cellular.AutoConnectTries";
224const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
225const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
226const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
227const char Metrics::kMetricCellularAutoConnectTotalTime[] =
228 "Network.Shill.Cellular.AutoConnectTotalTime";
229const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
230 60 * 1000; // 60 seconds
231const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
232const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
Thieu Le26fc01b2013-01-28 12:08:48 -0800233
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800234// static
Thieu Le5133b712013-02-19 14:47:21 -0800235const char Metrics::kMetricCorruptedProfile[] =
236 "Network.Shill.CorruptedProfile";
237
238// static
Paul Stewart91a43cb2013-03-02 21:34:15 -0800239const char Metrics::kMetricVpnDriver[] =
240 "Network.Shill.Vpn.Driver";
241const int Metrics::kMetricVpnDriverMax = Metrics::kVpnDriverMax;
242const char Metrics::kMetricVpnRemoteAuthenticationType[] =
243 "Network.Shill.Vpn.RemoteAuthenticationType";
244const int Metrics::kMetricVpnRemoteAuthenticationTypeMax =
245 Metrics::kVpnRemoteAuthenticationTypeMax;
246const char Metrics::kMetricVpnUserAuthenticationType[] =
247 "Network.Shill.Vpn.UserAuthenticationType";
248const int Metrics::kMetricVpnUserAuthenticationTypeMax =
249 Metrics::kVpnUserAuthenticationTypeMax;
250
251// static
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800252const int Metrics::kHourlyTimeoutMilliseconds = 3600 * 1000; // One hour
Wade Guthried4977f22012-08-22 12:37:54 -0700253
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800254
255Metrics::Metrics(EventDispatcher *dispatcher)
256 : dispatcher_(dispatcher),
257 library_(&metrics_library_),
Thieu Lea20cbc22012-01-09 22:01:43 +0000258 last_default_technology_(Technology::kUnknown),
259 was_online_(false),
260 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800261 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200262 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
Arman Ugurayab22c162012-10-08 19:08:38 -0700263 time_termination_actions_timer(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200264 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000265 metrics_library_.Init();
266 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
267}
268
269Metrics::~Metrics() {}
270
271// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000272Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
273 WiFiChannel channel = kWiFiChannelUndef;
274 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
275 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
276 channel = static_cast<WiFiChannel>(
277 kWiFiChannel2412 +
278 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
279 } else if (frequency == kWiFiFrequency2484) {
280 channel = kWiFiChannel2484;
281 } else if (kWiFiFrequency5170 <= frequency &&
282 frequency <= kWiFiFrequency5230) {
283 if ((frequency % kWiFiBandwidth20MHz) == 0)
284 channel = static_cast<WiFiChannel>(
285 kWiFiChannel5180 +
286 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
287 if ((frequency % kWiFiBandwidth20MHz) == 10)
288 channel = static_cast<WiFiChannel>(
289 kWiFiChannel5170 +
290 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
291 } else if (kWiFiFrequency5240 <= frequency &&
292 frequency <= kWiFiFrequency5320) {
293 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
294 channel = static_cast<WiFiChannel>(
295 kWiFiChannel5180 +
296 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
297 } else if (kWiFiFrequency5500 <= frequency &&
298 frequency <= kWiFiFrequency5700) {
299 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
300 channel = static_cast<WiFiChannel>(
301 kWiFiChannel5500 +
302 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
303 } else if (kWiFiFrequency5745 <= frequency &&
304 frequency <= kWiFiFrequency5825) {
305 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
306 channel = static_cast<WiFiChannel>(
307 kWiFiChannel5745 +
308 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
309 }
310 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
311
312 if (channel == kWiFiChannelUndef)
313 LOG(WARNING) << "no mapping for frequency " << frequency;
314 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700315 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000316
317 return channel;
318}
319
Thieu Lead1ec2c2012-01-05 23:39:48 +0000320// static
321Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
322 const std::string &security) {
323 if (security == flimflam::kSecurityNone) {
324 return kWiFiSecurityNone;
325 } else if (security == flimflam::kSecurityWep) {
326 return kWiFiSecurityWep;
327 } else if (security == flimflam::kSecurityWpa) {
328 return kWiFiSecurityWpa;
329 } else if (security == flimflam::kSecurityRsn) {
330 return kWiFiSecurityRsn;
331 } else if (security == flimflam::kSecurity8021x) {
332 return kWiFiSecurity8021x;
333 } else if (security == flimflam::kSecurityPsk) {
334 return kWiFiSecurityPsk;
335 } else {
336 return kWiFiSecurityUnknown;
337 }
338}
339
Thieu Le85e050b2012-03-13 15:04:38 -0700340// static
Paul Stewart21f40962013-03-01 14:27:28 -0800341Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
342 const std::string &outer) {
343 if (outer == flimflam::kEapMethodPEAP) {
344 return kEapOuterProtocolPeap;
345 } else if (outer == flimflam::kEapMethodTLS) {
346 return kEapOuterProtocolTls;
347 } else if (outer == flimflam::kEapMethodTTLS) {
348 return kEapOuterProtocolTtls;
349 } else if (outer == flimflam::kEapMethodLEAP) {
350 return kEapOuterProtocolLeap;
351 } else {
352 return kEapOuterProtocolUnknown;
353 }
354}
355
356// static
357Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
358 const std::string &inner) {
359 if (inner.empty()) {
360 return kEapInnerProtocolNone;
361 } else if (inner == flimflam::kEapPhase2AuthPEAPMD5) {
362 return kEapInnerProtocolPeapMd5;
363 } else if (inner == flimflam::kEapPhase2AuthPEAPMSCHAPV2) {
364 return kEapInnerProtocolPeapMschapv2;
365 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMD5) {
366 return kEapInnerProtocolTtlsEapMd5;
367 } else if (inner == flimflam::kEapPhase2AuthTTLSEAPMSCHAPV2) {
368 return kEapInnerProtocolTtlsEapMschapv2;
369 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAPV2) {
370 return kEapInnerProtocolTtlsMschapv2;
371 } else if (inner == flimflam::kEapPhase2AuthTTLSMSCHAP) {
372 return kEapInnerProtocolTtlsMschap;
373 } else if (inner == flimflam::kEapPhase2AuthTTLSPAP) {
374 return kEapInnerProtocolTtlsPap;
375 } else if (inner == flimflam::kEapPhase2AuthTTLSCHAP) {
376 return kEapInnerProtocolTtlsChap;
377 } else {
378 return kEapInnerProtocolUnknown;
379 }
380}
381
382// static
Thieu Le85e050b2012-03-13 15:04:38 -0700383Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
384 const PortalDetector::Result &result) {
385 DCHECK(result.final);
386 PortalResult retval = kPortalResultUnknown;
387 // The only time we should end a successful portal detection is when we're
388 // in the Content phase. If we end with kStatusSuccess in any other phase,
389 // then this indicates that something bad has happened.
390 switch (result.phase) {
391 case PortalDetector::kPhaseDNS:
392 if (result.status == PortalDetector::kStatusFailure)
393 retval = kPortalResultDNSFailure;
394 else if (result.status == PortalDetector::kStatusTimeout)
395 retval = kPortalResultDNSTimeout;
396 else
397 LOG(DFATAL) << __func__ << ": Final result status " << result.status
398 << " is not allowed in the DNS phase";
399 break;
400
401 case PortalDetector::kPhaseConnection:
402 if (result.status == PortalDetector::kStatusFailure)
403 retval = kPortalResultConnectionFailure;
404 else if (result.status == PortalDetector::kStatusTimeout)
405 retval = kPortalResultConnectionTimeout;
406 else
407 LOG(DFATAL) << __func__ << ": Final result status " << result.status
408 << " is not allowed in the Connection phase";
409 break;
410
411 case PortalDetector::kPhaseHTTP:
412 if (result.status == PortalDetector::kStatusFailure)
413 retval = kPortalResultHTTPFailure;
414 else if (result.status == PortalDetector::kStatusTimeout)
415 retval = kPortalResultHTTPTimeout;
416 else
417 LOG(DFATAL) << __func__ << ": Final result status " << result.status
418 << " is not allowed in the HTTP phase";
419 break;
420
421 case PortalDetector::kPhaseContent:
422 if (result.status == PortalDetector::kStatusSuccess)
423 retval = kPortalResultSuccess;
424 else if (result.status == PortalDetector::kStatusFailure)
425 retval = kPortalResultContentFailure;
426 else if (result.status == PortalDetector::kStatusTimeout)
427 retval = kPortalResultContentTimeout;
428 else
429 LOG(DFATAL) << __func__ << ": Final result status " << result.status
430 << " is not allowed in the Content phase";
431 break;
432
433 case PortalDetector::kPhaseUnknown:
434 retval = kPortalResultUnknown;
435 break;
436
437 default:
438 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
439 break;
440 }
441
442 return retval;
443}
444
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800445void Metrics::Start() {
446 SLOG(Metrics, 2) << __func__;
447 hourly_timeout_handler_.Reset(
448 Bind(&Metrics::HourlyTimeoutHandler, Unretained(this)));
449 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
450 kHourlyTimeoutMilliseconds);
451}
452
453void Metrics::Stop() {
454 SLOG(Metrics, 2) << __func__;
455 hourly_timeout_handler_.Cancel();
456}
457
Thieu Le48e6d6d2011-12-06 00:40:27 +0000458void Metrics::RegisterService(const Service *service) {
459 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
460 services_metrics_[service] = service_metrics;
461 service_metrics->service = service;
462 InitializeCommonServiceMetrics(service);
463 service->InitializeCustomMetrics();
464}
465
466void Metrics::DeregisterService(const Service *service) {
467 services_metrics_.erase(service);
468}
469
470void Metrics::AddServiceStateTransitionTimer(
471 const Service *service,
472 const string &histogram_name,
473 Service::ConnectState start_state,
474 Service::ConnectState stop_state) {
475 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
476 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700477 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000478 DCHECK(false);
479 return;
480 }
481 ServiceMetrics *service_metrics = it->second.get();
482 CHECK(start_state < stop_state);
483 chromeos_metrics::TimerReporter *timer =
484 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000485 kTimerHistogramMillisecondsMin,
486 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000487 kTimerHistogramNumBuckets);
488 service_metrics->timers.push_back(timer); // passes ownership.
489 service_metrics->start_on_state[start_state].push_back(timer);
490 service_metrics->stop_on_state[stop_state].push_back(timer);
491}
492
Thieu Lea20cbc22012-01-09 22:01:43 +0000493void Metrics::NotifyDefaultServiceChanged(const Service *service) {
494 base::TimeDelta elapsed_seconds;
495
496 Technology::Identifier technology = (service) ? service->technology() :
497 Technology::kUnknown;
498 if (technology != last_default_technology_) {
499 if (last_default_technology_ != Technology::kUnknown) {
500 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
501 last_default_technology_);
502 time_online_timer_->GetElapsedTime(&elapsed_seconds);
503 SendToUMA(histogram,
504 elapsed_seconds.InSeconds(),
505 kMetricTimeOnlineSecondsMin,
506 kMetricTimeOnlineSecondsMax,
507 kTimerHistogramNumBuckets);
508 }
509 last_default_technology_ = technology;
510 time_online_timer_->Start();
511 }
512
Thieu Lea20cbc22012-01-09 22:01:43 +0000513 // Ignore changes that are not online/offline transitions; e.g.
514 // switching between wired and wireless. TimeToDrop measures
515 // time online regardless of how we are connected.
516 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
517 return;
518
519 if (service == NULL) {
520 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
521 SendToUMA(kMetricTimeToDropSeconds,
522 elapsed_seconds.InSeconds(),
523 kMetricTimeToDropSecondsMin,
524 kMetricTimeToDropSecondsMax,
525 kTimerHistogramNumBuckets);
526 } else {
527 time_to_drop_timer_->Start();
528 }
529
530 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000531}
532
533void Metrics::NotifyServiceStateChanged(const Service *service,
534 Service::ConnectState new_state) {
535 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
536 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700537 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000538 DCHECK(false);
539 return;
540 }
541 ServiceMetrics *service_metrics = it->second.get();
542 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
543
544 if (new_state == Service::kStateFailure)
545 SendServiceFailure(service);
546
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200547 if (collect_bootstats_) {
548 bootstat_log(
549 StringPrintf("network-%s-%s",
550 Technology::NameFromIdentifier(
551 service->technology()).c_str(),
552 service->GetStateString().c_str()).c_str());
553 }
554
Paul Stewart20088d82012-02-16 06:58:55 -0800555 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000556 return;
557
Thieu Leb84ba342012-03-02 15:15:19 -0800558 base::TimeDelta time_resume_to_ready;
559 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
560 time_resume_to_ready_timer_->Reset();
561 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000562}
563
564string Metrics::GetFullMetricName(const char *metric_name,
565 Technology::Identifier technology_id) {
566 string technology = Technology::NameFromIdentifier(technology_id);
567 technology[0] = base::ToUpperASCII(technology[0]);
568 return base::StringPrintf(metric_name, technology.c_str());
569}
570
Thieu Le67370f62012-02-14 23:01:42 +0000571void Metrics::NotifyServiceDisconnect(const Service *service) {
572 Technology::Identifier technology = service->technology();
573 string histogram = GetFullMetricName(kMetricDisconnect, technology);
574 SendToUMA(histogram,
575 service->explicitly_disconnected(),
576 kMetricDisconnectMin,
577 kMetricDisconnectMax,
578 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000579}
580
Thieu Leb84ba342012-03-02 15:15:19 -0800581void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
582 if (new_state == PowerManagerProxyDelegate::kOn) {
583 time_resume_to_ready_timer_->Start();
584 } else {
585 time_resume_to_ready_timer_->Reset();
586 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000587}
588
Arman Ugurayab22c162012-10-08 19:08:38 -0700589void Metrics::NotifyTerminationActionsStarted(
590 TerminationActionReason /*reason*/) {
591 if (time_termination_actions_timer->HasStarted())
592 return;
593 time_termination_actions_timer->Start();
594}
595
596void Metrics::NotifyTerminationActionsCompleted(
597 TerminationActionReason reason, bool success) {
598 if (!time_termination_actions_timer->HasStarted())
599 return;
600
601 int result = success ? kTerminationActionResultSuccess :
602 kTerminationActionResultFailure;
603
604 base::TimeDelta elapsed_time;
605 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
606 time_termination_actions_timer->Reset();
607 string time_metric, result_metric;
608 switch (reason) {
609 case kTerminationActionReasonSuspend:
610 time_metric = kMetricTerminationActionTimeOnSuspend;
611 result_metric = kMetricTerminationActionResultOnSuspend;
612 break;
613 case kTerminationActionReasonTerminate:
614 time_metric = kMetricTerminationActionTimeOnTerminate;
615 result_metric = kMetricTerminationActionResultOnTerminate;
616 break;
617 }
618
619 SendToUMA(time_metric,
620 elapsed_time.InMilliseconds(),
621 kMetricTerminationActionTimeMillisecondsMin,
622 kMetricTerminationActionTimeMillisecondsMax,
623 kTimerHistogramNumBuckets);
624
625 SendEnumToUMA(result_metric,
626 result,
627 kTerminationActionResultMax);
628}
629
Paul Stewartff845fc2012-08-07 07:28:44 -0700630void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700631 Technology::Identifier technology,
632 LinkMonitorFailure failure,
Paul Stewartf1961f82012-09-11 20:45:39 -0700633 int seconds_to_failure,
634 int broadcast_error_count,
635 int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700636 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
637 technology);
638 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700639
640 if (failure == kLinkMonitorFailureThresholdReached) {
641 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
642 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
643 }
644 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
645 technology);
646 SendToUMA(histogram,
647 seconds_to_failure,
648 kMetricLinkMonitorSecondsToFailureMin,
649 kMetricLinkMonitorSecondsToFailureMax,
650 kMetricLinkMonitorSecondsToFailureNumBuckets);
651 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
652 technology);
653 SendToUMA(histogram,
654 broadcast_error_count,
655 kMetricLinkMonitorErrorCountMin,
656 kMetricLinkMonitorErrorCountMax,
657 kMetricLinkMonitorErrorCountNumBuckets);
658 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
659 technology);
660 SendToUMA(histogram,
661 unicast_error_count,
662 kMetricLinkMonitorErrorCountMin,
663 kMetricLinkMonitorErrorCountMax,
664 kMetricLinkMonitorErrorCountNumBuckets);
665 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700666}
667
668void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
669 Technology::Identifier technology,
Paul Stewartf1961f82012-09-11 20:45:39 -0700670 int response_time_milliseconds) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700671 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
672 technology);
673 SendToUMA(histogram,
674 response_time_milliseconds,
675 kMetricLinkMonitorResponseTimeSampleMin,
676 kMetricLinkMonitorResponseTimeSampleMax,
677 kMetricLinkMonitorResponseTimeSampleNumBuckets);
678}
679
Wade Guthried4977f22012-08-22 12:37:54 -0700680void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
681 IEEE_80211::WiFiReasonCode reason) {
682 string metric_disconnect_reason;
683 string metric_disconnect_type;
684 WiFiStatusType type;
685
686 if (by_whom == kDisconnectedByAp) {
687 metric_disconnect_reason = kMetricLinkApDisconnectReason;
688 metric_disconnect_type = kMetricLinkApDisconnectType;
689 type = kStatusCodeTypeByAp;
690 } else {
691 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
692 metric_disconnect_type = kMetricLinkClientDisconnectType;
693 switch(reason) {
694 case IEEE_80211::kReasonCodeSenderHasLeft:
695 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
696 type = kStatusCodeTypeByUser;
697 break;
698
699 case IEEE_80211::kReasonCodeInactivity:
700 type = kStatusCodeTypeConsideredDead;
701 break;
702
703 default:
704 type = kStatusCodeTypeByClient;
705 break;
706 }
707 }
708 SendEnumToUMA(metric_disconnect_reason, reason,
709 IEEE_80211::kStatusCodeMax);
710 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
711}
712
Thieu Lec8078a62013-01-22 18:01:12 -0800713void Metrics::RegisterDevice(int interface_index,
714 Technology::Identifier technology) {
Thieu Le9abd6742013-01-23 23:35:37 -0800715 SLOG(Metrics, 2) << __func__ << ": " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800716 shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
717 devices_metrics_[interface_index] = device_metrics;
Thieu Le9abd6742013-01-23 23:35:37 -0800718 device_metrics->technology = technology;
Thieu Lec8078a62013-01-22 18:01:12 -0800719 string histogram = GetFullMetricName(kMetricTimeToInitializeMilliseconds,
720 technology);
721 device_metrics->initialization_timer.reset(
722 new chromeos_metrics::TimerReporter(
723 histogram,
724 kMetricTimeToInitializeMillisecondsMin,
725 kMetricTimeToInitializeMillisecondsMax,
726 kMetricTimeToInitializeMillisecondsNumBuckets));
727 device_metrics->initialization_timer->Start();
Thieu Lece4483e2013-01-23 15:12:03 -0800728 histogram = GetFullMetricName(kMetricTimeToEnableMilliseconds,
729 technology);
730 device_metrics->enable_timer.reset(
731 new chromeos_metrics::TimerReporter(
732 histogram,
733 kMetricTimeToEnableMillisecondsMin,
734 kMetricTimeToEnableMillisecondsMax,
735 kMetricTimeToEnableMillisecondsNumBuckets));
Thieu Lea2519bf2013-01-23 16:51:54 -0800736 histogram = GetFullMetricName(kMetricTimeToDisableMilliseconds,
737 technology);
738 device_metrics->disable_timer.reset(
739 new chromeos_metrics::TimerReporter(
740 histogram,
741 kMetricTimeToDisableMillisecondsMin,
742 kMetricTimeToDisableMillisecondsMax,
743 kMetricTimeToDisableMillisecondsNumBuckets));
Thieu Le18c11072013-01-28 17:21:37 -0800744 histogram = GetFullMetricName(kMetricTimeToScanMilliseconds,
745 technology);
746 device_metrics->scan_timer.reset(
747 new chromeos_metrics::TimerReporter(
748 histogram,
749 kMetricTimeToScanMillisecondsMin,
750 kMetricTimeToScanMillisecondsMax,
751 kMetricTimeToScanMillisecondsNumBuckets));
Thieu Lecdb5a212013-01-25 11:17:18 -0800752 histogram = GetFullMetricName(kMetricTimeToConnectMilliseconds,
753 technology);
754 device_metrics->connect_timer.reset(
755 new chromeos_metrics::TimerReporter(
756 histogram,
757 kMetricTimeToConnectMillisecondsMin,
758 kMetricTimeToConnectMillisecondsMax,
759 kMetricTimeToConnectMillisecondsNumBuckets));
Thieu Le7cf36b02013-01-30 17:15:56 -0800760 device_metrics->auto_connect_timer.reset(
761 new chromeos_metrics::TimerReporter(
762 kMetricCellularAutoConnectTotalTime,
763 kMetricCellularAutoConnectTotalTimeMin,
764 kMetricCellularAutoConnectTotalTimeMax,
765 kMetricCellularAutoConnectTotalTimeNumBuckets));
Thieu Lec8078a62013-01-22 18:01:12 -0800766}
767
Thieu Le9abd6742013-01-23 23:35:37 -0800768bool Metrics::IsDeviceRegistered(int interface_index,
769 Technology::Identifier technology) {
770 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index
771 << ", technology: " << technology;
772 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
773 if (device_metrics == NULL)
774 return false;
775 // Make sure the device technologies match.
776 return (technology == device_metrics->technology);
777}
778
Thieu Lec8078a62013-01-22 18:01:12 -0800779void Metrics::DeregisterDevice(int interface_index) {
Thieu Le9abd6742013-01-23 23:35:37 -0800780 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800781 devices_metrics_.erase(interface_index);
782}
783
784void Metrics::NotifyDeviceInitialized(int interface_index) {
Thieu Lece4483e2013-01-23 15:12:03 -0800785 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
786 if (device_metrics == NULL)
Thieu Lec8078a62013-01-22 18:01:12 -0800787 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700788 if (!device_metrics->initialization_timer->Stop())
789 return;
Thieu Lec8078a62013-01-22 18:01:12 -0800790 device_metrics->initialization_timer->ReportMilliseconds();
791}
792
Thieu Lece4483e2013-01-23 15:12:03 -0800793void Metrics::NotifyDeviceEnableStarted(int interface_index) {
794 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
795 if (device_metrics == NULL)
796 return;
797 device_metrics->enable_timer->Start();
798}
799
800void Metrics::NotifyDeviceEnableFinished(int interface_index) {
801 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
802 if (device_metrics == NULL)
803 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700804 if (!device_metrics->enable_timer->Stop())
805 return;
Thieu Lece4483e2013-01-23 15:12:03 -0800806 device_metrics->enable_timer->ReportMilliseconds();
807}
808
Thieu Lea2519bf2013-01-23 16:51:54 -0800809void Metrics::NotifyDeviceDisableStarted(int interface_index) {
810 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
811 if (device_metrics == NULL)
812 return;
813 device_metrics->disable_timer->Start();
814}
815
816void Metrics::NotifyDeviceDisableFinished(int interface_index) {
817 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
818 if (device_metrics == NULL)
819 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700820 if (!device_metrics->disable_timer->Stop())
821 return;
Thieu Lea2519bf2013-01-23 16:51:54 -0800822 device_metrics->disable_timer->ReportMilliseconds();
823}
824
Thieu Le18c11072013-01-28 17:21:37 -0800825void Metrics::NotifyDeviceScanStarted(int interface_index) {
826 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
827 if (device_metrics == NULL)
828 return;
829 // This metric is only supported for cellular devices.
830 if (device_metrics->technology != Technology::kCellular)
831 return;
832 device_metrics->scan_timer->Start();
833}
834
835void Metrics::NotifyDeviceScanFinished(int interface_index) {
836 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
837 if (device_metrics == NULL)
838 return;
839 // This metric is only supported for cellular devices.
840 if (device_metrics->technology != Technology::kCellular)
841 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700842 if (!device_metrics->scan_timer->Stop())
843 return;
Thieu Le18c11072013-01-28 17:21:37 -0800844 // Don't send TimeToScan metrics if the elapsed time exceeds the max
845 // metrics value. This usually means that the modem is in an area
846 // without service and we're not interested in this scenario.
847 base::TimeDelta elapsed_time;
848 device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
849 if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
850 device_metrics->scan_timer->ReportMilliseconds();
851}
852
Thieu Le7cf36b02013-01-30 17:15:56 -0800853void Metrics::NotifyDeviceConnectStarted(int interface_index,
854 bool is_auto_connecting) {
Thieu Lecdb5a212013-01-25 11:17:18 -0800855 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
856 if (device_metrics == NULL)
857 return;
858 device_metrics->connect_timer->Start();
Thieu Le7cf36b02013-01-30 17:15:56 -0800859
860 if (is_auto_connecting) {
861 device_metrics->auto_connect_tries++;
862 if (device_metrics->auto_connect_tries == 1)
863 device_metrics->auto_connect_timer->Start();
864 } else {
865 AutoConnectMetricsReset(device_metrics);
866 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800867}
868
869void Metrics::NotifyDeviceConnectFinished(int interface_index) {
870 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
871 if (device_metrics == NULL)
872 return;
Wade Guthrie091c41c2013-03-22 15:48:53 -0700873 if (!device_metrics->connect_timer->Stop())
874 return;
Thieu Lecdb5a212013-01-25 11:17:18 -0800875 device_metrics->connect_timer->ReportMilliseconds();
Thieu Le7cf36b02013-01-30 17:15:56 -0800876
877 if (device_metrics->auto_connect_tries > 0) {
Wade Guthrie091c41c2013-03-22 15:48:53 -0700878 if (!device_metrics->auto_connect_timer->Stop())
879 return;
Thieu Le7cf36b02013-01-30 17:15:56 -0800880 base::TimeDelta elapsed_time;
881 device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
882 if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
883 return;
884 device_metrics->auto_connect_timer->ReportMilliseconds();
885 SendToUMA(kMetricCellularAutoConnectTries,
886 device_metrics->auto_connect_tries,
887 kMetricCellularAutoConnectTriesMin,
888 kMetricCellularAutoConnectTriesMax,
889 kMetricCellularAutoConnectTriesNumBuckets);
890 AutoConnectMetricsReset(device_metrics);
891 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800892}
893
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800894void Metrics::NotifyCellularDeviceDrop(int interface_index,
895 const string &network_technology,
Thieu Le26fc01b2013-01-28 12:08:48 -0800896 uint16 signal_strength) {
897 SLOG(Metrics, 2) << __func__ << ": " << network_technology
898 << ", " << signal_strength;
899 CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
900 if (network_technology == flimflam::kNetworkTechnology1Xrtt) {
901 drop_technology = kCellularDropTechnology1Xrtt;
902 } else if (network_technology == flimflam::kNetworkTechnologyEdge) {
903 drop_technology = kCellularDropTechnologyEdge;
904 } else if (network_technology == flimflam::kNetworkTechnologyEvdo) {
905 drop_technology = kCellularDropTechnologyEvdo;
906 } else if (network_technology == flimflam::kNetworkTechnologyGprs) {
907 drop_technology = kCellularDropTechnologyGprs;
908 } else if (network_technology == flimflam::kNetworkTechnologyGsm) {
909 drop_technology = kCellularDropTechnologyGsm;
910 } else if (network_technology == flimflam::kNetworkTechnologyHspa) {
911 drop_technology = kCellularDropTechnologyHspa;
912 } else if (network_technology == flimflam::kNetworkTechnologyHspaPlus) {
913 drop_technology = kCellularDropTechnologyHspaPlus;
914 } else if (network_technology == flimflam::kNetworkTechnologyLte) {
915 drop_technology = kCellularDropTechnologyLte;
916 } else if (network_technology == flimflam::kNetworkTechnologyUmts) {
917 drop_technology = kCellularDropTechnologyUmts;
918 }
919 SendEnumToUMA(kMetricCellularDrop,
920 drop_technology,
921 kCellularDropTechnologyMax);
922 SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
923 signal_strength,
924 kMetricCellularSignalStrengthBeforeDropMin,
925 kMetricCellularSignalStrengthBeforeDropMax,
926 kMetricCellularSignalStrengthBeforeDropNumBuckets);
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800927
928 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
929 if (device_metrics == NULL)
930 return;
931 device_metrics->num_drops++;
Thieu Le26fc01b2013-01-28 12:08:48 -0800932}
933
Thieu Leb7aa5f72013-01-31 15:57:48 -0800934void Metrics::NotifyCellularDeviceFailure(const Error &error) {
935 library_->SendUserActionToUMA(
936 kMetricCellularFailureReason + error.message());
937}
938
Thieu Le5133b712013-02-19 14:47:21 -0800939void Metrics::NotifyCorruptedProfile() {
940 SendEnumToUMA(kMetricCorruptedProfile,
941 kCorruptedProfile,
942 kCorruptedProfileMax);
943}
944
Thieu Le48e6d6d2011-12-06 00:40:27 +0000945bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
946 return library_->SendEnumToUMA(name, sample, max);
947}
948
Thieu Lea20cbc22012-01-09 22:01:43 +0000949bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
950 int num_buckets) {
951 return library_->SendToUMA(name, sample, min, max, num_buckets);
952}
953
Thieu Le48e6d6d2011-12-06 00:40:27 +0000954void Metrics::InitializeCommonServiceMetrics(const Service *service) {
955 Technology::Identifier technology = service->technology();
956 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
957 technology);
958 AddServiceStateTransitionTimer(
959 service,
960 histogram,
961 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800962 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000963 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
964 AddServiceStateTransitionTimer(
965 service,
966 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800967 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000968 Service::kStatePortal);
969 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
970 AddServiceStateTransitionTimer(
971 service,
972 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800973 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000974 Service::kStateOnline);
975}
976
977void Metrics::UpdateServiceStateTransitionMetrics(
978 ServiceMetrics *service_metrics,
979 Service::ConnectState new_state) {
980 TimerReportersList::iterator it;
981 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
982 for (it = start_timers.begin(); it != start_timers.end(); ++it)
983 (*it)->Start();
984
985 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
986 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
Wade Guthrie091c41c2013-03-22 15:48:53 -0700987 if ((*it)->Stop())
988 (*it)->ReportMilliseconds();
Thieu Le48e6d6d2011-12-06 00:40:27 +0000989 }
990}
991
992void Metrics::SendServiceFailure(const Service *service) {
993 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
994 service->failure(),
995 kMetricNetworkServiceErrorsMax);
996}
997
Thieu Le9abd6742013-01-23 23:35:37 -0800998Metrics::DeviceMetrics *Metrics::GetDeviceMetrics(int interface_index) const {
999 DeviceMetricsLookupMap::const_iterator it =
1000 devices_metrics_.find(interface_index);
Thieu Lece4483e2013-01-23 15:12:03 -08001001 if (it == devices_metrics_.end()) {
Thieu Le9abd6742013-01-23 23:35:37 -08001002 SLOG(Metrics, 2) << __func__ << ": device " << interface_index
1003 << " not found";
Thieu Lece4483e2013-01-23 15:12:03 -08001004 return NULL;
1005 }
1006 return it->second.get();
1007}
1008
Thieu Le7cf36b02013-01-30 17:15:56 -08001009void Metrics::AutoConnectMetricsReset(DeviceMetrics *device_metrics) {
1010 device_metrics->auto_connect_tries = 0;
1011 device_metrics->auto_connect_timer->Reset();
1012}
1013
Thieu Le6c1e3bb2013-02-06 15:20:35 -08001014void Metrics::HourlyTimeoutHandler() {
1015 SLOG(Metrics, 2) << __func__;
1016 DeviceMetricsLookupMap::iterator it;
1017 for (it = devices_metrics_.begin(); it != devices_metrics_.end(); ++it) {
1018 if (it->second->technology != Technology::kCellular ||
1019 it->second->num_drops == 0)
1020 continue;
1021 SendToUMA(kMetricCellularDropsPerHour,
1022 it->second->num_drops,
1023 kMetricCellularDropsPerHourMin,
1024 kMetricCellularDropsPerHourMax,
1025 kMetricCellularDropsPerHourNumBuckets);
1026 it->second->num_drops = 0;
1027 }
1028 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
1029 kHourlyTimeoutMilliseconds);
1030}
1031
Thieu Le48e6d6d2011-12-06 00:40:27 +00001032void Metrics::set_library(MetricsLibraryInterface *library) {
1033 chromeos_metrics::TimerReporter::set_metrics_lib(library);
1034 library_ = library;
1035}
1036
1037} // namespace shill