blob: 2c10a83309043a399184bbe3953d1da16ab1f93a [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;
Thieu Lead1ec2c2012-01-05 23:39:48 +000042const char Metrics::kMetricNetworkPhyMode[] = "Network.Shill.%s.PhyMode";
43const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
44const char Metrics::kMetricNetworkSecurity[] = "Network.Shill.%s.Security";
45const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
Thieu Le48e6d6d2011-12-06 00:40:27 +000046const char Metrics::kMetricNetworkServiceErrors[] =
47 "Network.Shill.ServiceErrors";
48const int Metrics::kMetricNetworkServiceErrorsMax = Service::kFailureMax;
Paul Stewart23b393a2012-09-25 21:21:06 -070049const char Metrics::kMetricNetworkSignalStrength[] =
50 "Network.Shill.%s.SignalStrength";
51const int Metrics::kMetricNetworkSignalStrengthMax = 200;
52const int Metrics::kMetricNetworkSignalStrengthMin = 0;
53const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
Thieu Lea20cbc22012-01-09 22:01:43 +000054
55const char Metrics::kMetricTimeOnlineSeconds[] = "Network.Shill.%s.TimeOnline";
56const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
57const int Metrics::kMetricTimeOnlineSecondsMin = 1;
58
Thieu Lecdb5a212013-01-25 11:17:18 -080059const char Metrics::kMetricTimeToConnectMilliseconds[] =
60 "Network.Shill.%s.TimeToConnect";
61const int Metrics::kMetricTimeToConnectMillisecondsMax =
62 60 * 1000; // 60 seconds
63const int Metrics::kMetricTimeToConnectMillisecondsMin = 1;
64const int Metrics::kMetricTimeToConnectMillisecondsNumBuckets = 60;
65
Thieu Lea20cbc22012-01-09 22:01:43 +000066const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
67const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
68const int Metrics::kMetricTimeToDropSecondsMin = 1;
69
Thieu Lea2519bf2013-01-23 16:51:54 -080070const char Metrics::kMetricTimeToDisableMilliseconds[] =
71 "Network.Shill.%s.TimeToDisable";
72const int Metrics::kMetricTimeToDisableMillisecondsMax =
73 60 * 1000; // 60 seconds
74const int Metrics::kMetricTimeToDisableMillisecondsMin = 1;
75const int Metrics::kMetricTimeToDisableMillisecondsNumBuckets = 60;
76
Thieu Lece4483e2013-01-23 15:12:03 -080077const char Metrics::kMetricTimeToEnableMilliseconds[] =
78 "Network.Shill.%s.TimeToEnable";
79const int Metrics::kMetricTimeToEnableMillisecondsMax =
80 60 * 1000; // 60 seconds
81const int Metrics::kMetricTimeToEnableMillisecondsMin = 1;
82const int Metrics::kMetricTimeToEnableMillisecondsNumBuckets = 60;
83
Thieu Lec8078a62013-01-22 18:01:12 -080084const char Metrics::kMetricTimeToInitializeMilliseconds[] =
85 "Network.Shill.%s.TimeToInitialize";
Thieu Le769d50d2013-01-23 17:11:59 -080086const int Metrics::kMetricTimeToInitializeMillisecondsMax =
87 30 * 1000; // 30 seconds
Thieu Lece4483e2013-01-23 15:12:03 -080088const int Metrics::kMetricTimeToInitializeMillisecondsMin = 1;
Thieu Le769d50d2013-01-23 17:11:59 -080089const int Metrics::kMetricTimeToInitializeMillisecondsNumBuckets = 30;
Thieu Lec8078a62013-01-22 18:01:12 -080090
Thieu Leb84ba342012-03-02 15:15:19 -080091const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
92 "Network.Shill.%s.TimeResumeToReady";
Thieu Le48e6d6d2011-12-06 00:40:27 +000093const char Metrics::kMetricTimeToConfigMilliseconds[] =
94 "Network.Shill.%s.TimeToConfig";
95const char Metrics::kMetricTimeToJoinMilliseconds[] =
96 "Network.Shill.%s.TimeToJoin";
97const char Metrics::kMetricTimeToOnlineMilliseconds[] =
98 "Network.Shill.%s.TimeToOnline";
99const char Metrics::kMetricTimeToPortalMilliseconds[] =
100 "Network.Shill.%s.TimeToPortal";
Thieu Le18c11072013-01-28 17:21:37 -0800101
102const char Metrics::kMetricTimeToScanMilliseconds[] =
103 "Network.Shill.%s.TimeToScan";
104const int Metrics::kMetricTimeToScanMillisecondsMax = 180 * 1000; // 3 minutes
105const int Metrics::kMetricTimeToScanMillisecondsMin = 1;
106const int Metrics::kMetricTimeToScanMillisecondsNumBuckets = 90;
107
Thieu Lea20cbc22012-01-09 22:01:43 +0000108const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
109const int Metrics::kTimerHistogramMillisecondsMin = 1;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000110const int Metrics::kTimerHistogramNumBuckets = 50;
111
Thieu Le85e050b2012-03-13 15:04:38 -0700112const char Metrics::kMetricPortalAttempts[] =
113 "Network.Shill.%s.PortalAttempts";
114const int Metrics::kMetricPortalAttemptsMax =
115 PortalDetector::kMaxRequestAttempts;
116const int Metrics::kMetricPortalAttemptsMin = 1;
117const int Metrics::kMetricPortalAttemptsNumBuckets =
118 Metrics::kMetricPortalAttemptsMax;
119
120const char Metrics::kMetricPortalAttemptsToOnline[] =
121 "Network.Shill.%s.PortalAttemptsToOnline";
122const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
123const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
124const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
125
126const char Metrics::kMetricPortalResult[] = "Network.Shill.%s.PortalResult";
127
Arman Ugurayab22c162012-10-08 19:08:38 -0700128const char Metrics::kMetricTerminationActionTimeOnTerminate[] =
129 "Network.Shill.TerminationActionTime.OnTerminate";
130const char Metrics::kMetricTerminationActionResultOnTerminate[] =
131 "Network.Shill.TerminationActionResult.OnTerminate";
132const char Metrics::kMetricTerminationActionTimeOnSuspend[] =
133 "Network.Shill.TerminationActionTime.OnSuspend";
134const char Metrics::kMetricTerminationActionResultOnSuspend[] =
135 "Network.Shill.TerminationActionResult.OnSuspend";
136const int Metrics::kMetricTerminationActionTimeMillisecondsMax = 10000;
137const int Metrics::kMetricTerminationActionTimeMillisecondsMin = 1;
Arman Uguray6d528f12012-09-13 13:44:55 -0700138
Thieu Le48e6d6d2011-12-06 00:40:27 +0000139// static
Paul Stewart85aea152013-01-22 09:31:56 -0800140const char Metrics::kMetricServiceFixupEntries[] =
141 "Network.Shill.%s.ServiceFixupEntries";
142
143// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000144const uint16 Metrics::kWiFiBandwidth5MHz = 5;
145const uint16 Metrics::kWiFiBandwidth20MHz = 20;
146const uint16 Metrics::kWiFiFrequency2412 = 2412;
147const uint16 Metrics::kWiFiFrequency2472 = 2472;
148const uint16 Metrics::kWiFiFrequency2484 = 2484;
149const uint16 Metrics::kWiFiFrequency5170 = 5170;
150const uint16 Metrics::kWiFiFrequency5180 = 5180;
151const uint16 Metrics::kWiFiFrequency5230 = 5230;
152const uint16 Metrics::kWiFiFrequency5240 = 5240;
153const uint16 Metrics::kWiFiFrequency5320 = 5320;
154const uint16 Metrics::kWiFiFrequency5500 = 5500;
155const uint16 Metrics::kWiFiFrequency5700 = 5700;
156const uint16 Metrics::kWiFiFrequency5745 = 5745;
157const uint16 Metrics::kWiFiFrequency5825 = 5825;
158
Thieu Leb84ba342012-03-02 15:15:19 -0800159// static
160const char Metrics::kMetricPowerManagerKey[] = "metrics";
161
Paul Stewartff845fc2012-08-07 07:28:44 -0700162// static
163const char Metrics::kMetricLinkMonitorFailure[] =
164 "Network.Shill.%s.LinkMonitorFailure";
165const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
166 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewartf1961f82012-09-11 20:45:39 -0700167const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
168const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700169 LinkMonitor::kTestPeriodMilliseconds;
170const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700171const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
172 "Network.Shill.%s.LinkMonitorSecondsToFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700173const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
174const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
Paul Stewart0443aa52012-08-09 10:43:50 -0700175const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
176const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
177 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
178const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
179 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700180const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
181const int Metrics::kMetricLinkMonitorErrorCountMax =
Paul Stewart0443aa52012-08-09 10:43:50 -0700182 LinkMonitor::kFailureThreshold;
183const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
184 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700185
Wade Guthried4977f22012-08-22 12:37:54 -0700186// static
187const char Metrics::kMetricLinkClientDisconnectReason[] =
188 "Network.Shill.WiFi.ClientDisconnectReason";
189const char Metrics::kMetricLinkApDisconnectReason[] =
190 "Network.Shill.WiFi.ApDisconnectReason";
191const char Metrics::kMetricLinkClientDisconnectType[] =
192 "Network.Shill.WiFi.ClientDisconnectType";
193const char Metrics::kMetricLinkApDisconnectType[] =
194 "Network.Shill.WiFi.ApDisconnectType";
195
Thieu Le26fc01b2013-01-28 12:08:48 -0800196// static
197const char Metrics::kMetricCellularDrop[] =
198 "Network.Shill.Cellular.Drop";
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800199const char Metrics::kMetricCellularDropsPerHour[] =
200 "Network.Shill.Cellular.DropsPerHour";
201const int Metrics::kMetricCellularDropsPerHourMax = 60;
202const int Metrics::kMetricCellularDropsPerHourMin = 1;
203const int Metrics::kMetricCellularDropsPerHourNumBuckets = 10;
Thieu Leb7aa5f72013-01-31 15:57:48 -0800204// The format of FailureReason is different to other metrics because this
205// name is prepended to the error message before the entire string is sent
206// via SendUserActionToUMA.
207const char Metrics::kMetricCellularFailureReason[] =
208 "Network.Shill.Cellular.FailureReason: ";
Thieu Le26fc01b2013-01-28 12:08:48 -0800209const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
210 "Network.Shill.Cellular.SignalStrengthBeforeDrop";
211const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
212const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
213const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
Thieu Le7cf36b02013-01-30 17:15:56 -0800214const char Metrics::kMetricCellularAutoConnectTries[] =
215 "Network.Shill.Cellular.AutoConnectTries";
216const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
217const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
218const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
219const char Metrics::kMetricCellularAutoConnectTotalTime[] =
220 "Network.Shill.Cellular.AutoConnectTotalTime";
221const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
222 60 * 1000; // 60 seconds
223const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
224const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
Thieu Le26fc01b2013-01-28 12:08:48 -0800225
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800226// static
227const int Metrics::kHourlyTimeoutMilliseconds = 3600 * 1000; // One hour
Wade Guthried4977f22012-08-22 12:37:54 -0700228
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800229
230Metrics::Metrics(EventDispatcher *dispatcher)
231 : dispatcher_(dispatcher),
232 library_(&metrics_library_),
Thieu Lea20cbc22012-01-09 22:01:43 +0000233 last_default_technology_(Technology::kUnknown),
234 was_online_(false),
235 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800236 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200237 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
Arman Ugurayab22c162012-10-08 19:08:38 -0700238 time_termination_actions_timer(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200239 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000240 metrics_library_.Init();
241 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
242}
243
244Metrics::~Metrics() {}
245
246// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000247Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
248 WiFiChannel channel = kWiFiChannelUndef;
249 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
250 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
251 channel = static_cast<WiFiChannel>(
252 kWiFiChannel2412 +
253 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
254 } else if (frequency == kWiFiFrequency2484) {
255 channel = kWiFiChannel2484;
256 } else if (kWiFiFrequency5170 <= frequency &&
257 frequency <= kWiFiFrequency5230) {
258 if ((frequency % kWiFiBandwidth20MHz) == 0)
259 channel = static_cast<WiFiChannel>(
260 kWiFiChannel5180 +
261 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
262 if ((frequency % kWiFiBandwidth20MHz) == 10)
263 channel = static_cast<WiFiChannel>(
264 kWiFiChannel5170 +
265 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
266 } else if (kWiFiFrequency5240 <= frequency &&
267 frequency <= kWiFiFrequency5320) {
268 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
269 channel = static_cast<WiFiChannel>(
270 kWiFiChannel5180 +
271 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
272 } else if (kWiFiFrequency5500 <= frequency &&
273 frequency <= kWiFiFrequency5700) {
274 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
275 channel = static_cast<WiFiChannel>(
276 kWiFiChannel5500 +
277 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
278 } else if (kWiFiFrequency5745 <= frequency &&
279 frequency <= kWiFiFrequency5825) {
280 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
281 channel = static_cast<WiFiChannel>(
282 kWiFiChannel5745 +
283 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
284 }
285 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
286
287 if (channel == kWiFiChannelUndef)
288 LOG(WARNING) << "no mapping for frequency " << frequency;
289 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700290 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000291
292 return channel;
293}
294
Thieu Lead1ec2c2012-01-05 23:39:48 +0000295// static
296Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
297 const std::string &security) {
298 if (security == flimflam::kSecurityNone) {
299 return kWiFiSecurityNone;
300 } else if (security == flimflam::kSecurityWep) {
301 return kWiFiSecurityWep;
302 } else if (security == flimflam::kSecurityWpa) {
303 return kWiFiSecurityWpa;
304 } else if (security == flimflam::kSecurityRsn) {
305 return kWiFiSecurityRsn;
306 } else if (security == flimflam::kSecurity8021x) {
307 return kWiFiSecurity8021x;
308 } else if (security == flimflam::kSecurityPsk) {
309 return kWiFiSecurityPsk;
310 } else {
311 return kWiFiSecurityUnknown;
312 }
313}
314
Thieu Le85e050b2012-03-13 15:04:38 -0700315// static
316Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
317 const PortalDetector::Result &result) {
318 DCHECK(result.final);
319 PortalResult retval = kPortalResultUnknown;
320 // The only time we should end a successful portal detection is when we're
321 // in the Content phase. If we end with kStatusSuccess in any other phase,
322 // then this indicates that something bad has happened.
323 switch (result.phase) {
324 case PortalDetector::kPhaseDNS:
325 if (result.status == PortalDetector::kStatusFailure)
326 retval = kPortalResultDNSFailure;
327 else if (result.status == PortalDetector::kStatusTimeout)
328 retval = kPortalResultDNSTimeout;
329 else
330 LOG(DFATAL) << __func__ << ": Final result status " << result.status
331 << " is not allowed in the DNS phase";
332 break;
333
334 case PortalDetector::kPhaseConnection:
335 if (result.status == PortalDetector::kStatusFailure)
336 retval = kPortalResultConnectionFailure;
337 else if (result.status == PortalDetector::kStatusTimeout)
338 retval = kPortalResultConnectionTimeout;
339 else
340 LOG(DFATAL) << __func__ << ": Final result status " << result.status
341 << " is not allowed in the Connection phase";
342 break;
343
344 case PortalDetector::kPhaseHTTP:
345 if (result.status == PortalDetector::kStatusFailure)
346 retval = kPortalResultHTTPFailure;
347 else if (result.status == PortalDetector::kStatusTimeout)
348 retval = kPortalResultHTTPTimeout;
349 else
350 LOG(DFATAL) << __func__ << ": Final result status " << result.status
351 << " is not allowed in the HTTP phase";
352 break;
353
354 case PortalDetector::kPhaseContent:
355 if (result.status == PortalDetector::kStatusSuccess)
356 retval = kPortalResultSuccess;
357 else if (result.status == PortalDetector::kStatusFailure)
358 retval = kPortalResultContentFailure;
359 else if (result.status == PortalDetector::kStatusTimeout)
360 retval = kPortalResultContentTimeout;
361 else
362 LOG(DFATAL) << __func__ << ": Final result status " << result.status
363 << " is not allowed in the Content phase";
364 break;
365
366 case PortalDetector::kPhaseUnknown:
367 retval = kPortalResultUnknown;
368 break;
369
370 default:
371 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
372 break;
373 }
374
375 return retval;
376}
377
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800378void Metrics::Start() {
379 SLOG(Metrics, 2) << __func__;
380 hourly_timeout_handler_.Reset(
381 Bind(&Metrics::HourlyTimeoutHandler, Unretained(this)));
382 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
383 kHourlyTimeoutMilliseconds);
384}
385
386void Metrics::Stop() {
387 SLOG(Metrics, 2) << __func__;
388 hourly_timeout_handler_.Cancel();
389}
390
Thieu Le48e6d6d2011-12-06 00:40:27 +0000391void Metrics::RegisterService(const Service *service) {
392 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
393 services_metrics_[service] = service_metrics;
394 service_metrics->service = service;
395 InitializeCommonServiceMetrics(service);
396 service->InitializeCustomMetrics();
397}
398
399void Metrics::DeregisterService(const Service *service) {
400 services_metrics_.erase(service);
401}
402
403void Metrics::AddServiceStateTransitionTimer(
404 const Service *service,
405 const string &histogram_name,
406 Service::ConnectState start_state,
407 Service::ConnectState stop_state) {
408 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
409 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700410 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000411 DCHECK(false);
412 return;
413 }
414 ServiceMetrics *service_metrics = it->second.get();
415 CHECK(start_state < stop_state);
416 chromeos_metrics::TimerReporter *timer =
417 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000418 kTimerHistogramMillisecondsMin,
419 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000420 kTimerHistogramNumBuckets);
421 service_metrics->timers.push_back(timer); // passes ownership.
422 service_metrics->start_on_state[start_state].push_back(timer);
423 service_metrics->stop_on_state[stop_state].push_back(timer);
424}
425
Thieu Lea20cbc22012-01-09 22:01:43 +0000426void Metrics::NotifyDefaultServiceChanged(const Service *service) {
427 base::TimeDelta elapsed_seconds;
428
429 Technology::Identifier technology = (service) ? service->technology() :
430 Technology::kUnknown;
431 if (technology != last_default_technology_) {
432 if (last_default_technology_ != Technology::kUnknown) {
433 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
434 last_default_technology_);
435 time_online_timer_->GetElapsedTime(&elapsed_seconds);
436 SendToUMA(histogram,
437 elapsed_seconds.InSeconds(),
438 kMetricTimeOnlineSecondsMin,
439 kMetricTimeOnlineSecondsMax,
440 kTimerHistogramNumBuckets);
441 }
442 last_default_technology_ = technology;
443 time_online_timer_->Start();
444 }
445
Thieu Lea20cbc22012-01-09 22:01:43 +0000446 // Ignore changes that are not online/offline transitions; e.g.
447 // switching between wired and wireless. TimeToDrop measures
448 // time online regardless of how we are connected.
449 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
450 return;
451
452 if (service == NULL) {
453 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
454 SendToUMA(kMetricTimeToDropSeconds,
455 elapsed_seconds.InSeconds(),
456 kMetricTimeToDropSecondsMin,
457 kMetricTimeToDropSecondsMax,
458 kTimerHistogramNumBuckets);
459 } else {
460 time_to_drop_timer_->Start();
461 }
462
463 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000464}
465
466void Metrics::NotifyServiceStateChanged(const Service *service,
467 Service::ConnectState new_state) {
468 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
469 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700470 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000471 DCHECK(false);
472 return;
473 }
474 ServiceMetrics *service_metrics = it->second.get();
475 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
476
477 if (new_state == Service::kStateFailure)
478 SendServiceFailure(service);
479
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200480 if (collect_bootstats_) {
481 bootstat_log(
482 StringPrintf("network-%s-%s",
483 Technology::NameFromIdentifier(
484 service->technology()).c_str(),
485 service->GetStateString().c_str()).c_str());
486 }
487
Paul Stewart20088d82012-02-16 06:58:55 -0800488 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000489 return;
490
Thieu Leb84ba342012-03-02 15:15:19 -0800491 base::TimeDelta time_resume_to_ready;
492 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
493 time_resume_to_ready_timer_->Reset();
494 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000495}
496
497string Metrics::GetFullMetricName(const char *metric_name,
498 Technology::Identifier technology_id) {
499 string technology = Technology::NameFromIdentifier(technology_id);
500 technology[0] = base::ToUpperASCII(technology[0]);
501 return base::StringPrintf(metric_name, technology.c_str());
502}
503
Thieu Le67370f62012-02-14 23:01:42 +0000504void Metrics::NotifyServiceDisconnect(const Service *service) {
505 Technology::Identifier technology = service->technology();
506 string histogram = GetFullMetricName(kMetricDisconnect, technology);
507 SendToUMA(histogram,
508 service->explicitly_disconnected(),
509 kMetricDisconnectMin,
510 kMetricDisconnectMax,
511 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000512}
513
Thieu Leb84ba342012-03-02 15:15:19 -0800514void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
515 if (new_state == PowerManagerProxyDelegate::kOn) {
516 time_resume_to_ready_timer_->Start();
517 } else {
518 time_resume_to_ready_timer_->Reset();
519 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000520}
521
Arman Ugurayab22c162012-10-08 19:08:38 -0700522void Metrics::NotifyTerminationActionsStarted(
523 TerminationActionReason /*reason*/) {
524 if (time_termination_actions_timer->HasStarted())
525 return;
526 time_termination_actions_timer->Start();
527}
528
529void Metrics::NotifyTerminationActionsCompleted(
530 TerminationActionReason reason, bool success) {
531 if (!time_termination_actions_timer->HasStarted())
532 return;
533
534 int result = success ? kTerminationActionResultSuccess :
535 kTerminationActionResultFailure;
536
537 base::TimeDelta elapsed_time;
538 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
539 time_termination_actions_timer->Reset();
540 string time_metric, result_metric;
541 switch (reason) {
542 case kTerminationActionReasonSuspend:
543 time_metric = kMetricTerminationActionTimeOnSuspend;
544 result_metric = kMetricTerminationActionResultOnSuspend;
545 break;
546 case kTerminationActionReasonTerminate:
547 time_metric = kMetricTerminationActionTimeOnTerminate;
548 result_metric = kMetricTerminationActionResultOnTerminate;
549 break;
550 }
551
552 SendToUMA(time_metric,
553 elapsed_time.InMilliseconds(),
554 kMetricTerminationActionTimeMillisecondsMin,
555 kMetricTerminationActionTimeMillisecondsMax,
556 kTimerHistogramNumBuckets);
557
558 SendEnumToUMA(result_metric,
559 result,
560 kTerminationActionResultMax);
561}
562
Paul Stewartff845fc2012-08-07 07:28:44 -0700563void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700564 Technology::Identifier technology,
565 LinkMonitorFailure failure,
Paul Stewartf1961f82012-09-11 20:45:39 -0700566 int seconds_to_failure,
567 int broadcast_error_count,
568 int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700569 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
570 technology);
571 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700572
573 if (failure == kLinkMonitorFailureThresholdReached) {
574 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
575 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
576 }
577 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
578 technology);
579 SendToUMA(histogram,
580 seconds_to_failure,
581 kMetricLinkMonitorSecondsToFailureMin,
582 kMetricLinkMonitorSecondsToFailureMax,
583 kMetricLinkMonitorSecondsToFailureNumBuckets);
584 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
585 technology);
586 SendToUMA(histogram,
587 broadcast_error_count,
588 kMetricLinkMonitorErrorCountMin,
589 kMetricLinkMonitorErrorCountMax,
590 kMetricLinkMonitorErrorCountNumBuckets);
591 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
592 technology);
593 SendToUMA(histogram,
594 unicast_error_count,
595 kMetricLinkMonitorErrorCountMin,
596 kMetricLinkMonitorErrorCountMax,
597 kMetricLinkMonitorErrorCountNumBuckets);
598 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700599}
600
601void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
602 Technology::Identifier technology,
Paul Stewartf1961f82012-09-11 20:45:39 -0700603 int response_time_milliseconds) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700604 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
605 technology);
606 SendToUMA(histogram,
607 response_time_milliseconds,
608 kMetricLinkMonitorResponseTimeSampleMin,
609 kMetricLinkMonitorResponseTimeSampleMax,
610 kMetricLinkMonitorResponseTimeSampleNumBuckets);
611}
612
Wade Guthried4977f22012-08-22 12:37:54 -0700613void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
614 IEEE_80211::WiFiReasonCode reason) {
615 string metric_disconnect_reason;
616 string metric_disconnect_type;
617 WiFiStatusType type;
618
619 if (by_whom == kDisconnectedByAp) {
620 metric_disconnect_reason = kMetricLinkApDisconnectReason;
621 metric_disconnect_type = kMetricLinkApDisconnectType;
622 type = kStatusCodeTypeByAp;
623 } else {
624 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
625 metric_disconnect_type = kMetricLinkClientDisconnectType;
626 switch(reason) {
627 case IEEE_80211::kReasonCodeSenderHasLeft:
628 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
629 type = kStatusCodeTypeByUser;
630 break;
631
632 case IEEE_80211::kReasonCodeInactivity:
633 type = kStatusCodeTypeConsideredDead;
634 break;
635
636 default:
637 type = kStatusCodeTypeByClient;
638 break;
639 }
640 }
641 SendEnumToUMA(metric_disconnect_reason, reason,
642 IEEE_80211::kStatusCodeMax);
643 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
644}
645
Thieu Lec8078a62013-01-22 18:01:12 -0800646void Metrics::RegisterDevice(int interface_index,
647 Technology::Identifier technology) {
Thieu Le9abd6742013-01-23 23:35:37 -0800648 SLOG(Metrics, 2) << __func__ << ": " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800649 shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
650 devices_metrics_[interface_index] = device_metrics;
Thieu Le9abd6742013-01-23 23:35:37 -0800651 device_metrics->technology = technology;
Thieu Lec8078a62013-01-22 18:01:12 -0800652 string histogram = GetFullMetricName(kMetricTimeToInitializeMilliseconds,
653 technology);
654 device_metrics->initialization_timer.reset(
655 new chromeos_metrics::TimerReporter(
656 histogram,
657 kMetricTimeToInitializeMillisecondsMin,
658 kMetricTimeToInitializeMillisecondsMax,
659 kMetricTimeToInitializeMillisecondsNumBuckets));
660 device_metrics->initialization_timer->Start();
Thieu Lece4483e2013-01-23 15:12:03 -0800661 histogram = GetFullMetricName(kMetricTimeToEnableMilliseconds,
662 technology);
663 device_metrics->enable_timer.reset(
664 new chromeos_metrics::TimerReporter(
665 histogram,
666 kMetricTimeToEnableMillisecondsMin,
667 kMetricTimeToEnableMillisecondsMax,
668 kMetricTimeToEnableMillisecondsNumBuckets));
Thieu Lea2519bf2013-01-23 16:51:54 -0800669 histogram = GetFullMetricName(kMetricTimeToDisableMilliseconds,
670 technology);
671 device_metrics->disable_timer.reset(
672 new chromeos_metrics::TimerReporter(
673 histogram,
674 kMetricTimeToDisableMillisecondsMin,
675 kMetricTimeToDisableMillisecondsMax,
676 kMetricTimeToDisableMillisecondsNumBuckets));
Thieu Le18c11072013-01-28 17:21:37 -0800677 histogram = GetFullMetricName(kMetricTimeToScanMilliseconds,
678 technology);
679 device_metrics->scan_timer.reset(
680 new chromeos_metrics::TimerReporter(
681 histogram,
682 kMetricTimeToScanMillisecondsMin,
683 kMetricTimeToScanMillisecondsMax,
684 kMetricTimeToScanMillisecondsNumBuckets));
Thieu Lecdb5a212013-01-25 11:17:18 -0800685 histogram = GetFullMetricName(kMetricTimeToConnectMilliseconds,
686 technology);
687 device_metrics->connect_timer.reset(
688 new chromeos_metrics::TimerReporter(
689 histogram,
690 kMetricTimeToConnectMillisecondsMin,
691 kMetricTimeToConnectMillisecondsMax,
692 kMetricTimeToConnectMillisecondsNumBuckets));
Thieu Le7cf36b02013-01-30 17:15:56 -0800693 device_metrics->auto_connect_timer.reset(
694 new chromeos_metrics::TimerReporter(
695 kMetricCellularAutoConnectTotalTime,
696 kMetricCellularAutoConnectTotalTimeMin,
697 kMetricCellularAutoConnectTotalTimeMax,
698 kMetricCellularAutoConnectTotalTimeNumBuckets));
Thieu Lec8078a62013-01-22 18:01:12 -0800699}
700
Thieu Le9abd6742013-01-23 23:35:37 -0800701bool Metrics::IsDeviceRegistered(int interface_index,
702 Technology::Identifier technology) {
703 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index
704 << ", technology: " << technology;
705 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
706 if (device_metrics == NULL)
707 return false;
708 // Make sure the device technologies match.
709 return (technology == device_metrics->technology);
710}
711
Thieu Lec8078a62013-01-22 18:01:12 -0800712void Metrics::DeregisterDevice(int interface_index) {
Thieu Le9abd6742013-01-23 23:35:37 -0800713 SLOG(Metrics, 2) << __func__ << ": interface index: " << interface_index;
Thieu Lec8078a62013-01-22 18:01:12 -0800714 devices_metrics_.erase(interface_index);
715}
716
717void Metrics::NotifyDeviceInitialized(int interface_index) {
Thieu Lece4483e2013-01-23 15:12:03 -0800718 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
719 if (device_metrics == NULL)
Thieu Lec8078a62013-01-22 18:01:12 -0800720 return;
Thieu Lec8078a62013-01-22 18:01:12 -0800721 device_metrics->initialization_timer->Stop();
722 device_metrics->initialization_timer->ReportMilliseconds();
723}
724
Thieu Lece4483e2013-01-23 15:12:03 -0800725void Metrics::NotifyDeviceEnableStarted(int interface_index) {
726 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
727 if (device_metrics == NULL)
728 return;
729 device_metrics->enable_timer->Start();
730}
731
732void Metrics::NotifyDeviceEnableFinished(int interface_index) {
733 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
734 if (device_metrics == NULL)
735 return;
736 device_metrics->enable_timer->Stop();
737 device_metrics->enable_timer->ReportMilliseconds();
738}
739
Thieu Lea2519bf2013-01-23 16:51:54 -0800740void Metrics::NotifyDeviceDisableStarted(int interface_index) {
741 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
742 if (device_metrics == NULL)
743 return;
744 device_metrics->disable_timer->Start();
745}
746
747void Metrics::NotifyDeviceDisableFinished(int interface_index) {
748 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
749 if (device_metrics == NULL)
750 return;
751 device_metrics->disable_timer->Stop();
752 device_metrics->disable_timer->ReportMilliseconds();
753}
754
Thieu Le18c11072013-01-28 17:21:37 -0800755void Metrics::NotifyDeviceScanStarted(int interface_index) {
756 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
757 if (device_metrics == NULL)
758 return;
759 // This metric is only supported for cellular devices.
760 if (device_metrics->technology != Technology::kCellular)
761 return;
762 device_metrics->scan_timer->Start();
763}
764
765void Metrics::NotifyDeviceScanFinished(int interface_index) {
766 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
767 if (device_metrics == NULL)
768 return;
769 // This metric is only supported for cellular devices.
770 if (device_metrics->technology != Technology::kCellular)
771 return;
772 device_metrics->scan_timer->Stop();
773 // Don't send TimeToScan metrics if the elapsed time exceeds the max
774 // metrics value. This usually means that the modem is in an area
775 // without service and we're not interested in this scenario.
776 base::TimeDelta elapsed_time;
777 device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
778 if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
779 device_metrics->scan_timer->ReportMilliseconds();
780}
781
Thieu Le7cf36b02013-01-30 17:15:56 -0800782void Metrics::NotifyDeviceConnectStarted(int interface_index,
783 bool is_auto_connecting) {
Thieu Lecdb5a212013-01-25 11:17:18 -0800784 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
785 if (device_metrics == NULL)
786 return;
787 device_metrics->connect_timer->Start();
Thieu Le7cf36b02013-01-30 17:15:56 -0800788
789 if (is_auto_connecting) {
790 device_metrics->auto_connect_tries++;
791 if (device_metrics->auto_connect_tries == 1)
792 device_metrics->auto_connect_timer->Start();
793 } else {
794 AutoConnectMetricsReset(device_metrics);
795 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800796}
797
798void Metrics::NotifyDeviceConnectFinished(int interface_index) {
799 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
800 if (device_metrics == NULL)
801 return;
802 device_metrics->connect_timer->Stop();
803 device_metrics->connect_timer->ReportMilliseconds();
Thieu Le7cf36b02013-01-30 17:15:56 -0800804
805 if (device_metrics->auto_connect_tries > 0) {
806 device_metrics->auto_connect_timer->Stop();
807 base::TimeDelta elapsed_time;
808 device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
809 if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
810 return;
811 device_metrics->auto_connect_timer->ReportMilliseconds();
812 SendToUMA(kMetricCellularAutoConnectTries,
813 device_metrics->auto_connect_tries,
814 kMetricCellularAutoConnectTriesMin,
815 kMetricCellularAutoConnectTriesMax,
816 kMetricCellularAutoConnectTriesNumBuckets);
817 AutoConnectMetricsReset(device_metrics);
818 }
Thieu Lecdb5a212013-01-25 11:17:18 -0800819}
820
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800821void Metrics::NotifyCellularDeviceDrop(int interface_index,
822 const string &network_technology,
Thieu Le26fc01b2013-01-28 12:08:48 -0800823 uint16 signal_strength) {
824 SLOG(Metrics, 2) << __func__ << ": " << network_technology
825 << ", " << signal_strength;
826 CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
827 if (network_technology == flimflam::kNetworkTechnology1Xrtt) {
828 drop_technology = kCellularDropTechnology1Xrtt;
829 } else if (network_technology == flimflam::kNetworkTechnologyEdge) {
830 drop_technology = kCellularDropTechnologyEdge;
831 } else if (network_technology == flimflam::kNetworkTechnologyEvdo) {
832 drop_technology = kCellularDropTechnologyEvdo;
833 } else if (network_technology == flimflam::kNetworkTechnologyGprs) {
834 drop_technology = kCellularDropTechnologyGprs;
835 } else if (network_technology == flimflam::kNetworkTechnologyGsm) {
836 drop_technology = kCellularDropTechnologyGsm;
837 } else if (network_technology == flimflam::kNetworkTechnologyHspa) {
838 drop_technology = kCellularDropTechnologyHspa;
839 } else if (network_technology == flimflam::kNetworkTechnologyHspaPlus) {
840 drop_technology = kCellularDropTechnologyHspaPlus;
841 } else if (network_technology == flimflam::kNetworkTechnologyLte) {
842 drop_technology = kCellularDropTechnologyLte;
843 } else if (network_technology == flimflam::kNetworkTechnologyUmts) {
844 drop_technology = kCellularDropTechnologyUmts;
845 }
846 SendEnumToUMA(kMetricCellularDrop,
847 drop_technology,
848 kCellularDropTechnologyMax);
849 SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
850 signal_strength,
851 kMetricCellularSignalStrengthBeforeDropMin,
852 kMetricCellularSignalStrengthBeforeDropMax,
853 kMetricCellularSignalStrengthBeforeDropNumBuckets);
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800854
855 DeviceMetrics *device_metrics = GetDeviceMetrics(interface_index);
856 if (device_metrics == NULL)
857 return;
858 device_metrics->num_drops++;
Thieu Le26fc01b2013-01-28 12:08:48 -0800859}
860
Thieu Leb7aa5f72013-01-31 15:57:48 -0800861void Metrics::NotifyCellularDeviceFailure(const Error &error) {
862 library_->SendUserActionToUMA(
863 kMetricCellularFailureReason + error.message());
864}
865
Thieu Le48e6d6d2011-12-06 00:40:27 +0000866bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
867 return library_->SendEnumToUMA(name, sample, max);
868}
869
Thieu Lea20cbc22012-01-09 22:01:43 +0000870bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
871 int num_buckets) {
872 return library_->SendToUMA(name, sample, min, max, num_buckets);
873}
874
Thieu Le48e6d6d2011-12-06 00:40:27 +0000875void Metrics::InitializeCommonServiceMetrics(const Service *service) {
876 Technology::Identifier technology = service->technology();
877 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
878 technology);
879 AddServiceStateTransitionTimer(
880 service,
881 histogram,
882 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800883 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000884 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
885 AddServiceStateTransitionTimer(
886 service,
887 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800888 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000889 Service::kStatePortal);
890 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
891 AddServiceStateTransitionTimer(
892 service,
893 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800894 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000895 Service::kStateOnline);
896}
897
898void Metrics::UpdateServiceStateTransitionMetrics(
899 ServiceMetrics *service_metrics,
900 Service::ConnectState new_state) {
901 TimerReportersList::iterator it;
902 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
903 for (it = start_timers.begin(); it != start_timers.end(); ++it)
904 (*it)->Start();
905
906 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
907 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
908 (*it)->Stop();
909 (*it)->ReportMilliseconds();
910 }
911}
912
913void Metrics::SendServiceFailure(const Service *service) {
914 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
915 service->failure(),
916 kMetricNetworkServiceErrorsMax);
917}
918
Thieu Le9abd6742013-01-23 23:35:37 -0800919Metrics::DeviceMetrics *Metrics::GetDeviceMetrics(int interface_index) const {
920 DeviceMetricsLookupMap::const_iterator it =
921 devices_metrics_.find(interface_index);
Thieu Lece4483e2013-01-23 15:12:03 -0800922 if (it == devices_metrics_.end()) {
Thieu Le9abd6742013-01-23 23:35:37 -0800923 SLOG(Metrics, 2) << __func__ << ": device " << interface_index
924 << " not found";
Thieu Lece4483e2013-01-23 15:12:03 -0800925 return NULL;
926 }
927 return it->second.get();
928}
929
Thieu Le7cf36b02013-01-30 17:15:56 -0800930void Metrics::AutoConnectMetricsReset(DeviceMetrics *device_metrics) {
931 device_metrics->auto_connect_tries = 0;
932 device_metrics->auto_connect_timer->Reset();
933}
934
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800935void Metrics::HourlyTimeoutHandler() {
936 SLOG(Metrics, 2) << __func__;
937 DeviceMetricsLookupMap::iterator it;
938 for (it = devices_metrics_.begin(); it != devices_metrics_.end(); ++it) {
939 if (it->second->technology != Technology::kCellular ||
940 it->second->num_drops == 0)
941 continue;
942 SendToUMA(kMetricCellularDropsPerHour,
943 it->second->num_drops,
944 kMetricCellularDropsPerHourMin,
945 kMetricCellularDropsPerHourMax,
946 kMetricCellularDropsPerHourNumBuckets);
947 it->second->num_drops = 0;
948 }
949 dispatcher_->PostDelayedTask(hourly_timeout_handler_.callback(),
950 kHourlyTimeoutMilliseconds);
951}
952
Thieu Le48e6d6d2011-12-06 00:40:27 +0000953void Metrics::set_library(MetricsLibraryInterface *library) {
954 chromeos_metrics::TimerReporter::set_metrics_lib(library);
955 library_ = library;
956}
957
958} // namespace shill