blob: f9a010f3285264058a59782b315e10e5f75691b8 [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;
Thieu Lea20cbc22012-01-09 22:01:43 +000046
47const char Metrics::kMetricTimeOnlineSeconds[] = "Network.Shill.%s.TimeOnline";
48const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
49const int Metrics::kMetricTimeOnlineSecondsMin = 1;
50
51const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
52const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
53const int Metrics::kMetricTimeToDropSecondsMin = 1;
54
Thieu Leb84ba342012-03-02 15:15:19 -080055const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
56 "Network.Shill.%s.TimeResumeToReady";
Thieu Le48e6d6d2011-12-06 00:40:27 +000057const char Metrics::kMetricTimeToConfigMilliseconds[] =
58 "Network.Shill.%s.TimeToConfig";
59const char Metrics::kMetricTimeToJoinMilliseconds[] =
60 "Network.Shill.%s.TimeToJoin";
61const char Metrics::kMetricTimeToOnlineMilliseconds[] =
62 "Network.Shill.%s.TimeToOnline";
63const char Metrics::kMetricTimeToPortalMilliseconds[] =
64 "Network.Shill.%s.TimeToPortal";
Thieu Lea20cbc22012-01-09 22:01:43 +000065const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
66const int Metrics::kTimerHistogramMillisecondsMin = 1;
Thieu Le48e6d6d2011-12-06 00:40:27 +000067const int Metrics::kTimerHistogramNumBuckets = 50;
68
Thieu Le85e050b2012-03-13 15:04:38 -070069const char Metrics::kMetricPortalAttempts[] =
70 "Network.Shill.%s.PortalAttempts";
71const int Metrics::kMetricPortalAttemptsMax =
72 PortalDetector::kMaxRequestAttempts;
73const int Metrics::kMetricPortalAttemptsMin = 1;
74const int Metrics::kMetricPortalAttemptsNumBuckets =
75 Metrics::kMetricPortalAttemptsMax;
76
77const char Metrics::kMetricPortalAttemptsToOnline[] =
78 "Network.Shill.%s.PortalAttemptsToOnline";
79const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
80const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
81const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
82
83const char Metrics::kMetricPortalResult[] = "Network.Shill.%s.PortalResult";
84
Arman Uguray6d528f12012-09-13 13:44:55 -070085const char Metrics::kMetricTerminationActionResult[] =
86 "Network.Shill.TerminationActionResult";
87
Thieu Le48e6d6d2011-12-06 00:40:27 +000088// static
89const uint16 Metrics::kWiFiBandwidth5MHz = 5;
90const uint16 Metrics::kWiFiBandwidth20MHz = 20;
91const uint16 Metrics::kWiFiFrequency2412 = 2412;
92const uint16 Metrics::kWiFiFrequency2472 = 2472;
93const uint16 Metrics::kWiFiFrequency2484 = 2484;
94const uint16 Metrics::kWiFiFrequency5170 = 5170;
95const uint16 Metrics::kWiFiFrequency5180 = 5180;
96const uint16 Metrics::kWiFiFrequency5230 = 5230;
97const uint16 Metrics::kWiFiFrequency5240 = 5240;
98const uint16 Metrics::kWiFiFrequency5320 = 5320;
99const uint16 Metrics::kWiFiFrequency5500 = 5500;
100const uint16 Metrics::kWiFiFrequency5700 = 5700;
101const uint16 Metrics::kWiFiFrequency5745 = 5745;
102const uint16 Metrics::kWiFiFrequency5825 = 5825;
103
Thieu Leb84ba342012-03-02 15:15:19 -0800104// static
105const char Metrics::kMetricPowerManagerKey[] = "metrics";
106
Paul Stewartff845fc2012-08-07 07:28:44 -0700107// static
108const char Metrics::kMetricLinkMonitorFailure[] =
109 "Network.Shill.%s.LinkMonitorFailure";
110const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
111 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewart0443aa52012-08-09 10:43:50 -0700112const unsigned int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
113const unsigned int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700114 LinkMonitor::kTestPeriodMilliseconds;
115const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700116const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
117 "Network.Shill.%s.LinkMonitorSecondsToFailure";
118const unsigned int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
119const unsigned int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
120const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
121const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
122 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
123const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
124 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
125const unsigned int Metrics::kMetricLinkMonitorErrorCountMin = 0;
126const unsigned int Metrics::kMetricLinkMonitorErrorCountMax =
127 LinkMonitor::kFailureThreshold;
128const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
129 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700130
Wade Guthried4977f22012-08-22 12:37:54 -0700131// static
132const char Metrics::kMetricLinkClientDisconnectReason[] =
133 "Network.Shill.WiFi.ClientDisconnectReason";
134const char Metrics::kMetricLinkApDisconnectReason[] =
135 "Network.Shill.WiFi.ApDisconnectReason";
136const char Metrics::kMetricLinkClientDisconnectType[] =
137 "Network.Shill.WiFi.ClientDisconnectType";
138const char Metrics::kMetricLinkApDisconnectType[] =
139 "Network.Shill.WiFi.ApDisconnectType";
140
141
Thieu Lea20cbc22012-01-09 22:01:43 +0000142Metrics::Metrics()
143 : library_(&metrics_library_),
144 last_default_technology_(Technology::kUnknown),
145 was_online_(false),
146 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800147 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200148 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
149 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000150 metrics_library_.Init();
151 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
152}
153
154Metrics::~Metrics() {}
155
156// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000157Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
158 WiFiChannel channel = kWiFiChannelUndef;
159 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
160 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
161 channel = static_cast<WiFiChannel>(
162 kWiFiChannel2412 +
163 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
164 } else if (frequency == kWiFiFrequency2484) {
165 channel = kWiFiChannel2484;
166 } else if (kWiFiFrequency5170 <= frequency &&
167 frequency <= kWiFiFrequency5230) {
168 if ((frequency % kWiFiBandwidth20MHz) == 0)
169 channel = static_cast<WiFiChannel>(
170 kWiFiChannel5180 +
171 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
172 if ((frequency % kWiFiBandwidth20MHz) == 10)
173 channel = static_cast<WiFiChannel>(
174 kWiFiChannel5170 +
175 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
176 } else if (kWiFiFrequency5240 <= frequency &&
177 frequency <= kWiFiFrequency5320) {
178 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
179 channel = static_cast<WiFiChannel>(
180 kWiFiChannel5180 +
181 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
182 } else if (kWiFiFrequency5500 <= frequency &&
183 frequency <= kWiFiFrequency5700) {
184 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
185 channel = static_cast<WiFiChannel>(
186 kWiFiChannel5500 +
187 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
188 } else if (kWiFiFrequency5745 <= frequency &&
189 frequency <= kWiFiFrequency5825) {
190 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
191 channel = static_cast<WiFiChannel>(
192 kWiFiChannel5745 +
193 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
194 }
195 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
196
197 if (channel == kWiFiChannelUndef)
198 LOG(WARNING) << "no mapping for frequency " << frequency;
199 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700200 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000201
202 return channel;
203}
204
Thieu Lead1ec2c2012-01-05 23:39:48 +0000205// static
206Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
207 const std::string &security) {
208 if (security == flimflam::kSecurityNone) {
209 return kWiFiSecurityNone;
210 } else if (security == flimflam::kSecurityWep) {
211 return kWiFiSecurityWep;
212 } else if (security == flimflam::kSecurityWpa) {
213 return kWiFiSecurityWpa;
214 } else if (security == flimflam::kSecurityRsn) {
215 return kWiFiSecurityRsn;
216 } else if (security == flimflam::kSecurity8021x) {
217 return kWiFiSecurity8021x;
218 } else if (security == flimflam::kSecurityPsk) {
219 return kWiFiSecurityPsk;
220 } else {
221 return kWiFiSecurityUnknown;
222 }
223}
224
Thieu Le85e050b2012-03-13 15:04:38 -0700225// static
226Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
227 const PortalDetector::Result &result) {
228 DCHECK(result.final);
229 PortalResult retval = kPortalResultUnknown;
230 // The only time we should end a successful portal detection is when we're
231 // in the Content phase. If we end with kStatusSuccess in any other phase,
232 // then this indicates that something bad has happened.
233 switch (result.phase) {
234 case PortalDetector::kPhaseDNS:
235 if (result.status == PortalDetector::kStatusFailure)
236 retval = kPortalResultDNSFailure;
237 else if (result.status == PortalDetector::kStatusTimeout)
238 retval = kPortalResultDNSTimeout;
239 else
240 LOG(DFATAL) << __func__ << ": Final result status " << result.status
241 << " is not allowed in the DNS phase";
242 break;
243
244 case PortalDetector::kPhaseConnection:
245 if (result.status == PortalDetector::kStatusFailure)
246 retval = kPortalResultConnectionFailure;
247 else if (result.status == PortalDetector::kStatusTimeout)
248 retval = kPortalResultConnectionTimeout;
249 else
250 LOG(DFATAL) << __func__ << ": Final result status " << result.status
251 << " is not allowed in the Connection phase";
252 break;
253
254 case PortalDetector::kPhaseHTTP:
255 if (result.status == PortalDetector::kStatusFailure)
256 retval = kPortalResultHTTPFailure;
257 else if (result.status == PortalDetector::kStatusTimeout)
258 retval = kPortalResultHTTPTimeout;
259 else
260 LOG(DFATAL) << __func__ << ": Final result status " << result.status
261 << " is not allowed in the HTTP phase";
262 break;
263
264 case PortalDetector::kPhaseContent:
265 if (result.status == PortalDetector::kStatusSuccess)
266 retval = kPortalResultSuccess;
267 else if (result.status == PortalDetector::kStatusFailure)
268 retval = kPortalResultContentFailure;
269 else if (result.status == PortalDetector::kStatusTimeout)
270 retval = kPortalResultContentTimeout;
271 else
272 LOG(DFATAL) << __func__ << ": Final result status " << result.status
273 << " is not allowed in the Content phase";
274 break;
275
276 case PortalDetector::kPhaseUnknown:
277 retval = kPortalResultUnknown;
278 break;
279
280 default:
281 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
282 break;
283 }
284
285 return retval;
286}
287
Thieu Le48e6d6d2011-12-06 00:40:27 +0000288void Metrics::RegisterService(const Service *service) {
289 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
290 services_metrics_[service] = service_metrics;
291 service_metrics->service = service;
292 InitializeCommonServiceMetrics(service);
293 service->InitializeCustomMetrics();
294}
295
296void Metrics::DeregisterService(const Service *service) {
297 services_metrics_.erase(service);
298}
299
300void Metrics::AddServiceStateTransitionTimer(
301 const Service *service,
302 const string &histogram_name,
303 Service::ConnectState start_state,
304 Service::ConnectState stop_state) {
305 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
306 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700307 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000308 DCHECK(false);
309 return;
310 }
311 ServiceMetrics *service_metrics = it->second.get();
312 CHECK(start_state < stop_state);
313 chromeos_metrics::TimerReporter *timer =
314 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000315 kTimerHistogramMillisecondsMin,
316 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000317 kTimerHistogramNumBuckets);
318 service_metrics->timers.push_back(timer); // passes ownership.
319 service_metrics->start_on_state[start_state].push_back(timer);
320 service_metrics->stop_on_state[stop_state].push_back(timer);
321}
322
Thieu Lea20cbc22012-01-09 22:01:43 +0000323void Metrics::NotifyDefaultServiceChanged(const Service *service) {
324 base::TimeDelta elapsed_seconds;
325
326 Technology::Identifier technology = (service) ? service->technology() :
327 Technology::kUnknown;
328 if (technology != last_default_technology_) {
329 if (last_default_technology_ != Technology::kUnknown) {
330 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
331 last_default_technology_);
332 time_online_timer_->GetElapsedTime(&elapsed_seconds);
333 SendToUMA(histogram,
334 elapsed_seconds.InSeconds(),
335 kMetricTimeOnlineSecondsMin,
336 kMetricTimeOnlineSecondsMax,
337 kTimerHistogramNumBuckets);
338 }
339 last_default_technology_ = technology;
340 time_online_timer_->Start();
341 }
342
Thieu Lea20cbc22012-01-09 22:01:43 +0000343 // Ignore changes that are not online/offline transitions; e.g.
344 // switching between wired and wireless. TimeToDrop measures
345 // time online regardless of how we are connected.
346 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
347 return;
348
349 if (service == NULL) {
350 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
351 SendToUMA(kMetricTimeToDropSeconds,
352 elapsed_seconds.InSeconds(),
353 kMetricTimeToDropSecondsMin,
354 kMetricTimeToDropSecondsMax,
355 kTimerHistogramNumBuckets);
356 } else {
357 time_to_drop_timer_->Start();
358 }
359
360 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000361}
362
363void Metrics::NotifyServiceStateChanged(const Service *service,
364 Service::ConnectState new_state) {
365 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
366 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700367 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000368 DCHECK(false);
369 return;
370 }
371 ServiceMetrics *service_metrics = it->second.get();
372 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
373
374 if (new_state == Service::kStateFailure)
375 SendServiceFailure(service);
376
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200377 if (collect_bootstats_) {
378 bootstat_log(
379 StringPrintf("network-%s-%s",
380 Technology::NameFromIdentifier(
381 service->technology()).c_str(),
382 service->GetStateString().c_str()).c_str());
383 }
384
Paul Stewart20088d82012-02-16 06:58:55 -0800385 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000386 return;
387
Thieu Leb84ba342012-03-02 15:15:19 -0800388 base::TimeDelta time_resume_to_ready;
389 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
390 time_resume_to_ready_timer_->Reset();
391 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000392}
393
394string Metrics::GetFullMetricName(const char *metric_name,
395 Technology::Identifier technology_id) {
396 string technology = Technology::NameFromIdentifier(technology_id);
397 technology[0] = base::ToUpperASCII(technology[0]);
398 return base::StringPrintf(metric_name, technology.c_str());
399}
400
Thieu Le67370f62012-02-14 23:01:42 +0000401void Metrics::NotifyServiceDisconnect(const Service *service) {
402 Technology::Identifier technology = service->technology();
403 string histogram = GetFullMetricName(kMetricDisconnect, technology);
404 SendToUMA(histogram,
405 service->explicitly_disconnected(),
406 kMetricDisconnectMin,
407 kMetricDisconnectMax,
408 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000409}
410
Thieu Leb84ba342012-03-02 15:15:19 -0800411void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
412 if (new_state == PowerManagerProxyDelegate::kOn) {
413 time_resume_to_ready_timer_->Start();
414 } else {
415 time_resume_to_ready_timer_->Reset();
416 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000417}
418
Paul Stewartff845fc2012-08-07 07:28:44 -0700419void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700420 Technology::Identifier technology,
421 LinkMonitorFailure failure,
422 unsigned int seconds_to_failure,
423 unsigned int broadcast_error_count,
424 unsigned int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700425 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
426 technology);
427 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700428
429 if (failure == kLinkMonitorFailureThresholdReached) {
430 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
431 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
432 }
433 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
434 technology);
435 SendToUMA(histogram,
436 seconds_to_failure,
437 kMetricLinkMonitorSecondsToFailureMin,
438 kMetricLinkMonitorSecondsToFailureMax,
439 kMetricLinkMonitorSecondsToFailureNumBuckets);
440 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
441 technology);
442 SendToUMA(histogram,
443 broadcast_error_count,
444 kMetricLinkMonitorErrorCountMin,
445 kMetricLinkMonitorErrorCountMax,
446 kMetricLinkMonitorErrorCountNumBuckets);
447 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
448 technology);
449 SendToUMA(histogram,
450 unicast_error_count,
451 kMetricLinkMonitorErrorCountMin,
452 kMetricLinkMonitorErrorCountMax,
453 kMetricLinkMonitorErrorCountNumBuckets);
454 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700455}
456
457void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
458 Technology::Identifier technology,
459 unsigned int response_time_milliseconds) {
460 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
461 technology);
462 SendToUMA(histogram,
463 response_time_milliseconds,
464 kMetricLinkMonitorResponseTimeSampleMin,
465 kMetricLinkMonitorResponseTimeSampleMax,
466 kMetricLinkMonitorResponseTimeSampleNumBuckets);
467}
468
Wade Guthried4977f22012-08-22 12:37:54 -0700469void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
470 IEEE_80211::WiFiReasonCode reason) {
471 string metric_disconnect_reason;
472 string metric_disconnect_type;
473 WiFiStatusType type;
474
475 if (by_whom == kDisconnectedByAp) {
476 metric_disconnect_reason = kMetricLinkApDisconnectReason;
477 metric_disconnect_type = kMetricLinkApDisconnectType;
478 type = kStatusCodeTypeByAp;
479 } else {
480 metric_disconnect_reason = kMetricLinkClientDisconnectReason;
481 metric_disconnect_type = kMetricLinkClientDisconnectType;
482 switch(reason) {
483 case IEEE_80211::kReasonCodeSenderHasLeft:
484 case IEEE_80211::kReasonCodeDisassociatedHasLeft:
485 type = kStatusCodeTypeByUser;
486 break;
487
488 case IEEE_80211::kReasonCodeInactivity:
489 type = kStatusCodeTypeConsideredDead;
490 break;
491
492 default:
493 type = kStatusCodeTypeByClient;
494 break;
495 }
496 }
497 SendEnumToUMA(metric_disconnect_reason, reason,
498 IEEE_80211::kStatusCodeMax);
499 SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
500}
501
Thieu Le48e6d6d2011-12-06 00:40:27 +0000502bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
503 return library_->SendEnumToUMA(name, sample, max);
504}
505
Thieu Lea20cbc22012-01-09 22:01:43 +0000506bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
507 int num_buckets) {
508 return library_->SendToUMA(name, sample, min, max, num_buckets);
509}
510
Thieu Le48e6d6d2011-12-06 00:40:27 +0000511void Metrics::InitializeCommonServiceMetrics(const Service *service) {
512 Technology::Identifier technology = service->technology();
513 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
514 technology);
515 AddServiceStateTransitionTimer(
516 service,
517 histogram,
518 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800519 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000520 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
521 AddServiceStateTransitionTimer(
522 service,
523 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800524 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000525 Service::kStatePortal);
526 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
527 AddServiceStateTransitionTimer(
528 service,
529 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800530 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000531 Service::kStateOnline);
532}
533
534void Metrics::UpdateServiceStateTransitionMetrics(
535 ServiceMetrics *service_metrics,
536 Service::ConnectState new_state) {
537 TimerReportersList::iterator it;
538 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
539 for (it = start_timers.begin(); it != start_timers.end(); ++it)
540 (*it)->Start();
541
542 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
543 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
544 (*it)->Stop();
545 (*it)->ReportMilliseconds();
546 }
547}
548
549void Metrics::SendServiceFailure(const Service *service) {
550 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
551 service->failure(),
552 kMetricNetworkServiceErrorsMax);
553}
554
555void Metrics::set_library(MetricsLibraryInterface *library) {
556 chromeos_metrics::TimerReporter::set_metrics_lib(library);
557 library_ = library;
558}
559
560} // namespace shill