blob: 2d5972020738fb483c155bb2a8b3d1849ff0c113 [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 Le48e6d6d2011-12-06 00:40:27 +00007#include <base/string_util.h>
8#include <base/stringprintf.h>
Thieu Lead1ec2c2012-01-05 23:39:48 +00009#include <chromeos/dbus/service_constants.h>
Darin Petkov58f0b6d2012-06-12 12:52:30 +020010#include <metrics/bootstat.h>
Thieu Le48e6d6d2011-12-06 00:40:27 +000011
Wade Guthried4977f22012-08-22 12:37:54 -070012#include "shill/ieee80211.h"
Paul Stewartff845fc2012-08-07 07:28:44 -070013#include "shill/link_monitor.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070014#include "shill/logging.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000015#include "shill/wifi_service.h"
16
17using std::string;
18using std::tr1::shared_ptr;
19
20namespace shill {
21
Thieu Le48e6d6d2011-12-06 00:40:27 +000022// static
Thieu Lec31e6f92012-08-03 13:08:58 -070023// Our disconnect enumeration values are 0 (System Disconnect) and
24// 1 (User Disconnect), see histograms.xml, but Chrome needs a minimum
25// enum value of 1 and the minimum number of buckets needs to be 3 (see
26// histogram.h). Instead of remapping System Disconnect to 1 and
27// User Disconnect to 2, we can just leave the enumerated values as-is
28// because Chrome implicitly creates a [0-1) bucket for us. Using Min=1,
29// Max=2 and NumBuckets=3 gives us the following three buckets:
30// [0-1), [1-2), [2-INT_MAX). We end up with an extra bucket [2-INT_MAX)
31// that we can safely ignore.
Thieu Le67370f62012-02-14 23:01:42 +000032const char Metrics::kMetricDisconnect[] = "Network.Shill.%s.Disconnect";
Thieu Lec31e6f92012-08-03 13:08:58 -070033const int Metrics::kMetricDisconnectMax = 2;
34const int Metrics::kMetricDisconnectMin = 1;
35const int Metrics::kMetricDisconnectNumBuckets = 3;
Thieu Le67370f62012-02-14 23:01:42 +000036
Thieu Le48e6d6d2011-12-06 00:40:27 +000037const char Metrics::kMetricNetworkChannel[] = "Network.Shill.%s.Channel";
38const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
Thieu Lead1ec2c2012-01-05 23:39:48 +000039const char Metrics::kMetricNetworkPhyMode[] = "Network.Shill.%s.PhyMode";
40const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
41const char Metrics::kMetricNetworkSecurity[] = "Network.Shill.%s.Security";
42const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
Thieu Le48e6d6d2011-12-06 00:40:27 +000043const char Metrics::kMetricNetworkServiceErrors[] =
44 "Network.Shill.ServiceErrors";
45const int Metrics::kMetricNetworkServiceErrorsMax = Service::kFailureMax;
Paul Stewart23b393a2012-09-25 21:21:06 -070046const char Metrics::kMetricNetworkSignalStrength[] =
47 "Network.Shill.%s.SignalStrength";
48const int Metrics::kMetricNetworkSignalStrengthMax = 200;
49const int Metrics::kMetricNetworkSignalStrengthMin = 0;
50const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
Thieu Lea20cbc22012-01-09 22:01:43 +000051
52const char Metrics::kMetricTimeOnlineSeconds[] = "Network.Shill.%s.TimeOnline";
53const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
54const int Metrics::kMetricTimeOnlineSecondsMin = 1;
55
56const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
57const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
58const int Metrics::kMetricTimeToDropSecondsMin = 1;
59
Thieu Leb84ba342012-03-02 15:15:19 -080060const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
61 "Network.Shill.%s.TimeResumeToReady";
Thieu Le48e6d6d2011-12-06 00:40:27 +000062const char Metrics::kMetricTimeToConfigMilliseconds[] =
63 "Network.Shill.%s.TimeToConfig";
64const char Metrics::kMetricTimeToJoinMilliseconds[] =
65 "Network.Shill.%s.TimeToJoin";
66const char Metrics::kMetricTimeToOnlineMilliseconds[] =
67 "Network.Shill.%s.TimeToOnline";
68const char Metrics::kMetricTimeToPortalMilliseconds[] =
69 "Network.Shill.%s.TimeToPortal";
Thieu Lea20cbc22012-01-09 22:01:43 +000070const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
71const int Metrics::kTimerHistogramMillisecondsMin = 1;
Thieu Le48e6d6d2011-12-06 00:40:27 +000072const int Metrics::kTimerHistogramNumBuckets = 50;
73
Thieu Le85e050b2012-03-13 15:04:38 -070074const char Metrics::kMetricPortalAttempts[] =
75 "Network.Shill.%s.PortalAttempts";
76const int Metrics::kMetricPortalAttemptsMax =
77 PortalDetector::kMaxRequestAttempts;
78const int Metrics::kMetricPortalAttemptsMin = 1;
79const int Metrics::kMetricPortalAttemptsNumBuckets =
80 Metrics::kMetricPortalAttemptsMax;
81
82const char Metrics::kMetricPortalAttemptsToOnline[] =
83 "Network.Shill.%s.PortalAttemptsToOnline";
84const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
85const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
86const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
87
88const char Metrics::kMetricPortalResult[] = "Network.Shill.%s.PortalResult";
89
Arman Ugurayab22c162012-10-08 19:08:38 -070090const char Metrics::kMetricTerminationActionTimeOnTerminate[] =
91 "Network.Shill.TerminationActionTime.OnTerminate";
92const char Metrics::kMetricTerminationActionResultOnTerminate[] =
93 "Network.Shill.TerminationActionResult.OnTerminate";
94const char Metrics::kMetricTerminationActionTimeOnSuspend[] =
95 "Network.Shill.TerminationActionTime.OnSuspend";
96const char Metrics::kMetricTerminationActionResultOnSuspend[] =
97 "Network.Shill.TerminationActionResult.OnSuspend";
98const int Metrics::kMetricTerminationActionTimeMillisecondsMax = 10000;
99const int Metrics::kMetricTerminationActionTimeMillisecondsMin = 1;
Arman Uguray6d528f12012-09-13 13:44:55 -0700100
Thieu Le48e6d6d2011-12-06 00:40:27 +0000101// static
102const uint16 Metrics::kWiFiBandwidth5MHz = 5;
103const uint16 Metrics::kWiFiBandwidth20MHz = 20;
104const uint16 Metrics::kWiFiFrequency2412 = 2412;
105const uint16 Metrics::kWiFiFrequency2472 = 2472;
106const uint16 Metrics::kWiFiFrequency2484 = 2484;
107const uint16 Metrics::kWiFiFrequency5170 = 5170;
108const uint16 Metrics::kWiFiFrequency5180 = 5180;
109const uint16 Metrics::kWiFiFrequency5230 = 5230;
110const uint16 Metrics::kWiFiFrequency5240 = 5240;
111const uint16 Metrics::kWiFiFrequency5320 = 5320;
112const uint16 Metrics::kWiFiFrequency5500 = 5500;
113const uint16 Metrics::kWiFiFrequency5700 = 5700;
114const uint16 Metrics::kWiFiFrequency5745 = 5745;
115const uint16 Metrics::kWiFiFrequency5825 = 5825;
116
Thieu Leb84ba342012-03-02 15:15:19 -0800117// static
118const char Metrics::kMetricPowerManagerKey[] = "metrics";
119
Paul Stewartff845fc2012-08-07 07:28:44 -0700120// static
121const char Metrics::kMetricLinkMonitorFailure[] =
122 "Network.Shill.%s.LinkMonitorFailure";
123const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
124 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewartf1961f82012-09-11 20:45:39 -0700125const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
126const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700127 LinkMonitor::kTestPeriodMilliseconds;
128const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700129const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
130 "Network.Shill.%s.LinkMonitorSecondsToFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700131const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
132const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
Paul Stewart0443aa52012-08-09 10:43:50 -0700133const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
134const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
135 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
136const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
137 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
Paul Stewartf1961f82012-09-11 20:45:39 -0700138const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
139const int Metrics::kMetricLinkMonitorErrorCountMax =
Paul Stewart0443aa52012-08-09 10:43:50 -0700140 LinkMonitor::kFailureThreshold;
141const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
142 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700143
Wade Guthried4977f22012-08-22 12:37:54 -0700144// static
145const char Metrics::kMetricLinkClientDisconnectReason[] =
146 "Network.Shill.WiFi.ClientDisconnectReason";
147const char Metrics::kMetricLinkApDisconnectReason[] =
148 "Network.Shill.WiFi.ApDisconnectReason";
149const char Metrics::kMetricLinkClientDisconnectType[] =
150 "Network.Shill.WiFi.ClientDisconnectType";
151const char Metrics::kMetricLinkApDisconnectType[] =
152 "Network.Shill.WiFi.ApDisconnectType";
153
154
Thieu Lea20cbc22012-01-09 22:01:43 +0000155Metrics::Metrics()
156 : library_(&metrics_library_),
157 last_default_technology_(Technology::kUnknown),
158 was_online_(false),
159 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800160 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200161 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
Arman Ugurayab22c162012-10-08 19:08:38 -0700162 time_termination_actions_timer(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200163 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000164 metrics_library_.Init();
165 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
166}
167
168Metrics::~Metrics() {}
169
170// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000171Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
172 WiFiChannel channel = kWiFiChannelUndef;
173 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
174 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
175 channel = static_cast<WiFiChannel>(
176 kWiFiChannel2412 +
177 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
178 } else if (frequency == kWiFiFrequency2484) {
179 channel = kWiFiChannel2484;
180 } else if (kWiFiFrequency5170 <= frequency &&
181 frequency <= kWiFiFrequency5230) {
182 if ((frequency % kWiFiBandwidth20MHz) == 0)
183 channel = static_cast<WiFiChannel>(
184 kWiFiChannel5180 +
185 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
186 if ((frequency % kWiFiBandwidth20MHz) == 10)
187 channel = static_cast<WiFiChannel>(
188 kWiFiChannel5170 +
189 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
190 } else if (kWiFiFrequency5240 <= frequency &&
191 frequency <= kWiFiFrequency5320) {
192 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
193 channel = static_cast<WiFiChannel>(
194 kWiFiChannel5180 +
195 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
196 } else if (kWiFiFrequency5500 <= frequency &&
197 frequency <= kWiFiFrequency5700) {
198 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
199 channel = static_cast<WiFiChannel>(
200 kWiFiChannel5500 +
201 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
202 } else if (kWiFiFrequency5745 <= frequency &&
203 frequency <= kWiFiFrequency5825) {
204 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
205 channel = static_cast<WiFiChannel>(
206 kWiFiChannel5745 +
207 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
208 }
209 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
210
211 if (channel == kWiFiChannelUndef)
212 LOG(WARNING) << "no mapping for frequency " << frequency;
213 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700214 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000215
216 return channel;
217}
218
Thieu Lead1ec2c2012-01-05 23:39:48 +0000219// static
220Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
221 const std::string &security) {
222 if (security == flimflam::kSecurityNone) {
223 return kWiFiSecurityNone;
224 } else if (security == flimflam::kSecurityWep) {
225 return kWiFiSecurityWep;
226 } else if (security == flimflam::kSecurityWpa) {
227 return kWiFiSecurityWpa;
228 } else if (security == flimflam::kSecurityRsn) {
229 return kWiFiSecurityRsn;
230 } else if (security == flimflam::kSecurity8021x) {
231 return kWiFiSecurity8021x;
232 } else if (security == flimflam::kSecurityPsk) {
233 return kWiFiSecurityPsk;
234 } else {
235 return kWiFiSecurityUnknown;
236 }
237}
238
Thieu Le85e050b2012-03-13 15:04:38 -0700239// static
240Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
241 const PortalDetector::Result &result) {
242 DCHECK(result.final);
243 PortalResult retval = kPortalResultUnknown;
244 // The only time we should end a successful portal detection is when we're
245 // in the Content phase. If we end with kStatusSuccess in any other phase,
246 // then this indicates that something bad has happened.
247 switch (result.phase) {
248 case PortalDetector::kPhaseDNS:
249 if (result.status == PortalDetector::kStatusFailure)
250 retval = kPortalResultDNSFailure;
251 else if (result.status == PortalDetector::kStatusTimeout)
252 retval = kPortalResultDNSTimeout;
253 else
254 LOG(DFATAL) << __func__ << ": Final result status " << result.status
255 << " is not allowed in the DNS phase";
256 break;
257
258 case PortalDetector::kPhaseConnection:
259 if (result.status == PortalDetector::kStatusFailure)
260 retval = kPortalResultConnectionFailure;
261 else if (result.status == PortalDetector::kStatusTimeout)
262 retval = kPortalResultConnectionTimeout;
263 else
264 LOG(DFATAL) << __func__ << ": Final result status " << result.status
265 << " is not allowed in the Connection phase";
266 break;
267
268 case PortalDetector::kPhaseHTTP:
269 if (result.status == PortalDetector::kStatusFailure)
270 retval = kPortalResultHTTPFailure;
271 else if (result.status == PortalDetector::kStatusTimeout)
272 retval = kPortalResultHTTPTimeout;
273 else
274 LOG(DFATAL) << __func__ << ": Final result status " << result.status
275 << " is not allowed in the HTTP phase";
276 break;
277
278 case PortalDetector::kPhaseContent:
279 if (result.status == PortalDetector::kStatusSuccess)
280 retval = kPortalResultSuccess;
281 else if (result.status == PortalDetector::kStatusFailure)
282 retval = kPortalResultContentFailure;
283 else if (result.status == PortalDetector::kStatusTimeout)
284 retval = kPortalResultContentTimeout;
285 else
286 LOG(DFATAL) << __func__ << ": Final result status " << result.status
287 << " is not allowed in the Content phase";
288 break;
289
290 case PortalDetector::kPhaseUnknown:
291 retval = kPortalResultUnknown;
292 break;
293
294 default:
295 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
296 break;
297 }
298
299 return retval;
300}
301
Thieu Le48e6d6d2011-12-06 00:40:27 +0000302void Metrics::RegisterService(const Service *service) {
303 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
304 services_metrics_[service] = service_metrics;
305 service_metrics->service = service;
306 InitializeCommonServiceMetrics(service);
307 service->InitializeCustomMetrics();
308}
309
310void Metrics::DeregisterService(const Service *service) {
311 services_metrics_.erase(service);
312}
313
314void Metrics::AddServiceStateTransitionTimer(
315 const Service *service,
316 const string &histogram_name,
317 Service::ConnectState start_state,
318 Service::ConnectState stop_state) {
319 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
320 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700321 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000322 DCHECK(false);
323 return;
324 }
325 ServiceMetrics *service_metrics = it->second.get();
326 CHECK(start_state < stop_state);
327 chromeos_metrics::TimerReporter *timer =
328 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000329 kTimerHistogramMillisecondsMin,
330 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000331 kTimerHistogramNumBuckets);
332 service_metrics->timers.push_back(timer); // passes ownership.
333 service_metrics->start_on_state[start_state].push_back(timer);
334 service_metrics->stop_on_state[stop_state].push_back(timer);
335}
336
Thieu Lea20cbc22012-01-09 22:01:43 +0000337void Metrics::NotifyDefaultServiceChanged(const Service *service) {
338 base::TimeDelta elapsed_seconds;
339
340 Technology::Identifier technology = (service) ? service->technology() :
341 Technology::kUnknown;
342 if (technology != last_default_technology_) {
343 if (last_default_technology_ != Technology::kUnknown) {
344 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
345 last_default_technology_);
346 time_online_timer_->GetElapsedTime(&elapsed_seconds);
347 SendToUMA(histogram,
348 elapsed_seconds.InSeconds(),
349 kMetricTimeOnlineSecondsMin,
350 kMetricTimeOnlineSecondsMax,
351 kTimerHistogramNumBuckets);
352 }
353 last_default_technology_ = technology;
354 time_online_timer_->Start();
355 }
356
Thieu Lea20cbc22012-01-09 22:01:43 +0000357 // Ignore changes that are not online/offline transitions; e.g.
358 // switching between wired and wireless. TimeToDrop measures
359 // time online regardless of how we are connected.
360 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
361 return;
362
363 if (service == NULL) {
364 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
365 SendToUMA(kMetricTimeToDropSeconds,
366 elapsed_seconds.InSeconds(),
367 kMetricTimeToDropSecondsMin,
368 kMetricTimeToDropSecondsMax,
369 kTimerHistogramNumBuckets);
370 } else {
371 time_to_drop_timer_->Start();
372 }
373
374 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000375}
376
377void Metrics::NotifyServiceStateChanged(const Service *service,
378 Service::ConnectState new_state) {
379 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
380 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700381 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000382 DCHECK(false);
383 return;
384 }
385 ServiceMetrics *service_metrics = it->second.get();
386 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
387
388 if (new_state == Service::kStateFailure)
389 SendServiceFailure(service);
390
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200391 if (collect_bootstats_) {
392 bootstat_log(
393 StringPrintf("network-%s-%s",
394 Technology::NameFromIdentifier(
395 service->technology()).c_str(),
396 service->GetStateString().c_str()).c_str());
397 }
398
Paul Stewart20088d82012-02-16 06:58:55 -0800399 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000400 return;
401
Thieu Leb84ba342012-03-02 15:15:19 -0800402 base::TimeDelta time_resume_to_ready;
403 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
404 time_resume_to_ready_timer_->Reset();
405 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000406}
407
408string Metrics::GetFullMetricName(const char *metric_name,
409 Technology::Identifier technology_id) {
410 string technology = Technology::NameFromIdentifier(technology_id);
411 technology[0] = base::ToUpperASCII(technology[0]);
412 return base::StringPrintf(metric_name, technology.c_str());
413}
414
Thieu Le67370f62012-02-14 23:01:42 +0000415void Metrics::NotifyServiceDisconnect(const Service *service) {
416 Technology::Identifier technology = service->technology();
417 string histogram = GetFullMetricName(kMetricDisconnect, technology);
418 SendToUMA(histogram,
419 service->explicitly_disconnected(),
420 kMetricDisconnectMin,
421 kMetricDisconnectMax,
422 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000423}
424
Thieu Leb84ba342012-03-02 15:15:19 -0800425void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
426 if (new_state == PowerManagerProxyDelegate::kOn) {
427 time_resume_to_ready_timer_->Start();
428 } else {
429 time_resume_to_ready_timer_->Reset();
430 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000431}
432
Arman Ugurayab22c162012-10-08 19:08:38 -0700433void Metrics::NotifyTerminationActionsStarted(
434 TerminationActionReason /*reason*/) {
435 if (time_termination_actions_timer->HasStarted())
436 return;
437 time_termination_actions_timer->Start();
438}
439
440void Metrics::NotifyTerminationActionsCompleted(
441 TerminationActionReason reason, bool success) {
442 if (!time_termination_actions_timer->HasStarted())
443 return;
444
445 int result = success ? kTerminationActionResultSuccess :
446 kTerminationActionResultFailure;
447
448 base::TimeDelta elapsed_time;
449 time_termination_actions_timer->GetElapsedTime(&elapsed_time);
450 time_termination_actions_timer->Reset();
451 string time_metric, result_metric;
452 switch (reason) {
453 case kTerminationActionReasonSuspend:
454 time_metric = kMetricTerminationActionTimeOnSuspend;
455 result_metric = kMetricTerminationActionResultOnSuspend;
456 break;
457 case kTerminationActionReasonTerminate:
458 time_metric = kMetricTerminationActionTimeOnTerminate;
459 result_metric = kMetricTerminationActionResultOnTerminate;
460 break;
461 }
462
463 SendToUMA(time_metric,
464 elapsed_time.InMilliseconds(),
465 kMetricTerminationActionTimeMillisecondsMin,
466 kMetricTerminationActionTimeMillisecondsMax,
467 kTimerHistogramNumBuckets);
468
469 SendEnumToUMA(result_metric,
470 result,
471 kTerminationActionResultMax);
472}
473
Paul Stewartff845fc2012-08-07 07:28:44 -0700474void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700475 Technology::Identifier technology,
476 LinkMonitorFailure failure,
Paul Stewartf1961f82012-09-11 20:45:39 -0700477 int seconds_to_failure,
478 int broadcast_error_count,
479 int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700480 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
481 technology);
482 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700483
484 if (failure == kLinkMonitorFailureThresholdReached) {
485 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
486 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
487 }
488 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
489 technology);
490 SendToUMA(histogram,
491 seconds_to_failure,
492 kMetricLinkMonitorSecondsToFailureMin,
493 kMetricLinkMonitorSecondsToFailureMax,
494 kMetricLinkMonitorSecondsToFailureNumBuckets);
495 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
496 technology);
497 SendToUMA(histogram,
498 broadcast_error_count,
499 kMetricLinkMonitorErrorCountMin,
500 kMetricLinkMonitorErrorCountMax,
501 kMetricLinkMonitorErrorCountNumBuckets);
502 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
503 technology);
504 SendToUMA(histogram,
505 unicast_error_count,
506 kMetricLinkMonitorErrorCountMin,
507 kMetricLinkMonitorErrorCountMax,
508 kMetricLinkMonitorErrorCountNumBuckets);
509 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700510}
511
512void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
513 Technology::Identifier technology,
Paul Stewartf1961f82012-09-11 20:45:39 -0700514 int response_time_milliseconds) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700515 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
516 technology);
517 SendToUMA(histogram,
518 response_time_milliseconds,
519 kMetricLinkMonitorResponseTimeSampleMin,
520 kMetricLinkMonitorResponseTimeSampleMax,
521 kMetricLinkMonitorResponseTimeSampleNumBuckets);
522}
523
Wade Guthried4977f22012-08-22 12:37:54 -0700524void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
525 IEEE_80211::WiFiReasonCode reason) {
526 string metric_disconnect_reason;
527 string metric_disconnect_type;
528 WiFiStatusType type;
529
530 if (by_whom == kDisconnectedByAp) {
531 metric_disconnect_reason = kMetricLinkApDisconnectReason;
532 metric_disconnect_type = kMetricLinkApDisconnectType;
533 type = kStatusCodeTypeByAp;
534 } else {
535 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
536 metric_disconnect_type = kMetricLinkClientDisconnectType;
537 switch(reason) {
538 case IEEE_80211::kReasonCodeSenderHasLeft:
539 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
540 type = kStatusCodeTypeByUser;
541 break;
542
543 case IEEE_80211::kReasonCodeInactivity:
544 type = kStatusCodeTypeConsideredDead;
545 break;
546
547 default:
548 type = kStatusCodeTypeByClient;
549 break;
550 }
551 }
552 SendEnumToUMA(metric_disconnect_reason, reason,
553 IEEE_80211::kStatusCodeMax);
554 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
555}
556
Thieu Le48e6d6d2011-12-06 00:40:27 +0000557bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
558 return library_->SendEnumToUMA(name, sample, max);
559}
560
Thieu Lea20cbc22012-01-09 22:01:43 +0000561bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
562 int num_buckets) {
563 return library_->SendToUMA(name, sample, min, max, num_buckets);
564}
565
Thieu Le48e6d6d2011-12-06 00:40:27 +0000566void Metrics::InitializeCommonServiceMetrics(const Service *service) {
567 Technology::Identifier technology = service->technology();
568 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
569 technology);
570 AddServiceStateTransitionTimer(
571 service,
572 histogram,
573 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800574 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000575 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
576 AddServiceStateTransitionTimer(
577 service,
578 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800579 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000580 Service::kStatePortal);
581 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
582 AddServiceStateTransitionTimer(
583 service,
584 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800585 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000586 Service::kStateOnline);
587}
588
589void Metrics::UpdateServiceStateTransitionMetrics(
590 ServiceMetrics *service_metrics,
591 Service::ConnectState new_state) {
592 TimerReportersList::iterator it;
593 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
594 for (it = start_timers.begin(); it != start_timers.end(); ++it)
595 (*it)->Start();
596
597 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
598 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
599 (*it)->Stop();
600 (*it)->ReportMilliseconds();
601 }
602}
603
604void Metrics::SendServiceFailure(const Service *service) {
605 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
606 service->failure(),
607 kMetricNetworkServiceErrorsMax);
608}
609
610void Metrics::set_library(MetricsLibraryInterface *library) {
611 chromeos_metrics::TimerReporter::set_metrics_lib(library);
612 library_ = library;
613}
614
615} // namespace shill