1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/metrics.h"
18
19 #include <base/strings/string_util.h>
20 #include <base/strings/stringprintf.h>
21 #if defined(__ANDROID__)
22 #include <dbus/service_constants.h>
23 #else
24 #include <chromeos/dbus/service_constants.h>
25 #endif // __ANDROID__
26 #if !defined(__ANDROID__)
27 #include <metrics/bootstat.h>
28 #endif // __ANDROID__
29
30 #include "shill/connection_diagnostics.h"
31 #include "shill/link_monitor.h"
32 #include "shill/logging.h"
33
34 using std::string;
35 using std::shared_ptr;
36
37 namespace shill {
38
39 namespace Logging {
40 static auto kModuleLogScope = ScopeLogger::kMetrics;
ObjectID(const Metrics * m)41 static string ObjectID(const Metrics* m) { return "(metrics)"; }
42 }
43
44 static const char kMetricPrefix[] = "Network.Shill";
45
46 // static
47 // Our disconnect enumeration values are 0 (System Disconnect) and
48 // 1 (User Disconnect), see histograms.xml, but Chrome needs a minimum
49 // enum value of 1 and the minimum number of buckets needs to be 3 (see
50 // histogram.h). Instead of remapping System Disconnect to 1 and
51 // User Disconnect to 2, we can just leave the enumerated values as-is
52 // because Chrome implicitly creates a [0-1) bucket for us. Using Min=1,
53 // Max=2 and NumBuckets=3 gives us the following three buckets:
54 // [0-1), [1-2), [2-INT_MAX). We end up with an extra bucket [2-INT_MAX)
55 // that we can safely ignore.
56 const char Metrics::kMetricDisconnectSuffix[] = "Disconnect";
57 const int Metrics::kMetricDisconnectMax = 2;
58 const int Metrics::kMetricDisconnectMin = 1;
59 const int Metrics::kMetricDisconnectNumBuckets = 3;
60
61 const char Metrics::kMetricSignalAtDisconnectSuffix[] = "SignalAtDisconnect";
62 const int Metrics::kMetricSignalAtDisconnectMin = 0;
63 const int Metrics::kMetricSignalAtDisconnectMax = 200;
64 const int Metrics::kMetricSignalAtDisconnectNumBuckets = 40;
65
66 const char Metrics::kMetricNetworkApModeSuffix[] = "ApMode";
67 const char Metrics::kMetricNetworkChannelSuffix[] = "Channel";
68 const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
69 const char Metrics::kMetricNetworkEapInnerProtocolSuffix[] = "EapInnerProtocol";
70 const int Metrics::kMetricNetworkEapInnerProtocolMax =
71 Metrics::kEapInnerProtocolMax;
72 const char Metrics::kMetricNetworkEapOuterProtocolSuffix[] = "EapOuterProtocol";
73 const int Metrics::kMetricNetworkEapOuterProtocolMax =
74 Metrics::kEapOuterProtocolMax;
75 const char Metrics::kMetricNetworkPhyModeSuffix[] = "PhyMode";
76 const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
77 const char Metrics::kMetricNetworkSecuritySuffix[] = "Security";
78 const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
79 const char Metrics::kMetricNetworkServiceErrors[] =
80 "Network.Shill.ServiceErrors";
81 const char Metrics::kMetricNetworkSignalStrengthSuffix[] = "SignalStrength";
82 const int Metrics::kMetricNetworkSignalStrengthMax = 200;
83 const int Metrics::kMetricNetworkSignalStrengthMin = 0;
84 const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
85
86 constexpr char
87 Metrics::kMetricRememberedSystemWiFiNetworkCountBySecurityModeFormat[];
88 constexpr char
89 Metrics::kMetricRememberedUserWiFiNetworkCountBySecurityModeFormat[];
90
91 const char Metrics::kMetricRememberedWiFiNetworkCount[] =
92 "Network.Shill.WiFi.RememberedNetworkCount";
93 const int Metrics::kMetricRememberedWiFiNetworkCountMax = 1024;
94 const int Metrics::kMetricRememberedWiFiNetworkCountMin = 0;
95 const int Metrics::kMetricRememberedWiFiNetworkCountNumBuckets = 32;
96
97 const char Metrics::kMetricTimeOnlineSecondsSuffix[] = "TimeOnline";
98 const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
99 const int Metrics::kMetricTimeOnlineSecondsMin = 1;
100
101 const char Metrics::kMetricTimeToConnectMillisecondsSuffix[] = "TimeToConnect";
102 const int Metrics::kMetricTimeToConnectMillisecondsMax =
103 60 * 1000; // 60 seconds
104 const int Metrics::kMetricTimeToConnectMillisecondsMin = 1;
105 const int Metrics::kMetricTimeToConnectMillisecondsNumBuckets = 60;
106
107 const char Metrics::kMetricTimeToScanAndConnectMillisecondsSuffix[] =
108 "TimeToScanAndConnect";
109
110 const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
111 const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
112 const int Metrics::kMetricTimeToDropSecondsMin = 1;
113
114 const char Metrics::kMetricTimeToDisableMillisecondsSuffix[] = "TimeToDisable";
115 const int Metrics::kMetricTimeToDisableMillisecondsMax =
116 60 * 1000; // 60 seconds
117 const int Metrics::kMetricTimeToDisableMillisecondsMin = 1;
118 const int Metrics::kMetricTimeToDisableMillisecondsNumBuckets = 60;
119
120 const char Metrics::kMetricTimeToEnableMillisecondsSuffix[] = "TimeToEnable";
121 const int Metrics::kMetricTimeToEnableMillisecondsMax =
122 60 * 1000; // 60 seconds
123 const int Metrics::kMetricTimeToEnableMillisecondsMin = 1;
124 const int Metrics::kMetricTimeToEnableMillisecondsNumBuckets = 60;
125
126 const char Metrics::kMetricTimeToInitializeMillisecondsSuffix[] =
127 "TimeToInitialize";
128 const int Metrics::kMetricTimeToInitializeMillisecondsMax =
129 30 * 1000; // 30 seconds
130 const int Metrics::kMetricTimeToInitializeMillisecondsMin = 1;
131 const int Metrics::kMetricTimeToInitializeMillisecondsNumBuckets = 30;
132
133 const char Metrics::kMetricTimeResumeToReadyMillisecondsSuffix[] =
134 "TimeResumeToReady";
135 const char Metrics::kMetricTimeToConfigMillisecondsSuffix[] = "TimeToConfig";
136 const char Metrics::kMetricTimeToJoinMillisecondsSuffix[] = "TimeToJoin";
137 const char Metrics::kMetricTimeToOnlineMillisecondsSuffix[] = "TimeToOnline";
138 const char Metrics::kMetricTimeToPortalMillisecondsSuffix[] = "TimeToPortal";
139
140 const char Metrics::kMetricTimeToScanMillisecondsSuffix[] = "TimeToScan";
141 const int Metrics::kMetricTimeToScanMillisecondsMax = 180 * 1000; // 3 minutes
142 const int Metrics::kMetricTimeToScanMillisecondsMin = 1;
143 const int Metrics::kMetricTimeToScanMillisecondsNumBuckets = 90;
144
145 const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
146 const int Metrics::kTimerHistogramMillisecondsMin = 1;
147 const int Metrics::kTimerHistogramNumBuckets = 50;
148
149 const char Metrics::kMetricPortalAttemptsSuffix[] = "PortalAttempts";
150 const int Metrics::kMetricPortalAttemptsMax =
151 PortalDetector::kMaxRequestAttempts;
152 const int Metrics::kMetricPortalAttemptsMin = 1;
153 const int Metrics::kMetricPortalAttemptsNumBuckets =
154 Metrics::kMetricPortalAttemptsMax;
155
156 const char Metrics::kMetricPortalAttemptsToOnlineSuffix[] =
157 "PortalAttemptsToOnline";
158 const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
159 const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
160 const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
161
162 const char Metrics::kMetricPortalResultSuffix[] = "PortalResult";
163
164 const char Metrics::kMetricFrequenciesConnectedEver[] =
165 "Network.Shill.WiFi.FrequenciesConnectedEver";
166 const int Metrics::kMetricFrequenciesConnectedMax = 50;
167 const int Metrics::kMetricFrequenciesConnectedMin = 1;
168 const int Metrics::kMetricFrequenciesConnectedNumBuckets = 50;
169
170 const char Metrics::kMetricScanResult[] =
171 "Network.Shill.WiFi.ScanResult";
172 const char Metrics::kMetricWiFiScanTimeInEbusyMilliseconds[] =
173 "Network.Shill.WiFi.ScanTimeInEbusy";
174
175 const char Metrics::kMetricTerminationActionTimeTaken[] =
176 "Network.Shill.TerminationActionTimeTaken";
177 const char Metrics::kMetricTerminationActionResult[] =
178 "Network.Shill.TerminationActionResult";
179 const int Metrics::kMetricTerminationActionTimeTakenMillisecondsMax = 20000;
180 const int Metrics::kMetricTerminationActionTimeTakenMillisecondsMin = 1;
181
182 const char Metrics::kMetricSuspendActionTimeTaken[] =
183 "Network.Shill.SuspendActionTimeTaken";
184 const char Metrics::kMetricSuspendActionResult[] =
185 "Network.Shill.SuspendActionResult";
186 const int Metrics::kMetricSuspendActionTimeTakenMillisecondsMax = 20000;
187 const int Metrics::kMetricSuspendActionTimeTakenMillisecondsMin = 1;
188
189 const char Metrics::kMetricDarkResumeActionTimeTaken[] =
190 "Network.Shill.DarkResumeActionTimeTaken";
191 const char Metrics::kMetricDarkResumeActionResult[] =
192 "Network.Shill.DarkResumeActionResult";
193 const int Metrics::kMetricDarkResumeActionTimeTakenMillisecondsMax = 20000;
194 const int Metrics::kMetricDarkResumeActionTimeTakenMillisecondsMin = 1;
195 const char Metrics::kMetricDarkResumeUnmatchedScanResultReceived[] =
196 "Network.Shill.WiFi.DarkResumeUnmatchedScanResultsReceived";
197
198 const char Metrics::kMetricWakeOnWiFiFeaturesEnabledState[] =
199 "Network.Shill.WiFi.WakeOnWiFiFeaturesEnabledState";
200 const char Metrics::kMetricVerifyWakeOnWiFiSettingsResult[] =
201 "Network.Shill.WiFi.VerifyWakeOnWiFiSettingsResult";
202 const char Metrics::kMetricWiFiConnectionStatusAfterWake[] =
203 "Network.Shill.WiFi.WiFiConnectionStatusAfterWake";
204 const char Metrics::kMetricWakeOnWiFiThrottled[] =
205 "Network.Shill.WiFi.WakeOnWiFiThrottled";
206 const char Metrics::kMetricWakeReasonReceivedBeforeOnDarkResume[] =
207 "Network.Shill.WiFi.WakeReasonReceivedBeforeOnDarkResume";
208 const char Metrics::kMetricDarkResumeWakeReason[] =
209 "Network.Shill.WiFi.DarkResumeWakeReason";
210 const char Metrics::kMetricDarkResumeScanType[] =
211 "Network.Shill.WiFi.DarkResumeScanType";
212 const char Metrics::kMetricDarkResumeScanRetryResult[] =
213 "Network.Shill.WiFi.DarkResumeScanRetryResult";
214 const char Metrics::kMetricDarkResumeScanNumRetries[] =
215 "Network.Shill.WiFi.DarkResumeScanNumRetries";
216 const int Metrics::kMetricDarkResumeScanNumRetriesMax = 20;
217 const int Metrics::kMetricDarkResumeScanNumRetriesMin = 0;
218
219 // static
220 const char Metrics::kMetricServiceFixupEntriesSuffix[] = "ServiceFixupEntries";
221
222 // static
223 const uint16_t Metrics::kWiFiBandwidth5MHz = 5;
224 const uint16_t Metrics::kWiFiBandwidth20MHz = 20;
225 const uint16_t Metrics::kWiFiFrequency2412 = 2412;
226 const uint16_t Metrics::kWiFiFrequency2472 = 2472;
227 const uint16_t Metrics::kWiFiFrequency2484 = 2484;
228 const uint16_t Metrics::kWiFiFrequency5170 = 5170;
229 const uint16_t Metrics::kWiFiFrequency5180 = 5180;
230 const uint16_t Metrics::kWiFiFrequency5230 = 5230;
231 const uint16_t Metrics::kWiFiFrequency5240 = 5240;
232 const uint16_t Metrics::kWiFiFrequency5320 = 5320;
233 const uint16_t Metrics::kWiFiFrequency5500 = 5500;
234 const uint16_t Metrics::kWiFiFrequency5700 = 5700;
235 const uint16_t Metrics::kWiFiFrequency5745 = 5745;
236 const uint16_t Metrics::kWiFiFrequency5825 = 5825;
237
238 // static
239 const char Metrics::kMetricPowerManagerKey[] = "metrics";
240
241 // static
242 const char Metrics::kMetricLinkMonitorFailureSuffix[] = "LinkMonitorFailure";
243 const char Metrics::kMetricLinkMonitorResponseTimeSampleSuffix[] =
244 "LinkMonitorResponseTimeSample";
245 const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
246 const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
247 LinkMonitor::kDefaultTestPeriodMilliseconds;
248 const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
249 const char Metrics::kMetricLinkMonitorSecondsToFailureSuffix[] =
250 "LinkMonitorSecondsToFailure";
251 const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
252 const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
253 const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
254 const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailureSuffix[] =
255 "LinkMonitorBroadcastErrorsAtFailure";
256 const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailureSuffix[] =
257 "LinkMonitorUnicastErrorsAtFailure";
258 const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
259 const int Metrics::kMetricLinkMonitorErrorCountMax =
260 LinkMonitor::kFailureThreshold;
261 const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
262 LinkMonitor::kFailureThreshold + 1;
263
264 // static
265 const char Metrics::kMetricLinkClientDisconnectReason[] =
266 "Network.Shill.WiFi.ClientDisconnectReason";
267 const char Metrics::kMetricLinkApDisconnectReason[] =
268 "Network.Shill.WiFi.ApDisconnectReason";
269 const char Metrics::kMetricLinkClientDisconnectType[] =
270 "Network.Shill.WiFi.ClientDisconnectType";
271 const char Metrics::kMetricLinkApDisconnectType[] =
272 "Network.Shill.WiFi.ApDisconnectType";
273
274 // static
275 const char Metrics::kMetricCellular3GPPRegistrationDelayedDrop[] =
276 "Network.Shill.Cellular.3GPPRegistrationDelayedDrop";
277 const char Metrics::kMetricCellularAutoConnectTries[] =
278 "Network.Shill.Cellular.AutoConnectTries";
279 const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
280 const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
281 const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
282 const char Metrics::kMetricCellularAutoConnectTotalTime[] =
283 "Network.Shill.Cellular.AutoConnectTotalTime";
284 const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
285 60 * 1000; // 60 seconds
286 const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
287 const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
288 const char Metrics::kMetricCellularDrop[] =
289 "Network.Shill.Cellular.Drop";
290
291 // static
292 const char Metrics::kMetricCellularFailure[] =
293 "Network.Shill.Cellular.Failure";
294 const int Metrics::kMetricCellularConnectionFailure = 0;
295 const int Metrics::kMetricCellularDisconnectionFailure = 1;
296 const int Metrics::kMetricCellularMaxFailure =
297 kMetricCellularDisconnectionFailure + 1;
298
299 const char Metrics::kMetricCellularOutOfCreditsReason[] =
300 "Network.Shill.Cellular.OutOfCreditsReason";
301 const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
302 "Network.Shill.Cellular.SignalStrengthBeforeDrop";
303 const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
304 const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
305 const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
306
307 // static
308 const char Metrics::kMetricCorruptedProfile[] =
309 "Network.Shill.CorruptedProfile";
310
311 // static
312 const char Metrics::kMetricVpnDriver[] =
313 "Network.Shill.Vpn.Driver";
314 const int Metrics::kMetricVpnDriverMax = Metrics::kVpnDriverMax;
315 const char Metrics::kMetricVpnRemoteAuthenticationType[] =
316 "Network.Shill.Vpn.RemoteAuthenticationType";
317 const int Metrics::kMetricVpnRemoteAuthenticationTypeMax =
318 Metrics::kVpnRemoteAuthenticationTypeMax;
319 const char Metrics::kMetricVpnUserAuthenticationType[] =
320 "Network.Shill.Vpn.UserAuthenticationType";
321 const int Metrics::kMetricVpnUserAuthenticationTypeMax =
322 Metrics::kVpnUserAuthenticationTypeMax;
323
324 const char Metrics::kMetricExpiredLeaseLengthSecondsSuffix[] =
325 "ExpiredLeaseLengthSeconds";
326 const int Metrics::kMetricExpiredLeaseLengthSecondsMax =
327 7 * 24 * 60 * 60; // 7 days
328 const int Metrics::kMetricExpiredLeaseLengthSecondsMin = 1;
329 const int Metrics::kMetricExpiredLeaseLengthSecondsNumBuckets =
330 Metrics::kMetricExpiredLeaseLengthSecondsMax;
331
332 // static
333 const char Metrics::kMetricWifiAutoConnectableServices[] =
334 "Network.Shill.WiFi.AutoConnectableServices";
335 const int Metrics::kMetricWifiAutoConnectableServicesMax = 50;
336 const int Metrics::kMetricWifiAutoConnectableServicesMin = 1;
337 const int Metrics::kMetricWifiAutoConnectableServicesNumBuckets = 10;
338
339 // static
340 const char Metrics::kMetricWifiAvailableBSSes[] =
341 "Network.Shill.WiFi.AvailableBSSesAtConnect";
342 const int Metrics::kMetricWifiAvailableBSSesMax = 50;
343 const int Metrics::kMetricWifiAvailableBSSesMin = 1;
344 const int Metrics::kMetricWifiAvailableBSSesNumBuckets = 10;
345
346 // static
347 const char Metrics::kMetricWifiStoppedTxQueueReason[] =
348 "Network.Shill.WiFi.StoppedTxQueueReason";
349 // Values are defined in mac80211_monitor.h.
350
351 // static
352 const char Metrics::kMetricWifiStoppedTxQueueLength[] =
353 "Network.Shill.WiFi.StoppedTxQueueLength";
354 const int Metrics::kMetricWifiStoppedTxQueueLengthMax = 10000;
355 const int Metrics::kMetricWifiStoppedTxQueueLengthMin = 1;
356 const int Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets = 50;
357
358 // Number of services associated with currently connected network.
359 const char Metrics::kMetricServicesOnSameNetwork[] =
360 "Network.Shill.ServicesOnSameNetwork";
361 const int Metrics::kMetricServicesOnSameNetworkMax = 20;
362 const int Metrics::kMetricServicesOnSameNetworkMin = 1;
363 const int Metrics::kMetricServicesOnSameNetworkNumBuckets = 10;
364
365 // static
366 const char Metrics::kMetricUserInitiatedEvents[] =
367 "Network.Shill.UserInitiatedEvents";
368
369 // static
370 const char Metrics::kMetricWifiTxBitrate[] =
371 "Network.Shill.WiFi.TransmitBitrateMbps";
372 const int Metrics::kMetricWifiTxBitrateMax = 7000;
373 const int Metrics::kMetricWifiTxBitrateMin = 1;
374 const int Metrics::kMetricWifiTxBitrateNumBuckets = 100;
375
376 // static
377 const char Metrics::kMetricWifiUserInitiatedConnectionResult[] =
378 "Network.Shill.WiFi.UserInitiatedConnectionResult";
379
380 // static
381 const char Metrics::kMetricWifiUserInitiatedConnectionFailureReason[] =
382 "Network.Shill.WiFi.UserInitiatedConnectionFailureReason";
383
384 // static
385 const char Metrics::kMetricFallbackDNSTestResultSuffix[] =
386 "FallbackDNSTestResult";
387
388 // static
389 const char Metrics::kMetricNetworkProblemDetectedSuffix[] =
390 "NetworkProblemDetected";
391
392 // static
393 const char Metrics::kMetricDeviceConnectionStatus[] =
394 "Network.Shill.DeviceConnectionStatus";
395
396 // static
397 const char Metrics::kMetricDhcpClientStatus[] =
398 "Network.Shill.DHCPClientStatus";
399
400 // static
401 const char Metrics::kMetricDhcpClientMTUValue[] =
402 "Network.Shill.DHCPClientMTUValue";
403 const char Metrics::kMetricPPPMTUValue[] = "Network.Shill.PPPMTUValue";
404
405 // static
406 const char Metrics::kMetricNetworkConnectionIPTypeSuffix[] =
407 "NetworkConnectionIPType";
408
409 // static
410 const char Metrics::kMetricIPv6ConnectivityStatusSuffix[] =
411 "IPv6ConnectivityStatus";
412
413 // static
414 const char Metrics::kMetricDevicePresenceStatusSuffix[] =
415 "DevicePresenceStatus";
416
417 // static
418 const char Metrics::kMetricDeviceRemovedEvent[] =
419 "Network.Shill.DeviceRemovedEvent";
420
421 // static
422 const char Metrics::kMetricConnectionDiagnosticsIssue[] =
423 "Network.Shill.ConnectionDiagnosticsIssue";
424
425 // static
426 const char Metrics::kMetricUnreliableLinkSignalStrengthSuffix[] =
427 "UnreliableLinkSignalStrength";
428 const int Metrics::kMetricSerivceSignalStrengthMin = 0;
429 const int Metrics::kMetricServiceSignalStrengthMax = 100;
430 const int Metrics::kMetricServiceSignalStrengthNumBuckets = 40;
431
Metrics(EventDispatcher * dispatcher)432 Metrics::Metrics(EventDispatcher* dispatcher)
433 : dispatcher_(dispatcher),
434 library_(&metrics_library_),
435 last_default_technology_(Technology::kUnknown),
436 was_online_(false),
437 time_online_timer_(new chromeos_metrics::Timer),
438 time_to_drop_timer_(new chromeos_metrics::Timer),
439 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
440 time_termination_actions_timer(new chromeos_metrics::Timer),
441 time_suspend_actions_timer(new chromeos_metrics::Timer),
442 time_dark_resume_actions_timer(new chromeos_metrics::Timer),
443 collect_bootstats_(true),
444 num_scan_results_expected_in_dark_resume_(0),
445 wake_on_wifi_throttled_(false),
446 wake_reason_received_(false),
447 dark_resume_scan_retries_(0) {
448 metrics_library_.Init();
449 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
450 }
451
~Metrics()452 Metrics::~Metrics() {}
453
454 // static
WiFiFrequencyToChannel(uint16_t frequency)455 Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16_t frequency) {
456 WiFiChannel channel = kWiFiChannelUndef;
457 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
458 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
459 channel = static_cast<WiFiChannel>(
460 kWiFiChannel2412 +
461 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
462 } else if (frequency == kWiFiFrequency2484) {
463 channel = kWiFiChannel2484;
464 } else if (kWiFiFrequency5170 <= frequency &&
465 frequency <= kWiFiFrequency5230) {
466 if ((frequency % kWiFiBandwidth20MHz) == 0)
467 channel = static_cast<WiFiChannel>(
468 kWiFiChannel5180 +
469 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
470 if ((frequency % kWiFiBandwidth20MHz) == 10)
471 channel = static_cast<WiFiChannel>(
472 kWiFiChannel5170 +
473 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
474 } else if (kWiFiFrequency5240 <= frequency &&
475 frequency <= kWiFiFrequency5320) {
476 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
477 channel = static_cast<WiFiChannel>(
478 kWiFiChannel5180 +
479 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
480 } else if (kWiFiFrequency5500 <= frequency &&
481 frequency <= kWiFiFrequency5700) {
482 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
483 channel = static_cast<WiFiChannel>(
484 kWiFiChannel5500 +
485 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
486 } else if (kWiFiFrequency5745 <= frequency &&
487 frequency <= kWiFiFrequency5825) {
488 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
489 channel = static_cast<WiFiChannel>(
490 kWiFiChannel5745 +
491 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
492 }
493 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
494
495 if (channel == kWiFiChannelUndef)
496 LOG(WARNING) << "no mapping for frequency " << frequency;
497 else
498 SLOG(nullptr, 3) << "mapped frequency " << frequency
499 << " to enum bucket " << channel;
500
501 return channel;
502 }
503
504 // static
WiFiSecurityStringToEnum(const string & security)505 Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
506 const string& security) {
507 if (security == kSecurityNone) {
508 return kWiFiSecurityNone;
509 } else if (security == kSecurityWep) {
510 return kWiFiSecurityWep;
511 } else if (security == kSecurityWpa) {
512 return kWiFiSecurityWpa;
513 } else if (security == kSecurityRsn) {
514 return kWiFiSecurityRsn;
515 } else if (security == kSecurity8021x) {
516 return kWiFiSecurity8021x;
517 } else if (security == kSecurityPsk) {
518 return kWiFiSecurityPsk;
519 } else {
520 return kWiFiSecurityUnknown;
521 }
522 }
523
524 // static
WiFiApModeStringToEnum(const string & ap_mode)525 Metrics::WiFiApMode Metrics::WiFiApModeStringToEnum(const string& ap_mode) {
526 if (ap_mode == kModeManaged) {
527 return kWiFiApModeManaged;
528 } else if (ap_mode == kModeAdhoc) {
529 return kWiFiApModeAdHoc;
530 } else {
531 return kWiFiApModeUnknown;
532 }
533 }
534
535 // static
EapOuterProtocolStringToEnum(const string & outer)536 Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
537 const string& outer) {
538 if (outer == kEapMethodPEAP) {
539 return kEapOuterProtocolPeap;
540 } else if (outer == kEapMethodTLS) {
541 return kEapOuterProtocolTls;
542 } else if (outer == kEapMethodTTLS) {
543 return kEapOuterProtocolTtls;
544 } else if (outer == kEapMethodLEAP) {
545 return kEapOuterProtocolLeap;
546 } else {
547 return kEapOuterProtocolUnknown;
548 }
549 }
550
551 // static
EapInnerProtocolStringToEnum(const string & inner)552 Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
553 const string& inner) {
554 if (inner.empty()) {
555 return kEapInnerProtocolNone;
556 } else if (inner == kEapPhase2AuthPEAPMD5) {
557 return kEapInnerProtocolPeapMd5;
558 } else if (inner == kEapPhase2AuthPEAPMSCHAPV2) {
559 return kEapInnerProtocolPeapMschapv2;
560 } else if (inner == kEapPhase2AuthTTLSEAPMD5) {
561 return kEapInnerProtocolTtlsEapMd5;
562 } else if (inner == kEapPhase2AuthTTLSEAPMSCHAPV2) {
563 return kEapInnerProtocolTtlsEapMschapv2;
564 } else if (inner == kEapPhase2AuthTTLSMSCHAPV2) {
565 return kEapInnerProtocolTtlsMschapv2;
566 } else if (inner == kEapPhase2AuthTTLSMSCHAP) {
567 return kEapInnerProtocolTtlsMschap;
568 } else if (inner == kEapPhase2AuthTTLSPAP) {
569 return kEapInnerProtocolTtlsPap;
570 } else if (inner == kEapPhase2AuthTTLSCHAP) {
571 return kEapInnerProtocolTtlsChap;
572 } else {
573 return kEapInnerProtocolUnknown;
574 }
575 }
576
577 // static
PortalDetectionResultToEnum(const PortalDetector::Result & portal_result)578 Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
579 const PortalDetector::Result& portal_result) {
580 DCHECK(portal_result.final);
581 PortalResult retval = kPortalResultUnknown;
582 ConnectivityTrial::Result result = portal_result.trial_result;
583 // The only time we should end a successful portal detection is when we're
584 // in the Content phase. If we end with kStatusSuccess in any other phase,
585 // then this indicates that something bad has happened.
586 switch (result.phase) {
587 case ConnectivityTrial::kPhaseDNS:
588 if (result.status == ConnectivityTrial::kStatusFailure)
589 retval = kPortalResultDNSFailure;
590 else if (result.status == ConnectivityTrial::kStatusTimeout)
591 retval = kPortalResultDNSTimeout;
592 else
593 LOG(DFATAL) << __func__ << ": Final result status " << result.status
594 << " is not allowed in the DNS phase";
595 break;
596
597 case ConnectivityTrial::kPhaseConnection:
598 if (result.status == ConnectivityTrial::kStatusFailure)
599 retval = kPortalResultConnectionFailure;
600 else if (result.status == ConnectivityTrial::kStatusTimeout)
601 retval = kPortalResultConnectionTimeout;
602 else
603 LOG(DFATAL) << __func__ << ": Final result status " << result.status
604 << " is not allowed in the Connection phase";
605 break;
606
607 case ConnectivityTrial::kPhaseHTTP:
608 if (result.status == ConnectivityTrial::kStatusFailure)
609 retval = kPortalResultHTTPFailure;
610 else if (result.status == ConnectivityTrial::kStatusTimeout)
611 retval = kPortalResultHTTPTimeout;
612 else
613 LOG(DFATAL) << __func__ << ": Final result status " << result.status
614 << " is not allowed in the HTTP phase";
615 break;
616
617 case ConnectivityTrial::kPhaseContent:
618 if (result.status == ConnectivityTrial::kStatusSuccess)
619 retval = kPortalResultSuccess;
620 else if (result.status == ConnectivityTrial::kStatusFailure)
621 retval = kPortalResultContentFailure;
622 else if (result.status == ConnectivityTrial::kStatusTimeout)
623 retval = kPortalResultContentTimeout;
624 else
625 LOG(DFATAL) << __func__ << ": Final result status " << result.status
626 << " is not allowed in the Content phase";
627 break;
628
629 case ConnectivityTrial::kPhaseUnknown:
630 retval = kPortalResultUnknown;
631 break;
632
633 default:
634 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
635 break;
636 }
637
638 return retval;
639 }
640
Start()641 void Metrics::Start() {
642 SLOG(this, 2) << __func__;
643 }
644
Stop()645 void Metrics::Stop() {
646 SLOG(this, 2) << __func__;
647 }
648
RegisterService(const Service & service)649 void Metrics::RegisterService(const Service& service) {
650 SLOG(this, 2) << __func__;
651 LOG_IF(WARNING, ContainsKey(services_metrics_, &service))
652 << "Repeatedly registering " << service.unique_name();
653 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics());
654 services_metrics_[&service] = service_metrics;
655 InitializeCommonServiceMetrics(service);
656 }
657
DeregisterService(const Service & service)658 void Metrics::DeregisterService(const Service& service) {
659 services_metrics_.erase(&service);
660 }
661
AddServiceStateTransitionTimer(const Service & service,const string & histogram_name,Service::ConnectState start_state,Service::ConnectState stop_state)662 void Metrics::AddServiceStateTransitionTimer(
663 const Service& service,
664 const string& histogram_name,
665 Service::ConnectState start_state,
666 Service::ConnectState stop_state) {
667 SLOG(this, 2) << __func__ << ": adding " << histogram_name << " for "
668 << Service::ConnectStateToString(start_state) << " -> "
669 << Service::ConnectStateToString(stop_state);
670 ServiceMetricsLookupMap::iterator it = services_metrics_.find(&service);
671 if (it == services_metrics_.end()) {
672 SLOG(this, 1) << "service not found";
673 DCHECK(false);
674 return;
675 }
676 ServiceMetrics* service_metrics = it->second.get();
677 CHECK(start_state < stop_state);
678 chromeos_metrics::TimerReporter* timer =
679 new chromeos_metrics::TimerReporter(histogram_name,
680 kTimerHistogramMillisecondsMin,
681 kTimerHistogramMillisecondsMax,
682 kTimerHistogramNumBuckets);
683 service_metrics->timers.push_back(timer); // passes ownership.
684 service_metrics->start_on_state[start_state].push_back(timer);
685 service_metrics->stop_on_state[stop_state].push_back(timer);
686 }
687
NotifyDefaultServiceChanged(const Service * service)688 void Metrics::NotifyDefaultServiceChanged(const Service* service) {
689 base::TimeDelta elapsed_seconds;
690
691 Technology::Identifier technology = (service) ? service->technology() :
692 Technology::kUnknown;
693 if (technology != last_default_technology_) {
694 if (last_default_technology_ != Technology::kUnknown) {
695 string histogram = GetFullMetricName(kMetricTimeOnlineSecondsSuffix,
696 last_default_technology_);
697 time_online_timer_->GetElapsedTime(&elapsed_seconds);
698 SendToUMA(histogram,
699 elapsed_seconds.InSeconds(),
700 kMetricTimeOnlineSecondsMin,
701 kMetricTimeOnlineSecondsMax,
702 kTimerHistogramNumBuckets);
703 }
704 last_default_technology_ = technology;
705 time_online_timer_->Start();
706 }
707
708 // Ignore changes that are not online/offline transitions; e.g.
709 // switching between wired and wireless. TimeToDrop measures
710 // time online regardless of how we are connected.
711 if ((service == nullptr && !was_online_) ||
712 (service != nullptr && was_online_))
713 return;
714
715 if (service == nullptr) {
716 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
717 SendToUMA(kMetricTimeToDropSeconds,
718 elapsed_seconds.InSeconds(),
719 kMetricTimeToDropSecondsMin,
720 kMetricTimeToDropSecondsMax,
721 kTimerHistogramNumBuckets);
722 } else {
723 time_to_drop_timer_->Start();
724 }
725
726 was_online_ = (service != nullptr);
727 }
728
NotifyServiceStateChanged(const Service & service,Service::ConnectState new_state)729 void Metrics::NotifyServiceStateChanged(const Service& service,
730 Service::ConnectState new_state) {
731 ServiceMetricsLookupMap::iterator it = services_metrics_.find(&service);
732 if (it == services_metrics_.end()) {
733 SLOG(this, 1) << "service not found";
734 DCHECK(false);
735 return;
736 }
737 ServiceMetrics* service_metrics = it->second.get();
738 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
739
740 if (new_state == Service::kStateFailure)
741 SendServiceFailure(service);
742
743 #if !defined(__ANDROID__)
744 if (collect_bootstats_) {
745 bootstat_log(base::StringPrintf("network-%s-%s",
746 Technology::NameFromIdentifier(
747 service.technology()).c_str(),
748 service.GetStateString().c_str()).c_str());
749 }
750 #endif // __ANDROID__
751
752 if (new_state != Service::kStateConnected)
753 return;
754
755 base::TimeDelta time_resume_to_ready;
756 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
757 time_resume_to_ready_timer_->Reset();
758 service.SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
759 }
760
GetFullMetricName(const char * metric_suffix,Technology::Identifier technology_id)761 string Metrics::GetFullMetricName(const char* metric_suffix,
762 Technology::Identifier technology_id) {
763 string technology = Technology::NameFromIdentifier(technology_id);
764 technology[0] = base::ToUpperASCII(technology[0]);
765 return base::StringPrintf("%s.%s.%s", kMetricPrefix, technology.c_str(),
766 metric_suffix);
767 }
768
NotifyServiceDisconnect(const Service & service)769 void Metrics::NotifyServiceDisconnect(const Service& service) {
770 Technology::Identifier technology = service.technology();
771 string histogram = GetFullMetricName(kMetricDisconnectSuffix, technology);
772 SendToUMA(histogram,
773 service.explicitly_disconnected(),
774 kMetricDisconnectMin,
775 kMetricDisconnectMax,
776 kMetricDisconnectNumBuckets);
777 }
778
NotifySignalAtDisconnect(const Service & service,int16_t signal_strength)779 void Metrics::NotifySignalAtDisconnect(const Service& service,
780 int16_t signal_strength) {
781 // Negate signal_strength (goes from dBm to -dBm) because the metrics don't
782 // seem to handle negative values well. Now everything's positive.
783 Technology::Identifier technology = service.technology();
784 string histogram = GetFullMetricName(kMetricSignalAtDisconnectSuffix,
785 technology);
786 SendToUMA(histogram,
787 -signal_strength,
788 kMetricSignalAtDisconnectMin,
789 kMetricSignalAtDisconnectMax,
790 kMetricSignalAtDisconnectNumBuckets);
791 }
792
NotifySuspendDone()793 void Metrics::NotifySuspendDone() {
794 time_resume_to_ready_timer_->Start();
795 }
796
NotifyWakeOnWiFiFeaturesEnabledState(WakeOnWiFiFeaturesEnabledState state)797 void Metrics::NotifyWakeOnWiFiFeaturesEnabledState(
798 WakeOnWiFiFeaturesEnabledState state) {
799 SendEnumToUMA(kMetricWakeOnWiFiFeaturesEnabledState, state,
800 kWakeOnWiFiFeaturesEnabledStateMax);
801 }
802
NotifyVerifyWakeOnWiFiSettingsResult(VerifyWakeOnWiFiSettingsResult result)803 void Metrics::NotifyVerifyWakeOnWiFiSettingsResult(
804 VerifyWakeOnWiFiSettingsResult result) {
805 SendEnumToUMA(kMetricVerifyWakeOnWiFiSettingsResult, result,
806 kVerifyWakeOnWiFiSettingsResultMax);
807 }
808
NotifyConnectedToServiceAfterWake(WiFiConnectionStatusAfterWake status)809 void Metrics::NotifyConnectedToServiceAfterWake(
810 WiFiConnectionStatusAfterWake status) {
811 SendEnumToUMA(kMetricWiFiConnectionStatusAfterWake, status,
812 kWiFiConnetionStatusAfterWakeMax);
813 }
814
NotifyTerminationActionsStarted()815 void Metrics::NotifyTerminationActionsStarted() {
816 if (time_termination_actions_timer->HasStarted())
817 return;
818 time_termination_actions_timer->Start();
819 }
820
NotifyTerminationActionsCompleted(bool success)821 void Metrics::NotifyTerminationActionsCompleted(bool success) {
822 if (!time_termination_actions_timer->HasStarted())
823 return;
824
825 TerminationActionResult result = success ? kTerminationActionResultSuccess
826 : kTerminationActionResultFailure;
827
828 base::TimeDelta elapsed_time;
829 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
830 time_termination_actions_timer->Reset();
831 string time_metric, result_metric;
832 time_metric = kMetricTerminationActionTimeTaken;
833 result_metric = kMetricTerminationActionResult;
834
835 SendToUMA(time_metric,
836 elapsed_time.InMilliseconds(),
837 kMetricTerminationActionTimeTakenMillisecondsMin,
838 kMetricTerminationActionTimeTakenMillisecondsMax,
839 kTimerHistogramNumBuckets);
840
841 SendEnumToUMA(result_metric,
842 result,
843 kTerminationActionResultMax);
844 }
845
NotifySuspendActionsStarted()846 void Metrics::NotifySuspendActionsStarted() {
847 if (time_suspend_actions_timer->HasStarted())
848 return;
849 time_suspend_actions_timer->Start();
850 wake_on_wifi_throttled_ = false;
851 }
852
NotifySuspendActionsCompleted(bool success)853 void Metrics::NotifySuspendActionsCompleted(bool success) {
854 if (!time_suspend_actions_timer->HasStarted())
855 return;
856
857 // Reset for next dark resume.
858 wake_reason_received_ = false;
859
860 SuspendActionResult result =
861 success ? kSuspendActionResultSuccess : kSuspendActionResultFailure;
862
863 base::TimeDelta elapsed_time;
864 time_suspend_actions_timer->GetElapsedTime(&elapsed_time);
865 time_suspend_actions_timer->Reset();
866 string time_metric, result_metric;
867 time_metric = kMetricSuspendActionTimeTaken;
868 result_metric = kMetricSuspendActionResult;
869
870 SendToUMA(time_metric,
871 elapsed_time.InMilliseconds(),
872 kMetricSuspendActionTimeTakenMillisecondsMin,
873 kMetricSuspendActionTimeTakenMillisecondsMax,
874 kTimerHistogramNumBuckets);
875
876 SendEnumToUMA(result_metric,
877 result,
878 kSuspendActionResultMax);
879 }
880
NotifyDarkResumeActionsStarted()881 void Metrics::NotifyDarkResumeActionsStarted() {
882 if (time_dark_resume_actions_timer->HasStarted())
883 return;
884 time_dark_resume_actions_timer->Start();
885 num_scan_results_expected_in_dark_resume_ = 0;
886 dark_resume_scan_retries_ = 0;
887 }
888
NotifyDarkResumeActionsCompleted(bool success)889 void Metrics::NotifyDarkResumeActionsCompleted(bool success) {
890 if (!time_dark_resume_actions_timer->HasStarted())
891 return;
892
893 // Reset for next dark resume.
894 wake_reason_received_ = false;
895
896 DarkResumeActionResult result =
897 success ? kDarkResumeActionResultSuccess : kDarkResumeActionResultFailure;
898
899 base::TimeDelta elapsed_time;
900 time_dark_resume_actions_timer->GetElapsedTime(&elapsed_time);
901 time_dark_resume_actions_timer->Reset();
902
903 SendToUMA(kMetricDarkResumeActionTimeTaken,
904 elapsed_time.InMilliseconds(),
905 kMetricDarkResumeActionTimeTakenMillisecondsMin,
906 kMetricDarkResumeActionTimeTakenMillisecondsMax,
907 kTimerHistogramNumBuckets);
908
909 SendEnumToUMA(kMetricDarkResumeActionResult,
910 result,
911 kDarkResumeActionResultMax);
912
913 DarkResumeUnmatchedScanResultReceived unmatched_scan_results_received =
914 (num_scan_results_expected_in_dark_resume_ < 0)
915 ? kDarkResumeUnmatchedScanResultsReceivedTrue
916 : kDarkResumeUnmatchedScanResultsReceivedFalse;
917 SendEnumToUMA(kMetricDarkResumeUnmatchedScanResultReceived,
918 unmatched_scan_results_received,
919 kDarkResumeUnmatchedScanResultsReceivedMax);
920
921 SendToUMA(kMetricDarkResumeScanNumRetries, dark_resume_scan_retries_,
922 kMetricDarkResumeScanNumRetriesMin,
923 kMetricDarkResumeScanNumRetriesMax, kTimerHistogramNumBuckets);
924 }
925
NotifyDarkResumeInitiateScan()926 void Metrics::NotifyDarkResumeInitiateScan() {
927 ++num_scan_results_expected_in_dark_resume_;
928 }
929
NotifyDarkResumeScanResultsReceived()930 void Metrics::NotifyDarkResumeScanResultsReceived() {
931 --num_scan_results_expected_in_dark_resume_;
932 }
933
NotifyLinkMonitorFailure(Technology::Identifier technology,LinkMonitorFailure failure,int seconds_to_failure,int broadcast_error_count,int unicast_error_count)934 void Metrics::NotifyLinkMonitorFailure(
935 Technology::Identifier technology,
936 LinkMonitorFailure failure,
937 int seconds_to_failure,
938 int broadcast_error_count,
939 int unicast_error_count) {
940 string histogram = GetFullMetricName(kMetricLinkMonitorFailureSuffix,
941 technology);
942 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
943
944 if (failure == kLinkMonitorFailureThresholdReached) {
945 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
946 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
947 }
948 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailureSuffix,
949 technology);
950 SendToUMA(histogram,
951 seconds_to_failure,
952 kMetricLinkMonitorSecondsToFailureMin,
953 kMetricLinkMonitorSecondsToFailureMax,
954 kMetricLinkMonitorSecondsToFailureNumBuckets);
955 histogram = GetFullMetricName(
956 kMetricLinkMonitorBroadcastErrorsAtFailureSuffix, technology);
957 SendToUMA(histogram,
958 broadcast_error_count,
959 kMetricLinkMonitorErrorCountMin,
960 kMetricLinkMonitorErrorCountMax,
961 kMetricLinkMonitorErrorCountNumBuckets);
962 histogram = GetFullMetricName(
963 kMetricLinkMonitorUnicastErrorsAtFailureSuffix, technology);
964 SendToUMA(histogram,
965 unicast_error_count,
966 kMetricLinkMonitorErrorCountMin,
967 kMetricLinkMonitorErrorCountMax,
968 kMetricLinkMonitorErrorCountNumBuckets);
969 }
970 }
971
NotifyLinkMonitorResponseTimeSampleAdded(Technology::Identifier technology,int response_time_milliseconds)972 void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
973 Technology::Identifier technology,
974 int response_time_milliseconds) {
975 string histogram = GetFullMetricName(
976 kMetricLinkMonitorResponseTimeSampleSuffix, technology);
977 SendToUMA(histogram,
978 response_time_milliseconds,
979 kMetricLinkMonitorResponseTimeSampleMin,
980 kMetricLinkMonitorResponseTimeSampleMax,
981 kMetricLinkMonitorResponseTimeSampleNumBuckets);
982 }
983
984 #if !defined(DISABLE_WIFI)
985 // TODO(zqiu): Change argument type from IEEE_80211::WiFiReasonCode to
986 // Metrics::WiFiStatusType, to remove dependency for IEEE_80211.
Notify80211Disconnect(WiFiDisconnectByWhom by_whom,IEEE_80211::WiFiReasonCode reason)987 void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
988 IEEE_80211::WiFiReasonCode reason) {
989 string metric_disconnect_reason;
990 string metric_disconnect_type;
991 WiFiStatusType type;
992
993 if (by_whom == kDisconnectedByAp) {
994 metric_disconnect_reason = kMetricLinkApDisconnectReason;
995 metric_disconnect_type = kMetricLinkApDisconnectType;
996 type = kStatusCodeTypeByAp;
997 } else {
998 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
999 metric_disconnect_type = kMetricLinkClientDisconnectType;
1000 switch (reason) {
1001 case IEEE_80211::kReasonCodeSenderHasLeft:
1002 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
1003 type = kStatusCodeTypeByUser;
1004 break;
1005
1006 case IEEE_80211::kReasonCodeInactivity:
1007 type = kStatusCodeTypeConsideredDead;
1008 break;
1009
1010 default:
1011 type = kStatusCodeTypeByClient;
1012 break;
1013 }
1014 }
1015 SendEnumToUMA(metric_disconnect_reason, reason,
1016 IEEE_80211::kStatusCodeMax);
1017 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
1018 }
1019 #endif // DISABLE_WIFI
1020
RegisterDevice(int interface_index,Technology::Identifier technology)1021 void Metrics::RegisterDevice(int interface_index,
1022 Technology::Identifier technology) {
1023 SLOG(this, 2) << __func__ << ": " << interface_index;
1024 shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
1025 devices_metrics_[interface_index] = device_metrics;
1026 device_metrics->technology = technology;
1027 string histogram = GetFullMetricName(
1028 kMetricTimeToInitializeMillisecondsSuffix, technology);
1029 device_metrics->initialization_timer.reset(
1030 new chromeos_metrics::TimerReporter(
1031 histogram,
1032 kMetricTimeToInitializeMillisecondsMin,
1033 kMetricTimeToInitializeMillisecondsMax,
1034 kMetricTimeToInitializeMillisecondsNumBuckets));
1035 device_metrics->initialization_timer->Start();
1036 histogram = GetFullMetricName(kMetricTimeToEnableMillisecondsSuffix,
1037 technology);
1038 device_metrics->enable_timer.reset(
1039 new chromeos_metrics::TimerReporter(
1040 histogram,
1041 kMetricTimeToEnableMillisecondsMin,
1042 kMetricTimeToEnableMillisecondsMax,
1043 kMetricTimeToEnableMillisecondsNumBuckets));
1044 histogram = GetFullMetricName(kMetricTimeToDisableMillisecondsSuffix,
1045 technology);
1046 device_metrics->disable_timer.reset(
1047 new chromeos_metrics::TimerReporter(
1048 histogram,
1049 kMetricTimeToDisableMillisecondsMin,
1050 kMetricTimeToDisableMillisecondsMax,
1051 kMetricTimeToDisableMillisecondsNumBuckets));
1052 histogram = GetFullMetricName(kMetricTimeToScanMillisecondsSuffix,
1053 technology);
1054 device_metrics->scan_timer.reset(
1055 new chromeos_metrics::TimerReporter(
1056 histogram,
1057 kMetricTimeToScanMillisecondsMin,
1058 kMetricTimeToScanMillisecondsMax,
1059 kMetricTimeToScanMillisecondsNumBuckets));
1060 histogram = GetFullMetricName(kMetricTimeToConnectMillisecondsSuffix,
1061 technology);
1062 device_metrics->connect_timer.reset(
1063 new chromeos_metrics::TimerReporter(
1064 histogram,
1065 kMetricTimeToConnectMillisecondsMin,
1066 kMetricTimeToConnectMillisecondsMax,
1067 kMetricTimeToConnectMillisecondsNumBuckets));
1068 histogram = GetFullMetricName(kMetricTimeToScanAndConnectMillisecondsSuffix,
1069 technology);
1070 device_metrics->scan_connect_timer.reset(
1071 new chromeos_metrics::TimerReporter(
1072 histogram,
1073 kMetricTimeToScanMillisecondsMin,
1074 kMetricTimeToScanMillisecondsMax +
1075 kMetricTimeToConnectMillisecondsMax,
1076 kMetricTimeToScanMillisecondsNumBuckets +
1077 kMetricTimeToConnectMillisecondsNumBuckets));
1078 device_metrics->auto_connect_timer.reset(
1079 new chromeos_metrics::TimerReporter(
1080 kMetricCellularAutoConnectTotalTime,
1081 kMetricCellularAutoConnectTotalTimeMin,
1082 kMetricCellularAutoConnectTotalTimeMax,
1083 kMetricCellularAutoConnectTotalTimeNumBuckets));
1084 }
1085
IsDeviceRegistered(int interface_index,Technology::Identifier technology)1086 bool Metrics::IsDeviceRegistered(int interface_index,
1087 Technology::Identifier technology) {
1088 SLOG(this, 2) << __func__ << ": interface index: " << interface_index
1089 << ", technology: " << technology;
1090 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1091 if (device_metrics == nullptr)
1092 return false;
1093 // Make sure the device technologies match.
1094 return (technology == device_metrics->technology);
1095 }
1096
DeregisterDevice(int interface_index)1097 void Metrics::DeregisterDevice(int interface_index) {
1098 SLOG(this, 2) << __func__ << ": interface index: " << interface_index;
1099
1100 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1101 if (device_metrics != nullptr) {
1102 NotifyDeviceRemovedEvent(device_metrics->technology);
1103 }
1104
1105 devices_metrics_.erase(interface_index);
1106 }
1107
NotifyDeviceInitialized(int interface_index)1108 void Metrics::NotifyDeviceInitialized(int interface_index) {
1109 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1110 if (device_metrics == nullptr)
1111 return;
1112 if (!device_metrics->initialization_timer->Stop())
1113 return;
1114 device_metrics->initialization_timer->ReportMilliseconds();
1115 }
1116
NotifyDeviceEnableStarted(int interface_index)1117 void Metrics::NotifyDeviceEnableStarted(int interface_index) {
1118 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1119 if (device_metrics == nullptr)
1120 return;
1121 device_metrics->enable_timer->Start();
1122 }
1123
NotifyDeviceEnableFinished(int interface_index)1124 void Metrics::NotifyDeviceEnableFinished(int interface_index) {
1125 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1126 if (device_metrics == nullptr)
1127 return;
1128 if (!device_metrics->enable_timer->Stop())
1129 return;
1130 device_metrics->enable_timer->ReportMilliseconds();
1131 }
1132
NotifyDeviceDisableStarted(int interface_index)1133 void Metrics::NotifyDeviceDisableStarted(int interface_index) {
1134 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1135 if (device_metrics == nullptr)
1136 return;
1137 device_metrics->disable_timer->Start();
1138 }
1139
NotifyDeviceDisableFinished(int interface_index)1140 void Metrics::NotifyDeviceDisableFinished(int interface_index) {
1141 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1142 if (device_metrics == nullptr)
1143 return;
1144 if (!device_metrics->disable_timer->Stop())
1145 return;
1146 device_metrics->disable_timer->ReportMilliseconds();
1147 }
1148
NotifyDeviceScanStarted(int interface_index)1149 void Metrics::NotifyDeviceScanStarted(int interface_index) {
1150 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1151 if (device_metrics == nullptr)
1152 return;
1153 device_metrics->scan_timer->Start();
1154 device_metrics->scan_connect_timer->Start();
1155 }
1156
NotifyDeviceScanFinished(int interface_index)1157 void Metrics::NotifyDeviceScanFinished(int interface_index) {
1158 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1159 if (device_metrics == nullptr)
1160 return;
1161 if (!device_metrics->scan_timer->Stop())
1162 return;
1163 // Don't send TimeToScan metrics if the elapsed time exceeds the max metrics
1164 // value. Huge scan times usually mean something's gone awry; for cellular,
1165 // for instance, this usually means that the modem is in an area without
1166 // service and we're not interested in this scenario.
1167 base::TimeDelta elapsed_time;
1168 device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
1169 if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
1170 device_metrics->scan_timer->ReportMilliseconds();
1171 }
1172
ResetScanTimer(int interface_index)1173 void Metrics::ResetScanTimer(int interface_index) {
1174 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1175 if (device_metrics == nullptr)
1176 return;
1177 device_metrics->scan_timer->Reset();
1178 }
1179
NotifyDeviceConnectStarted(int interface_index,bool is_auto_connecting)1180 void Metrics::NotifyDeviceConnectStarted(int interface_index,
1181 bool is_auto_connecting) {
1182 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1183 if (device_metrics == nullptr)
1184 return;
1185 device_metrics->connect_timer->Start();
1186
1187 if (is_auto_connecting) {
1188 device_metrics->auto_connect_tries++;
1189 if (device_metrics->auto_connect_tries == 1)
1190 device_metrics->auto_connect_timer->Start();
1191 } else {
1192 AutoConnectMetricsReset(device_metrics);
1193 }
1194 }
1195
NotifyDeviceConnectFinished(int interface_index)1196 void Metrics::NotifyDeviceConnectFinished(int interface_index) {
1197 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1198 if (device_metrics == nullptr)
1199 return;
1200 if (!device_metrics->connect_timer->Stop())
1201 return;
1202 device_metrics->connect_timer->ReportMilliseconds();
1203
1204 if (device_metrics->auto_connect_tries > 0) {
1205 if (!device_metrics->auto_connect_timer->Stop())
1206 return;
1207 base::TimeDelta elapsed_time;
1208 device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
1209 if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
1210 return;
1211 device_metrics->auto_connect_timer->ReportMilliseconds();
1212 SendToUMA(kMetricCellularAutoConnectTries,
1213 device_metrics->auto_connect_tries,
1214 kMetricCellularAutoConnectTriesMin,
1215 kMetricCellularAutoConnectTriesMax,
1216 kMetricCellularAutoConnectTriesNumBuckets);
1217 AutoConnectMetricsReset(device_metrics);
1218 }
1219
1220 if (!device_metrics->scan_connect_timer->Stop())
1221 return;
1222 device_metrics->scan_connect_timer->ReportMilliseconds();
1223 }
1224
ResetConnectTimer(int interface_index)1225 void Metrics::ResetConnectTimer(int interface_index) {
1226 DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1227 if (device_metrics == nullptr)
1228 return;
1229 device_metrics->connect_timer->Reset();
1230 device_metrics->scan_connect_timer->Reset();
1231 }
1232
Notify3GPPRegistrationDelayedDropPosted()1233 void Metrics::Notify3GPPRegistrationDelayedDropPosted() {
1234 SendEnumToUMA(kMetricCellular3GPPRegistrationDelayedDrop,
1235 kCellular3GPPRegistrationDelayedDropPosted,
1236 kCellular3GPPRegistrationDelayedDropMax);
1237 }
1238
Notify3GPPRegistrationDelayedDropCanceled()1239 void Metrics::Notify3GPPRegistrationDelayedDropCanceled() {
1240 SendEnumToUMA(kMetricCellular3GPPRegistrationDelayedDrop,
1241 kCellular3GPPRegistrationDelayedDropCanceled,
1242 kCellular3GPPRegistrationDelayedDropMax);
1243 }
1244
NotifyCellularDeviceDrop(const string & network_technology,uint16_t signal_strength)1245 void Metrics::NotifyCellularDeviceDrop(const string& network_technology,
1246 uint16_t signal_strength) {
1247 SLOG(this, 2) << __func__ << ": " << network_technology
1248 << ", " << signal_strength;
1249 CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
1250 if (network_technology == kNetworkTechnology1Xrtt) {
1251 drop_technology = kCellularDropTechnology1Xrtt;
1252 } else if (network_technology == kNetworkTechnologyEdge) {
1253 drop_technology = kCellularDropTechnologyEdge;
1254 } else if (network_technology == kNetworkTechnologyEvdo) {
1255 drop_technology = kCellularDropTechnologyEvdo;
1256 } else if (network_technology == kNetworkTechnologyGprs) {
1257 drop_technology = kCellularDropTechnologyGprs;
1258 } else if (network_technology == kNetworkTechnologyGsm) {
1259 drop_technology = kCellularDropTechnologyGsm;
1260 } else if (network_technology == kNetworkTechnologyHspa) {
1261 drop_technology = kCellularDropTechnologyHspa;
1262 } else if (network_technology == kNetworkTechnologyHspaPlus) {
1263 drop_technology = kCellularDropTechnologyHspaPlus;
1264 } else if (network_technology == kNetworkTechnologyLte) {
1265 drop_technology = kCellularDropTechnologyLte;
1266 } else if (network_technology == kNetworkTechnologyUmts) {
1267 drop_technology = kCellularDropTechnologyUmts;
1268 }
1269 SendEnumToUMA(kMetricCellularDrop,
1270 drop_technology,
1271 kCellularDropTechnologyMax);
1272 SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
1273 signal_strength,
1274 kMetricCellularSignalStrengthBeforeDropMin,
1275 kMetricCellularSignalStrengthBeforeDropMax,
1276 kMetricCellularSignalStrengthBeforeDropNumBuckets);
1277 }
1278
NotifyCellularDeviceConnectionFailure()1279 void Metrics::NotifyCellularDeviceConnectionFailure() {
1280 library_->SendEnumToUMA(
1281 kMetricCellularFailure, kMetricCellularConnectionFailure,
1282 kMetricCellularMaxFailure);
1283 }
1284
NotifyCellularDeviceDisconnectionFailure()1285 void Metrics::NotifyCellularDeviceDisconnectionFailure() {
1286 library_->SendEnumToUMA(
1287 kMetricCellularFailure, kMetricCellularDisconnectionFailure,
1288 kMetricCellularMaxFailure);
1289 }
1290
NotifyCellularOutOfCredits(Metrics::CellularOutOfCreditsReason reason)1291 void Metrics::NotifyCellularOutOfCredits(
1292 Metrics::CellularOutOfCreditsReason reason) {
1293 SendEnumToUMA(kMetricCellularOutOfCreditsReason,
1294 reason,
1295 kCellularOutOfCreditsReasonMax);
1296 }
1297
NotifyCorruptedProfile()1298 void Metrics::NotifyCorruptedProfile() {
1299 SendEnumToUMA(kMetricCorruptedProfile,
1300 kCorruptedProfile,
1301 kCorruptedProfileMax);
1302 }
1303
NotifyWifiAutoConnectableServices(int num_services)1304 void Metrics::NotifyWifiAutoConnectableServices(int num_services) {
1305 SendToUMA(kMetricWifiAutoConnectableServices,
1306 num_services,
1307 kMetricWifiAutoConnectableServicesMin,
1308 kMetricWifiAutoConnectableServicesMax,
1309 kMetricWifiAutoConnectableServicesNumBuckets);
1310 }
1311
NotifyWifiAvailableBSSes(int num_bss)1312 void Metrics::NotifyWifiAvailableBSSes(int num_bss) {
1313 SendToUMA(kMetricWifiAvailableBSSes,
1314 num_bss,
1315 kMetricWifiAvailableBSSesMin,
1316 kMetricWifiAvailableBSSesMax,
1317 kMetricWifiAvailableBSSesNumBuckets);
1318 }
1319
NotifyServicesOnSameNetwork(int num_services)1320 void Metrics::NotifyServicesOnSameNetwork(int num_services) {
1321 SendToUMA(kMetricServicesOnSameNetwork,
1322 num_services,
1323 kMetricServicesOnSameNetworkMin,
1324 kMetricServicesOnSameNetworkMax,
1325 kMetricServicesOnSameNetworkNumBuckets);
1326 }
1327
NotifyUserInitiatedEvent(int event)1328 void Metrics::NotifyUserInitiatedEvent(int event) {
1329 SendEnumToUMA(kMetricUserInitiatedEvents,
1330 event,
1331 kUserInitiatedEventMax);
1332 }
1333
NotifyWifiTxBitrate(int bitrate)1334 void Metrics::NotifyWifiTxBitrate(int bitrate) {
1335 SendToUMA(kMetricWifiTxBitrate,
1336 bitrate,
1337 kMetricWifiTxBitrateMin,
1338 kMetricWifiTxBitrateMax,
1339 kMetricWifiTxBitrateNumBuckets);
1340 }
1341
NotifyUserInitiatedConnectionResult(const string & name,int result)1342 void Metrics::NotifyUserInitiatedConnectionResult(const string& name,
1343 int result) {
1344 SendEnumToUMA(name,
1345 result,
1346 kUserInitiatedConnectionResultMax);
1347 }
1348
NotifyUserInitiatedConnectionFailureReason(const string & name,const Service::ConnectFailure failure)1349 void Metrics::NotifyUserInitiatedConnectionFailureReason(
1350 const string& name, const Service::ConnectFailure failure) {
1351 UserInitiatedConnectionFailureReason reason;
1352 switch (failure) {
1353 case Service::kFailureBadPassphrase:
1354 reason = kUserInitiatedConnectionFailureReasonBadPassphrase;
1355 break;
1356 case Service::kFailureBadWEPKey:
1357 reason = kUserInitiatedConnectionFailureReasonBadWEPKey;
1358 break;
1359 case Service::kFailureConnect:
1360 reason = kUserInitiatedConnectionFailureReasonConnect;
1361 break;
1362 case Service::kFailureDHCP:
1363 reason = kUserInitiatedConnectionFailureReasonDHCP;
1364 break;
1365 case Service::kFailureDNSLookup:
1366 reason = kUserInitiatedConnectionFailureReasonDNSLookup;
1367 break;
1368 case Service::kFailureEAPAuthentication:
1369 reason = kUserInitiatedConnectionFailureReasonEAPAuthentication;
1370 break;
1371 case Service::kFailureEAPLocalTLS:
1372 reason = kUserInitiatedConnectionFailureReasonEAPLocalTLS;
1373 break;
1374 case Service::kFailureEAPRemoteTLS:
1375 reason = kUserInitiatedConnectionFailureReasonEAPRemoteTLS;
1376 break;
1377 case Service::kFailureOutOfRange:
1378 reason = kUserInitiatedConnectionFailureReasonOutOfRange;
1379 break;
1380 case Service::kFailurePinMissing:
1381 reason = kUserInitiatedConnectionFailureReasonPinMissing;
1382 break;
1383 default:
1384 reason = kUserInitiatedConnectionFailureReasonUnknown;
1385 break;
1386 }
1387 SendEnumToUMA(name,
1388 reason,
1389 kUserInitiatedConnectionFailureReasonMax);
1390 }
1391
NotifyFallbackDNSTestResult(Technology::Identifier technology_id,int result)1392 void Metrics::NotifyFallbackDNSTestResult(Technology::Identifier technology_id,
1393 int result) {
1394 string histogram = GetFullMetricName(kMetricFallbackDNSTestResultSuffix,
1395 technology_id);
1396 SendEnumToUMA(histogram,
1397 result,
1398 kFallbackDNSTestResultMax);
1399 }
1400
NotifyNetworkProblemDetected(Technology::Identifier technology_id,int reason)1401 void Metrics::NotifyNetworkProblemDetected(Technology::Identifier technology_id,
1402 int reason) {
1403 string histogram = GetFullMetricName(kMetricNetworkProblemDetectedSuffix,
1404 technology_id);
1405 SendEnumToUMA(histogram,
1406 reason,
1407 kNetworkProblemMax);
1408 }
1409
NotifyDeviceConnectionStatus(ConnectionStatus status)1410 void Metrics::NotifyDeviceConnectionStatus(ConnectionStatus status) {
1411 SendEnumToUMA(kMetricDeviceConnectionStatus, status, kConnectionStatusMax);
1412 }
1413
NotifyDhcpClientStatus(DhcpClientStatus status)1414 void Metrics::NotifyDhcpClientStatus(DhcpClientStatus status) {
1415 SendEnumToUMA(kMetricDhcpClientStatus, status, kDhcpClientStatusMax);
1416 }
1417
NotifyNetworkConnectionIPType(Technology::Identifier technology_id,NetworkConnectionIPType type)1418 void Metrics::NotifyNetworkConnectionIPType(
1419 Technology::Identifier technology_id, NetworkConnectionIPType type) {
1420 string histogram = GetFullMetricName(kMetricNetworkConnectionIPTypeSuffix,
1421 technology_id);
1422 SendEnumToUMA(histogram, type, kNetworkConnectionIPTypeMax);
1423 }
1424
NotifyIPv6ConnectivityStatus(Technology::Identifier technology_id,bool status)1425 void Metrics::NotifyIPv6ConnectivityStatus(Technology::Identifier technology_id,
1426 bool status) {
1427 string histogram = GetFullMetricName(kMetricIPv6ConnectivityStatusSuffix,
1428 technology_id);
1429 IPv6ConnectivityStatus ipv6_status = status ? kIPv6ConnectivityStatusYes
1430 : kIPv6ConnectivityStatusNo;
1431 SendEnumToUMA(histogram, ipv6_status, kIPv6ConnectivityStatusMax);
1432 }
1433
NotifyDevicePresenceStatus(Technology::Identifier technology_id,bool status)1434 void Metrics::NotifyDevicePresenceStatus(Technology::Identifier technology_id,
1435 bool status) {
1436 string histogram = GetFullMetricName(kMetricDevicePresenceStatusSuffix,
1437 technology_id);
1438 DevicePresenceStatus presence = status ? kDevicePresenceStatusYes
1439 : kDevicePresenceStatusNo;
1440 SendEnumToUMA(histogram, presence, kDevicePresenceStatusMax);
1441 }
1442
NotifyDeviceRemovedEvent(Technology::Identifier technology_id)1443 void Metrics::NotifyDeviceRemovedEvent(Technology::Identifier technology_id) {
1444 DeviceTechnologyType type;
1445 switch (technology_id) {
1446 case Technology::kEthernet:
1447 type = kDeviceTechnologyTypeEthernet;
1448 break;
1449 case Technology::kWifi:
1450 type = kDeviceTechnologyTypeWifi;
1451 break;
1452 case Technology::kWiMax:
1453 type = kDeviceTechnologyTypeWimax;
1454 break;
1455 case Technology::kCellular:
1456 type = kDeviceTechnologyTypeCellular;
1457 break;
1458 default:
1459 type = kDeviceTechnologyTypeUnknown;
1460 break;
1461 }
1462 SendEnumToUMA(kMetricDeviceRemovedEvent, type, kDeviceTechnologyTypeMax);
1463 }
1464
NotifyUnreliableLinkSignalStrength(Technology::Identifier technology_id,int signal_strength)1465 void Metrics::NotifyUnreliableLinkSignalStrength(
1466 Technology::Identifier technology_id, int signal_strength) {
1467 string histogram = GetFullMetricName(
1468 kMetricUnreliableLinkSignalStrengthSuffix, technology_id);
1469 SendToUMA(histogram,
1470 signal_strength,
1471 kMetricSerivceSignalStrengthMin,
1472 kMetricServiceSignalStrengthMax,
1473 kMetricServiceSignalStrengthNumBuckets);
1474 }
1475
SendEnumToUMA(const string & name,int sample,int max)1476 bool Metrics::SendEnumToUMA(const string& name, int sample, int max) {
1477 SLOG(this, 5)
1478 << "Sending enum " << name << " with value " << sample << ".";
1479 return library_->SendEnumToUMA(name, sample, max);
1480 }
1481
SendToUMA(const string & name,int sample,int min,int max,int num_buckets)1482 bool Metrics::SendToUMA(const string& name, int sample, int min, int max,
1483 int num_buckets) {
1484 SLOG(this, 5)
1485 << "Sending metric " << name << " with value " << sample << ".";
1486 return library_->SendToUMA(name, sample, min, max, num_buckets);
1487 }
1488
SendSparseToUMA(const string & name,int sample)1489 bool Metrics::SendSparseToUMA(const string& name, int sample) {
1490 SLOG(this, 5)
1491 << "Sending sparse metric " << name << " with value " << sample << ".";
1492 return library_->SendSparseToUMA(name, sample);
1493 }
1494
NotifyWakeOnWiFiThrottled()1495 void Metrics::NotifyWakeOnWiFiThrottled() {
1496 wake_on_wifi_throttled_ = true;
1497 }
1498
NotifySuspendWithWakeOnWiFiEnabledDone()1499 void Metrics::NotifySuspendWithWakeOnWiFiEnabledDone() {
1500 WakeOnWiFiThrottled throttled_result = wake_on_wifi_throttled_
1501 ? kWakeOnWiFiThrottledTrue
1502 : kWakeOnWiFiThrottledFalse;
1503 SendEnumToUMA(kMetricWakeOnWiFiThrottled, throttled_result,
1504 kWakeOnWiFiThrottledMax);
1505 }
1506
NotifyWakeupReasonReceived()1507 void Metrics::NotifyWakeupReasonReceived() { wake_reason_received_ = true; }
1508
1509 #if !defined(DISABLE_WIFI)
1510 // TODO(zqiu): Change argument type from WakeOnWiFi::WakeOnWiFiTrigger to
1511 // Metrics::DarkResumeWakeReason, to remove the dependency for WakeOnWiFi.
1512 // to remove the dependency for WakeOnWiFi.
NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::WakeOnWiFiTrigger reason)1513 void Metrics::NotifyWakeOnWiFiOnDarkResume(
1514 WakeOnWiFi::WakeOnWiFiTrigger reason) {
1515 WakeReasonReceivedBeforeOnDarkResume result =
1516 wake_reason_received_ ? kWakeReasonReceivedBeforeOnDarkResumeTrue
1517 : kWakeReasonReceivedBeforeOnDarkResumeFalse;
1518
1519 SendEnumToUMA(kMetricWakeReasonReceivedBeforeOnDarkResume, result,
1520 kWakeReasonReceivedBeforeOnDarkResumeMax);
1521
1522 DarkResumeWakeReason wake_reason;
1523 switch (reason) {
1524 case WakeOnWiFi::kWakeTriggerPattern:
1525 wake_reason = kDarkResumeWakeReasonPattern;
1526 break;
1527 case WakeOnWiFi::kWakeTriggerDisconnect:
1528 wake_reason = kDarkResumeWakeReasonDisconnect;
1529 break;
1530 case WakeOnWiFi::kWakeTriggerSSID:
1531 wake_reason = kDarkResumeWakeReasonSSID;
1532 break;
1533 case WakeOnWiFi::kWakeTriggerUnsupported:
1534 default:
1535 wake_reason = kDarkResumeWakeReasonUnsupported;
1536 break;
1537 }
1538 SendEnumToUMA(kMetricDarkResumeWakeReason, wake_reason,
1539 kDarkResumeWakeReasonMax);
1540 }
1541 #endif // DISABLE_WIFI
1542
NotifyScanStartedInDarkResume(bool is_active_scan)1543 void Metrics::NotifyScanStartedInDarkResume(bool is_active_scan) {
1544 DarkResumeScanType scan_type =
1545 is_active_scan ? kDarkResumeScanTypeActive : kDarkResumeScanTypePassive;
1546 SendEnumToUMA(kMetricDarkResumeScanType, scan_type, kDarkResumeScanTypeMax);
1547 }
1548
NotifyDarkResumeScanRetry()1549 void Metrics::NotifyDarkResumeScanRetry() {
1550 ++dark_resume_scan_retries_;
1551 }
1552
NotifyBeforeSuspendActions(bool is_connected,bool in_dark_resume)1553 void Metrics::NotifyBeforeSuspendActions(bool is_connected,
1554 bool in_dark_resume) {
1555 if (in_dark_resume && dark_resume_scan_retries_) {
1556 DarkResumeScanRetryResult connect_result =
1557 is_connected ? kDarkResumeScanRetryResultConnected
1558 : kDarkResumeScanRetryResultNotConnected;
1559 SendEnumToUMA(kMetricDarkResumeScanRetryResult, connect_result,
1560 kDarkResumeScanRetryResultMax);
1561 }
1562 }
1563
NotifyConnectionDiagnosticsIssue(const string & issue)1564 void Metrics::NotifyConnectionDiagnosticsIssue(const string& issue) {
1565 ConnectionDiagnosticsIssue issue_enum;
1566 if (issue == ConnectionDiagnostics::kIssueIPCollision) {
1567 issue_enum = kConnectionDiagnosticsIssueIPCollision;
1568 } else if (issue == ConnectionDiagnostics::kIssueRouting) {
1569 issue_enum = kConnectionDiagnosticsIssueRouting;
1570 } else if (issue == ConnectionDiagnostics::kIssueHTTPBrokenPortal) {
1571 issue_enum = kConnectionDiagnosticsIssueHTTPBrokenPortal;
1572 } else if (issue == ConnectionDiagnostics::kIssueDNSServerMisconfig) {
1573 issue_enum = kConnectionDiagnosticsIssueDNSServerMisconfig;
1574 } else if (issue == ConnectionDiagnostics::kIssueDNSServerNoResponse) {
1575 issue_enum = kConnectionDiagnosticsIssueDNSServerNoResponse;
1576 } else if (issue == ConnectionDiagnostics::kIssueNoDNSServersConfigured) {
1577 issue_enum = kConnectionDiagnosticsIssueNoDNSServersConfigured;
1578 } else if (issue == ConnectionDiagnostics::kIssueDNSServersInvalid) {
1579 issue_enum = kConnectionDiagnosticsIssueDNSServersInvalid;
1580 } else if (issue == ConnectionDiagnostics::kIssueNone) {
1581 issue_enum = kConnectionDiagnosticsIssueNone;
1582 } else if (issue == ConnectionDiagnostics::kIssueCaptivePortal) {
1583 issue_enum = kConnectionDiagnosticsIssueCaptivePortal;
1584 } else if (issue == ConnectionDiagnostics::kIssueGatewayUpstream) {
1585 issue_enum = kConnectionDiagnosticsIssueGatewayUpstream;
1586 } else if (issue == ConnectionDiagnostics::kIssueGatewayNotResponding) {
1587 issue_enum = kConnectionDiagnosticsIssueGatewayNotResponding;
1588 } else if (issue == ConnectionDiagnostics::kIssueServerNotResponding) {
1589 issue_enum = kConnectionDiagnosticsIssueServerNotResponding;
1590 } else if (issue == ConnectionDiagnostics::kIssueGatewayArpFailed) {
1591 issue_enum = kConnectionDiagnosticsIssueGatewayArpFailed;
1592 } else if (issue == ConnectionDiagnostics::kIssueServerArpFailed) {
1593 issue_enum = kConnectionDiagnosticsIssueServerArpFailed;
1594 } else if (issue == ConnectionDiagnostics::kIssueInternalError) {
1595 issue_enum = kConnectionDiagnosticsIssueInternalError;
1596 } else if (issue == ConnectionDiagnostics::kIssueGatewayNoNeighborEntry) {
1597 issue_enum = kConnectionDiagnosticsIssueGatewayNoNeighborEntry;
1598 } else if (issue == ConnectionDiagnostics::kIssueServerNoNeighborEntry) {
1599 issue_enum = kConnectionDiagnosticsIssueServerNoNeighborEntry;
1600 } else if (issue ==
1601 ConnectionDiagnostics::kIssueGatewayNeighborEntryNotConnected) {
1602 issue_enum = kConnectionDiagnosticsIssueGatewayNeighborEntryNotConnected;
1603 } else if (issue ==
1604 ConnectionDiagnostics::kIssueServerNeighborEntryNotConnected) {
1605 issue_enum = kConnectionDiagnosticsIssueServerNeighborEntryNotConnected;
1606 } else {
1607 LOG(ERROR) << __func__ << ": Invalid issue: " << issue;
1608 return;
1609 }
1610
1611 SendEnumToUMA(kMetricConnectionDiagnosticsIssue, issue_enum,
1612 kConnectionDiagnosticsIssueMax);
1613 }
1614
InitializeCommonServiceMetrics(const Service & service)1615 void Metrics::InitializeCommonServiceMetrics(const Service& service) {
1616 Technology::Identifier technology = service.technology();
1617 string histogram = GetFullMetricName(kMetricTimeToConfigMillisecondsSuffix,
1618 technology);
1619 AddServiceStateTransitionTimer(
1620 service,
1621 histogram,
1622 Service::kStateConfiguring,
1623 Service::kStateConnected);
1624 histogram = GetFullMetricName(kMetricTimeToPortalMillisecondsSuffix,
1625 technology);
1626 AddServiceStateTransitionTimer(
1627 service,
1628 histogram,
1629 Service::kStateConnected,
1630 Service::kStatePortal);
1631 histogram = GetFullMetricName(kMetricTimeToOnlineMillisecondsSuffix,
1632 technology);
1633 AddServiceStateTransitionTimer(
1634 service,
1635 histogram,
1636 Service::kStateConnected,
1637 Service::kStateOnline);
1638 }
1639
UpdateServiceStateTransitionMetrics(ServiceMetrics * service_metrics,Service::ConnectState new_state)1640 void Metrics::UpdateServiceStateTransitionMetrics(
1641 ServiceMetrics* service_metrics,
1642 Service::ConnectState new_state) {
1643 const char* state_string = Service::ConnectStateToString(new_state);
1644 SLOG(this, 5) << __func__ << ": new_state=" << state_string;
1645 TimerReportersList& start_timers = service_metrics->start_on_state[new_state];
1646 for (auto& start_timer : start_timers) {
1647 SLOG(this, 5) << "Starting timer for " << start_timer->histogram_name()
1648 << " due to new state " << state_string << ".";
1649 start_timer->Start();
1650 }
1651
1652 TimerReportersList& stop_timers = service_metrics->stop_on_state[new_state];
1653 for (auto& stop_timer : stop_timers) {
1654 SLOG(this, 5) << "Stopping timer for " << stop_timer->histogram_name()
1655 << " due to new state " << state_string << ".";
1656 if (stop_timer->Stop())
1657 stop_timer->ReportMilliseconds();
1658 }
1659 }
1660
SendServiceFailure(const Service & service)1661 void Metrics::SendServiceFailure(const Service& service) {
1662 NetworkServiceError error = kNetworkServiceErrorUnknown;
1663 // Explicitly map all possible failures. So when new failures are added,
1664 // they will need to be mapped as well. Otherwise, the compiler will
1665 // complain.
1666 switch (service.failure()) {
1667 case Service::kFailureUnknown:
1668 case Service::kFailureMax:
1669 error = kNetworkServiceErrorUnknown;
1670 break;
1671 case Service::kFailureAAA:
1672 error = kNetworkServiceErrorAAA;
1673 break;
1674 case Service::kFailureActivation:
1675 error = kNetworkServiceErrorActivation;
1676 break;
1677 case Service::kFailureBadPassphrase:
1678 error = kNetworkServiceErrorBadPassphrase;
1679 break;
1680 case Service::kFailureBadWEPKey:
1681 error = kNetworkServiceErrorBadWEPKey;
1682 break;
1683 case Service::kFailureConnect:
1684 error = kNetworkServiceErrorConnect;
1685 break;
1686 case Service::kFailureDHCP:
1687 error = kNetworkServiceErrorDHCP;
1688 break;
1689 case Service::kFailureDNSLookup:
1690 error = kNetworkServiceErrorDNSLookup;
1691 break;
1692 case Service::kFailureEAPAuthentication:
1693 error = kNetworkServiceErrorEAPAuthentication;
1694 break;
1695 case Service::kFailureEAPLocalTLS:
1696 error = kNetworkServiceErrorEAPLocalTLS;
1697 break;
1698 case Service::kFailureEAPRemoteTLS:
1699 error = kNetworkServiceErrorEAPRemoteTLS;
1700 break;
1701 case Service::kFailureHTTPGet:
1702 error = kNetworkServiceErrorHTTPGet;
1703 break;
1704 case Service::kFailureIPSecCertAuth:
1705 error = kNetworkServiceErrorIPSecCertAuth;
1706 break;
1707 case Service::kFailureIPSecPSKAuth:
1708 error = kNetworkServiceErrorIPSecPSKAuth;
1709 break;
1710 case Service::kFailureInternal:
1711 error = kNetworkServiceErrorInternal;
1712 break;
1713 case Service::kFailureNeedEVDO:
1714 error = kNetworkServiceErrorNeedEVDO;
1715 break;
1716 case Service::kFailureNeedHomeNetwork:
1717 error = kNetworkServiceErrorNeedHomeNetwork;
1718 break;
1719 case Service::kFailureOTASP:
1720 error = kNetworkServiceErrorOTASP;
1721 break;
1722 case Service::kFailureOutOfRange:
1723 error = kNetworkServiceErrorOutOfRange;
1724 break;
1725 case Service::kFailurePPPAuth:
1726 error = kNetworkServiceErrorPPPAuth;
1727 break;
1728 case Service::kFailurePinMissing:
1729 error = kNetworkServiceErrorPinMissing;
1730 break;
1731 }
1732
1733 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
1734 error,
1735 kNetworkServiceErrorMax);
1736 }
1737
GetDeviceMetrics(int interface_index) const1738 Metrics::DeviceMetrics* Metrics::GetDeviceMetrics(int interface_index) const {
1739 DeviceMetricsLookupMap::const_iterator it =
1740 devices_metrics_.find(interface_index);
1741 if (it == devices_metrics_.end()) {
1742 SLOG(this, 2) << __func__ << ": device " << interface_index
1743 << " not found";
1744 return nullptr;
1745 }
1746 return it->second.get();
1747 }
1748
AutoConnectMetricsReset(DeviceMetrics * device_metrics)1749 void Metrics::AutoConnectMetricsReset(DeviceMetrics* device_metrics) {
1750 device_metrics->auto_connect_tries = 0;
1751 device_metrics->auto_connect_timer->Reset();
1752 }
1753
set_library(MetricsLibraryInterface * library)1754 void Metrics::set_library(MetricsLibraryInterface* library) {
1755 chromeos_metrics::TimerReporter::set_metrics_lib(library);
1756 library_ = library;
1757 }
1758
1759 } // namespace shill
1760