blob: dc83a509b0abd1a0d486bdeb08037c8bd02ee603 [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
Paul Stewartff845fc2012-08-07 07:28:44 -070012#include "shill/link_monitor.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070013#include "shill/logging.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000014#include "shill/wifi_service.h"
15
16using std::string;
17using std::tr1::shared_ptr;
18
19namespace shill {
20
Thieu Le48e6d6d2011-12-06 00:40:27 +000021// static
Thieu Lec31e6f92012-08-03 13:08:58 -070022// Our disconnect enumeration values are 0 (System Disconnect) and
23// 1 (User Disconnect), see histograms.xml, but Chrome needs a minimum
24// enum value of 1 and the minimum number of buckets needs to be 3 (see
25// histogram.h). Instead of remapping System Disconnect to 1 and
26// User Disconnect to 2, we can just leave the enumerated values as-is
27// because Chrome implicitly creates a [0-1) bucket for us. Using Min=1,
28// Max=2 and NumBuckets=3 gives us the following three buckets:
29// [0-1), [1-2), [2-INT_MAX). We end up with an extra bucket [2-INT_MAX)
30// that we can safely ignore.
Thieu Le67370f62012-02-14 23:01:42 +000031const char Metrics::kMetricDisconnect[] = "Network.Shill.%s.Disconnect";
Thieu Lec31e6f92012-08-03 13:08:58 -070032const int Metrics::kMetricDisconnectMax = 2;
33const int Metrics::kMetricDisconnectMin = 1;
34const int Metrics::kMetricDisconnectNumBuckets = 3;
Thieu Le67370f62012-02-14 23:01:42 +000035
Thieu Le48e6d6d2011-12-06 00:40:27 +000036const char Metrics::kMetricNetworkChannel[] = "Network.Shill.%s.Channel";
37const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
Thieu Lead1ec2c2012-01-05 23:39:48 +000038const char Metrics::kMetricNetworkPhyMode[] = "Network.Shill.%s.PhyMode";
39const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
40const char Metrics::kMetricNetworkSecurity[] = "Network.Shill.%s.Security";
41const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
Thieu Le48e6d6d2011-12-06 00:40:27 +000042const char Metrics::kMetricNetworkServiceErrors[] =
43 "Network.Shill.ServiceErrors";
44const int Metrics::kMetricNetworkServiceErrorsMax = Service::kFailureMax;
Thieu Lea20cbc22012-01-09 22:01:43 +000045
46const char Metrics::kMetricTimeOnlineSeconds[] = "Network.Shill.%s.TimeOnline";
47const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60; // 8 hours
48const int Metrics::kMetricTimeOnlineSecondsMin = 1;
49
50const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
51const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60; // 8 hours
52const int Metrics::kMetricTimeToDropSecondsMin = 1;
53
Thieu Leb84ba342012-03-02 15:15:19 -080054const char Metrics::kMetricTimeResumeToReadyMilliseconds[] =
55 "Network.Shill.%s.TimeResumeToReady";
Thieu Le48e6d6d2011-12-06 00:40:27 +000056const char Metrics::kMetricTimeToConfigMilliseconds[] =
57 "Network.Shill.%s.TimeToConfig";
58const char Metrics::kMetricTimeToJoinMilliseconds[] =
59 "Network.Shill.%s.TimeToJoin";
60const char Metrics::kMetricTimeToOnlineMilliseconds[] =
61 "Network.Shill.%s.TimeToOnline";
62const char Metrics::kMetricTimeToPortalMilliseconds[] =
63 "Network.Shill.%s.TimeToPortal";
Thieu Lea20cbc22012-01-09 22:01:43 +000064const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
65const int Metrics::kTimerHistogramMillisecondsMin = 1;
Thieu Le48e6d6d2011-12-06 00:40:27 +000066const int Metrics::kTimerHistogramNumBuckets = 50;
67
Thieu Le85e050b2012-03-13 15:04:38 -070068const char Metrics::kMetricPortalAttempts[] =
69 "Network.Shill.%s.PortalAttempts";
70const int Metrics::kMetricPortalAttemptsMax =
71 PortalDetector::kMaxRequestAttempts;
72const int Metrics::kMetricPortalAttemptsMin = 1;
73const int Metrics::kMetricPortalAttemptsNumBuckets =
74 Metrics::kMetricPortalAttemptsMax;
75
76const char Metrics::kMetricPortalAttemptsToOnline[] =
77 "Network.Shill.%s.PortalAttemptsToOnline";
78const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
79const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
80const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
81
82const char Metrics::kMetricPortalResult[] = "Network.Shill.%s.PortalResult";
83
Thieu Le48e6d6d2011-12-06 00:40:27 +000084// static
85const uint16 Metrics::kWiFiBandwidth5MHz = 5;
86const uint16 Metrics::kWiFiBandwidth20MHz = 20;
87const uint16 Metrics::kWiFiFrequency2412 = 2412;
88const uint16 Metrics::kWiFiFrequency2472 = 2472;
89const uint16 Metrics::kWiFiFrequency2484 = 2484;
90const uint16 Metrics::kWiFiFrequency5170 = 5170;
91const uint16 Metrics::kWiFiFrequency5180 = 5180;
92const uint16 Metrics::kWiFiFrequency5230 = 5230;
93const uint16 Metrics::kWiFiFrequency5240 = 5240;
94const uint16 Metrics::kWiFiFrequency5320 = 5320;
95const uint16 Metrics::kWiFiFrequency5500 = 5500;
96const uint16 Metrics::kWiFiFrequency5700 = 5700;
97const uint16 Metrics::kWiFiFrequency5745 = 5745;
98const uint16 Metrics::kWiFiFrequency5825 = 5825;
99
Thieu Leb84ba342012-03-02 15:15:19 -0800100// static
101const char Metrics::kMetricPowerManagerKey[] = "metrics";
102
Paul Stewartff845fc2012-08-07 07:28:44 -0700103// static
104const char Metrics::kMetricLinkMonitorFailure[] =
105 "Network.Shill.%s.LinkMonitorFailure";
106const char Metrics::kMetricLinkMonitorResponseTimeSample[] =
107 "Network.Shill.%s.LinkMonitorResponseTimeSample";
Paul Stewart0443aa52012-08-09 10:43:50 -0700108const unsigned int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
109const unsigned int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
Paul Stewartff845fc2012-08-07 07:28:44 -0700110 LinkMonitor::kTestPeriodMilliseconds;
111const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
Paul Stewart0443aa52012-08-09 10:43:50 -0700112const char Metrics::kMetricLinkMonitorSecondsToFailure[] =
113 "Network.Shill.%s.LinkMonitorSecondsToFailure";
114const unsigned int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
115const unsigned int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
116const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
117const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailure[] =
118 "Network.Shill.%s.LinkMonitorBroadcastErrorsAtFailure";
119const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailure[] =
120 "Network.Shill.%s.LinkMonitorUnicastErrorsAtFailure";
121const unsigned int Metrics::kMetricLinkMonitorErrorCountMin = 0;
122const unsigned int Metrics::kMetricLinkMonitorErrorCountMax =
123 LinkMonitor::kFailureThreshold;
124const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
125 LinkMonitor::kFailureThreshold + 1;
Paul Stewartff845fc2012-08-07 07:28:44 -0700126
Thieu Lea20cbc22012-01-09 22:01:43 +0000127Metrics::Metrics()
128 : library_(&metrics_library_),
129 last_default_technology_(Technology::kUnknown),
130 was_online_(false),
131 time_online_timer_(new chromeos_metrics::Timer),
Thieu Leb84ba342012-03-02 15:15:19 -0800132 time_to_drop_timer_(new chromeos_metrics::Timer),
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200133 time_resume_to_ready_timer_(new chromeos_metrics::Timer),
134 collect_bootstats_(true) {
Thieu Le48e6d6d2011-12-06 00:40:27 +0000135 metrics_library_.Init();
136 chromeos_metrics::TimerReporter::set_metrics_lib(library_);
137}
138
139Metrics::~Metrics() {}
140
141// static
Thieu Le48e6d6d2011-12-06 00:40:27 +0000142Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
143 WiFiChannel channel = kWiFiChannelUndef;
144 if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
145 if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
146 channel = static_cast<WiFiChannel>(
147 kWiFiChannel2412 +
148 (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
149 } else if (frequency == kWiFiFrequency2484) {
150 channel = kWiFiChannel2484;
151 } else if (kWiFiFrequency5170 <= frequency &&
152 frequency <= kWiFiFrequency5230) {
153 if ((frequency % kWiFiBandwidth20MHz) == 0)
154 channel = static_cast<WiFiChannel>(
155 kWiFiChannel5180 +
156 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
157 if ((frequency % kWiFiBandwidth20MHz) == 10)
158 channel = static_cast<WiFiChannel>(
159 kWiFiChannel5170 +
160 (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
161 } else if (kWiFiFrequency5240 <= frequency &&
162 frequency <= kWiFiFrequency5320) {
163 if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
164 channel = static_cast<WiFiChannel>(
165 kWiFiChannel5180 +
166 (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
167 } else if (kWiFiFrequency5500 <= frequency &&
168 frequency <= kWiFiFrequency5700) {
169 if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
170 channel = static_cast<WiFiChannel>(
171 kWiFiChannel5500 +
172 (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
173 } else if (kWiFiFrequency5745 <= frequency &&
174 frequency <= kWiFiFrequency5825) {
175 if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
176 channel = static_cast<WiFiChannel>(
177 kWiFiChannel5745 +
178 (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
179 }
180 CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
181
182 if (channel == kWiFiChannelUndef)
183 LOG(WARNING) << "no mapping for frequency " << frequency;
184 else
Ben Chanfad4a0b2012-04-18 15:49:59 -0700185 SLOG(Metrics, 3) << "map " << frequency << " to " << channel;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000186
187 return channel;
188}
189
Thieu Lead1ec2c2012-01-05 23:39:48 +0000190// static
191Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
192 const std::string &security) {
193 if (security == flimflam::kSecurityNone) {
194 return kWiFiSecurityNone;
195 } else if (security == flimflam::kSecurityWep) {
196 return kWiFiSecurityWep;
197 } else if (security == flimflam::kSecurityWpa) {
198 return kWiFiSecurityWpa;
199 } else if (security == flimflam::kSecurityRsn) {
200 return kWiFiSecurityRsn;
201 } else if (security == flimflam::kSecurity8021x) {
202 return kWiFiSecurity8021x;
203 } else if (security == flimflam::kSecurityPsk) {
204 return kWiFiSecurityPsk;
205 } else {
206 return kWiFiSecurityUnknown;
207 }
208}
209
Thieu Le85e050b2012-03-13 15:04:38 -0700210// static
211Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
212 const PortalDetector::Result &result) {
213 DCHECK(result.final);
214 PortalResult retval = kPortalResultUnknown;
215 // The only time we should end a successful portal detection is when we're
216 // in the Content phase. If we end with kStatusSuccess in any other phase,
217 // then this indicates that something bad has happened.
218 switch (result.phase) {
219 case PortalDetector::kPhaseDNS:
220 if (result.status == PortalDetector::kStatusFailure)
221 retval = kPortalResultDNSFailure;
222 else if (result.status == PortalDetector::kStatusTimeout)
223 retval = kPortalResultDNSTimeout;
224 else
225 LOG(DFATAL) << __func__ << ": Final result status " << result.status
226 << " is not allowed in the DNS phase";
227 break;
228
229 case PortalDetector::kPhaseConnection:
230 if (result.status == PortalDetector::kStatusFailure)
231 retval = kPortalResultConnectionFailure;
232 else if (result.status == PortalDetector::kStatusTimeout)
233 retval = kPortalResultConnectionTimeout;
234 else
235 LOG(DFATAL) << __func__ << ": Final result status " << result.status
236 << " is not allowed in the Connection phase";
237 break;
238
239 case PortalDetector::kPhaseHTTP:
240 if (result.status == PortalDetector::kStatusFailure)
241 retval = kPortalResultHTTPFailure;
242 else if (result.status == PortalDetector::kStatusTimeout)
243 retval = kPortalResultHTTPTimeout;
244 else
245 LOG(DFATAL) << __func__ << ": Final result status " << result.status
246 << " is not allowed in the HTTP phase";
247 break;
248
249 case PortalDetector::kPhaseContent:
250 if (result.status == PortalDetector::kStatusSuccess)
251 retval = kPortalResultSuccess;
252 else if (result.status == PortalDetector::kStatusFailure)
253 retval = kPortalResultContentFailure;
254 else if (result.status == PortalDetector::kStatusTimeout)
255 retval = kPortalResultContentTimeout;
256 else
257 LOG(DFATAL) << __func__ << ": Final result status " << result.status
258 << " is not allowed in the Content phase";
259 break;
260
261 case PortalDetector::kPhaseUnknown:
262 retval = kPortalResultUnknown;
263 break;
264
265 default:
266 LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
267 break;
268 }
269
270 return retval;
271}
272
Thieu Le48e6d6d2011-12-06 00:40:27 +0000273void Metrics::RegisterService(const Service *service) {
274 shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
275 services_metrics_[service] = service_metrics;
276 service_metrics->service = service;
277 InitializeCommonServiceMetrics(service);
278 service->InitializeCustomMetrics();
279}
280
281void Metrics::DeregisterService(const Service *service) {
282 services_metrics_.erase(service);
283}
284
285void Metrics::AddServiceStateTransitionTimer(
286 const Service *service,
287 const string &histogram_name,
288 Service::ConnectState start_state,
289 Service::ConnectState stop_state) {
290 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
291 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700292 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000293 DCHECK(false);
294 return;
295 }
296 ServiceMetrics *service_metrics = it->second.get();
297 CHECK(start_state < stop_state);
298 chromeos_metrics::TimerReporter *timer =
299 new chromeos_metrics::TimerReporter(histogram_name,
Thieu Lea20cbc22012-01-09 22:01:43 +0000300 kTimerHistogramMillisecondsMin,
301 kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000302 kTimerHistogramNumBuckets);
303 service_metrics->timers.push_back(timer); // passes ownership.
304 service_metrics->start_on_state[start_state].push_back(timer);
305 service_metrics->stop_on_state[stop_state].push_back(timer);
306}
307
Thieu Lea20cbc22012-01-09 22:01:43 +0000308void Metrics::NotifyDefaultServiceChanged(const Service *service) {
309 base::TimeDelta elapsed_seconds;
310
311 Technology::Identifier technology = (service) ? service->technology() :
312 Technology::kUnknown;
313 if (technology != last_default_technology_) {
314 if (last_default_technology_ != Technology::kUnknown) {
315 string histogram = GetFullMetricName(kMetricTimeOnlineSeconds,
316 last_default_technology_);
317 time_online_timer_->GetElapsedTime(&elapsed_seconds);
318 SendToUMA(histogram,
319 elapsed_seconds.InSeconds(),
320 kMetricTimeOnlineSecondsMin,
321 kMetricTimeOnlineSecondsMax,
322 kTimerHistogramNumBuckets);
323 }
324 last_default_technology_ = technology;
325 time_online_timer_->Start();
326 }
327
Thieu Lea20cbc22012-01-09 22:01:43 +0000328 // Ignore changes that are not online/offline transitions; e.g.
329 // switching between wired and wireless. TimeToDrop measures
330 // time online regardless of how we are connected.
331 if ((service == NULL && !was_online_) || (service != NULL && was_online_))
332 return;
333
334 if (service == NULL) {
335 time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
336 SendToUMA(kMetricTimeToDropSeconds,
337 elapsed_seconds.InSeconds(),
338 kMetricTimeToDropSecondsMin,
339 kMetricTimeToDropSecondsMax,
340 kTimerHistogramNumBuckets);
341 } else {
342 time_to_drop_timer_->Start();
343 }
344
345 was_online_ = (service != NULL);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000346}
347
348void Metrics::NotifyServiceStateChanged(const Service *service,
349 Service::ConnectState new_state) {
350 ServiceMetricsLookupMap::iterator it = services_metrics_.find(service);
351 if (it == services_metrics_.end()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700352 SLOG(Metrics, 1) << "service not found";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000353 DCHECK(false);
354 return;
355 }
356 ServiceMetrics *service_metrics = it->second.get();
357 UpdateServiceStateTransitionMetrics(service_metrics, new_state);
358
359 if (new_state == Service::kStateFailure)
360 SendServiceFailure(service);
361
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200362 if (collect_bootstats_) {
363 bootstat_log(
364 StringPrintf("network-%s-%s",
365 Technology::NameFromIdentifier(
366 service->technology()).c_str(),
367 service->GetStateString().c_str()).c_str());
368 }
369
Paul Stewart20088d82012-02-16 06:58:55 -0800370 if (new_state != Service::kStateConnected)
Thieu Le48e6d6d2011-12-06 00:40:27 +0000371 return;
372
Thieu Leb84ba342012-03-02 15:15:19 -0800373 base::TimeDelta time_resume_to_ready;
374 time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
375 time_resume_to_ready_timer_->Reset();
376 service->SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
Thieu Le48e6d6d2011-12-06 00:40:27 +0000377}
378
379string Metrics::GetFullMetricName(const char *metric_name,
380 Technology::Identifier technology_id) {
381 string technology = Technology::NameFromIdentifier(technology_id);
382 technology[0] = base::ToUpperASCII(technology[0]);
383 return base::StringPrintf(metric_name, technology.c_str());
384}
385
Thieu Le67370f62012-02-14 23:01:42 +0000386void Metrics::NotifyServiceDisconnect(const Service *service) {
387 Technology::Identifier technology = service->technology();
388 string histogram = GetFullMetricName(kMetricDisconnect, technology);
389 SendToUMA(histogram,
390 service->explicitly_disconnected(),
391 kMetricDisconnectMin,
392 kMetricDisconnectMax,
393 kMetricDisconnectNumBuckets);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000394}
395
Thieu Leb84ba342012-03-02 15:15:19 -0800396void Metrics::NotifyPowerStateChange(PowerManager::SuspendState new_state) {
397 if (new_state == PowerManagerProxyDelegate::kOn) {
398 time_resume_to_ready_timer_->Start();
399 } else {
400 time_resume_to_ready_timer_->Reset();
401 }
Thieu Le48e6d6d2011-12-06 00:40:27 +0000402}
403
Paul Stewartff845fc2012-08-07 07:28:44 -0700404void Metrics::NotifyLinkMonitorFailure(
Paul Stewart0443aa52012-08-09 10:43:50 -0700405 Technology::Identifier technology,
406 LinkMonitorFailure failure,
407 unsigned int seconds_to_failure,
408 unsigned int broadcast_error_count,
409 unsigned int unicast_error_count) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700410 string histogram = GetFullMetricName(kMetricLinkMonitorFailure,
411 technology);
412 SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
Paul Stewart0443aa52012-08-09 10:43:50 -0700413
414 if (failure == kLinkMonitorFailureThresholdReached) {
415 if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
416 seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
417 }
418 histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailure,
419 technology);
420 SendToUMA(histogram,
421 seconds_to_failure,
422 kMetricLinkMonitorSecondsToFailureMin,
423 kMetricLinkMonitorSecondsToFailureMax,
424 kMetricLinkMonitorSecondsToFailureNumBuckets);
425 histogram = GetFullMetricName(kMetricLinkMonitorBroadcastErrorsAtFailure,
426 technology);
427 SendToUMA(histogram,
428 broadcast_error_count,
429 kMetricLinkMonitorErrorCountMin,
430 kMetricLinkMonitorErrorCountMax,
431 kMetricLinkMonitorErrorCountNumBuckets);
432 histogram = GetFullMetricName(kMetricLinkMonitorUnicastErrorsAtFailure,
433 technology);
434 SendToUMA(histogram,
435 unicast_error_count,
436 kMetricLinkMonitorErrorCountMin,
437 kMetricLinkMonitorErrorCountMax,
438 kMetricLinkMonitorErrorCountNumBuckets);
439 }
Paul Stewartff845fc2012-08-07 07:28:44 -0700440}
441
442void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
443 Technology::Identifier technology,
444 unsigned int response_time_milliseconds) {
445 string histogram = GetFullMetricName(kMetricLinkMonitorResponseTimeSample,
446 technology);
447 SendToUMA(histogram,
448 response_time_milliseconds,
449 kMetricLinkMonitorResponseTimeSampleMin,
450 kMetricLinkMonitorResponseTimeSampleMax,
451 kMetricLinkMonitorResponseTimeSampleNumBuckets);
452}
453
Thieu Le48e6d6d2011-12-06 00:40:27 +0000454bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
455 return library_->SendEnumToUMA(name, sample, max);
456}
457
Thieu Lea20cbc22012-01-09 22:01:43 +0000458bool Metrics::SendToUMA(const string &name, int sample, int min, int max,
459 int num_buckets) {
460 return library_->SendToUMA(name, sample, min, max, num_buckets);
461}
462
Thieu Le48e6d6d2011-12-06 00:40:27 +0000463void Metrics::InitializeCommonServiceMetrics(const Service *service) {
464 Technology::Identifier technology = service->technology();
465 string histogram = GetFullMetricName(kMetricTimeToConfigMilliseconds,
466 technology);
467 AddServiceStateTransitionTimer(
468 service,
469 histogram,
470 Service::kStateConfiguring,
Paul Stewart20088d82012-02-16 06:58:55 -0800471 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000472 histogram = GetFullMetricName(kMetricTimeToPortalMilliseconds, technology);
473 AddServiceStateTransitionTimer(
474 service,
475 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800476 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000477 Service::kStatePortal);
478 histogram = GetFullMetricName(kMetricTimeToOnlineMilliseconds, technology);
479 AddServiceStateTransitionTimer(
480 service,
481 histogram,
Paul Stewart20088d82012-02-16 06:58:55 -0800482 Service::kStateConnected,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000483 Service::kStateOnline);
484}
485
486void Metrics::UpdateServiceStateTransitionMetrics(
487 ServiceMetrics *service_metrics,
488 Service::ConnectState new_state) {
489 TimerReportersList::iterator it;
490 TimerReportersList &start_timers = service_metrics->start_on_state[new_state];
491 for (it = start_timers.begin(); it != start_timers.end(); ++it)
492 (*it)->Start();
493
494 TimerReportersList &stop_timers = service_metrics->stop_on_state[new_state];
495 for (it = stop_timers.begin(); it != stop_timers.end(); ++it) {
496 (*it)->Stop();
497 (*it)->ReportMilliseconds();
498 }
499}
500
501void Metrics::SendServiceFailure(const Service *service) {
502 library_->SendEnumToUMA(kMetricNetworkServiceErrors,
503 service->failure(),
504 kMetricNetworkServiceErrorsMax);
505}
506
507void Metrics::set_library(MetricsLibraryInterface *library) {
508 chromeos_metrics::TimerReporter::set_metrics_lib(library);
509 library_ = library;
510}
511
512} // namespace shill