Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(353)

Side by Side Diff: src/platform/metrics/metrics_daemon.cc

Issue 1919005: Add some basic tests for metrics_daemon. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: Address review comments. Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "metrics_daemon.h" 5 #include "metrics_daemon.h"
6 #include "metrics_library.h" 6 #include "metrics_library.h"
7 7
8 #include <dbus/dbus-glib-lowlevel.h> 8 #include <dbus/dbus-glib-lowlevel.h>
9 #include <sys/file.h> 9 #include <sys/file.h>
10 10
(...skipping 19 matching lines...) Expand all
30 30
31 // The daily use monitor is scheduled to a 1-minute interval after 31 // The daily use monitor is scheduled to a 1-minute interval after
32 // initial user activity and then it's exponentially backed off to 32 // initial user activity and then it's exponentially backed off to
33 // 10-minute intervals. Although not required, the back off is 33 // 10-minute intervals. Although not required, the back off is
34 // implemented because the histogram buckets are spaced exponentially 34 // implemented because the histogram buckets are spaced exponentially
35 // anyway and to avoid too frequent metrics daemon process wake-ups 35 // anyway and to avoid too frequent metrics daemon process wake-ups
36 // and file I/O. 36 // and file I/O.
37 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute; 37 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute;
38 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute; 38 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute;
39 39
40 // static metrics parameters.
41 const char MetricsDaemon::kMetricDailyUseTimeName[] =
42 "Logging.DailyUseTime";
43 const int MetricsDaemon::kMetricDailyUseTimeMin = 1;
44 const int MetricsDaemon::kMetricDailyUseTimeMax = kMinutesPerDay;
45 const int MetricsDaemon::kMetricDailyUseTimeBuckets = 50;
46
47 const char MetricsDaemon::kMetricTimeToNetworkDropName[] =
48 "Network.TimeToDrop";
49 const int MetricsDaemon::kMetricTimeToNetworkDropMin = 1;
50 const int MetricsDaemon::kMetricTimeToNetworkDropMax =
51 8 /* hours */ * kMinutesPerHour * kSecondsPerMinute;
52 const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50;
53
40 // static 54 // static
41 const char* MetricsDaemon::kDBusMatches_[] = { 55 const char* MetricsDaemon::kDBusMatches_[] = {
42 "type='signal'," 56 "type='signal',"
43 "sender='org.moblin.connman'," 57 "sender='org.moblin.connman',"
44 "interface='" DBUS_IFACE_CONNMAN_MANAGER "'," 58 "interface='" DBUS_IFACE_CONNMAN_MANAGER "',"
45 "path='/'," 59 "path='/',"
46 "member='StateChanged'", 60 "member='StateChanged'",
47 61
48 "type='signal'," 62 "type='signal',"
49 "interface='" DBUS_IFACE_POWER_MANAGER "'," 63 "interface='" DBUS_IFACE_POWER_MANAGER "',"
(...skipping 29 matching lines...) Expand all
79 #define STATE(name, capname) #name, 93 #define STATE(name, capname) #name,
80 #include "screensaver_states.h" 94 #include "screensaver_states.h"
81 }; 95 };
82 96
83 // static 97 // static
84 const char* MetricsDaemon::kSessionStates_[] = { 98 const char* MetricsDaemon::kSessionStates_[] = {
85 #define STATE(name, capname) #name, 99 #define STATE(name, capname) #name,
86 #include "session_states.h" 100 #include "session_states.h"
87 }; 101 };
88 102
89 void MetricsDaemon::Run(bool run_as_daemon, bool testing) { 103 void MetricsDaemon::Run(bool run_as_daemon) {
90 Init(testing); 104 Init(false);
91 if (!run_as_daemon || daemon(0, 0) == 0) { 105 if (!run_as_daemon || daemon(0, 0) == 0) {
92 Loop(); 106 Loop();
93 } 107 }
94 } 108 }
95 109
96 void MetricsDaemon::Init(bool testing) { 110 void MetricsDaemon::Init(bool testing) {
97 testing_ = testing; 111 testing_ = testing;
112 daily_use_record_file_ = kDailyUseRecordFile;
113
114 // Don't setup D-Bus and GLib in test mode.
115 if (testing)
116 return;
98 117
99 g_thread_init(NULL); 118 g_thread_init(NULL);
100 g_type_init(); 119 g_type_init();
101 dbus_g_thread_init(); 120 dbus_g_thread_init();
102 121
103 DBusError error; 122 DBusError error;
104 dbus_error_init(&error); 123 dbus_error_init(&error);
105 124
106 DBusConnection *connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); 125 DBusConnection *connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
107 LOG_IF(FATAL, dbus_error_is_set(&error)) << 126 LOG_IF(FATAL, dbus_error_is_set(&error)) <<
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 204
186 return DBUS_HANDLER_RESULT_HANDLED; 205 return DBUS_HANDLER_RESULT_HANDLED;
187 } 206 }
188 207
189 void MetricsDaemon::NetStateChanged(const char* state_name, time_t now) { 208 void MetricsDaemon::NetStateChanged(const char* state_name, time_t now) {
190 DLOG(INFO) << "network state: " << state_name; 209 DLOG(INFO) << "network state: " << state_name;
191 210
192 NetworkState state = LookupNetworkState(state_name); 211 NetworkState state = LookupNetworkState(state_name);
193 212
194 // Logs the time in seconds between the network going online to 213 // Logs the time in seconds between the network going online to
195 // going offline in order to measure the mean time to network 214 // going offline (or, more precisely, going not online) in order to
196 // dropping. Going offline as part of suspend-to-RAM is not logged 215 // measure the mean time to network dropping. Going offline as part
197 // as network drop -- the assumption is that the message for 216 // of suspend-to-RAM is not logged as network drop -- the assumption
198 // suspend-to-RAM comes before the network offline message which 217 // is that the message for suspend-to-RAM comes before the network
199 // seems to and should be the case. 218 // offline message which seems to and should be the case.
200 if (state == kNetworkStateOffline && 219 if (state != kNetworkStateOnline &&
201 network_state_ == kNetworkStateOnline && 220 network_state_ == kNetworkStateOnline &&
202 power_state_ != kPowerStateMem) { 221 power_state_ != kPowerStateMem) {
203 int online_time = static_cast<int>(now - network_state_last_); 222 int online_time = static_cast<int>(now - network_state_last_);
204 PublishMetric("Network.TimeToDrop", online_time, 223 PublishMetric(kMetricTimeToNetworkDropName, online_time,
205 1, 8 /* hours */ * 60 * 60, 50); 224 kMetricTimeToNetworkDropMin,
225 kMetricTimeToNetworkDropMax,
226 kMetricTimeToNetworkDropBuckets);
206 } 227 }
207 228
208 network_state_ = state; 229 network_state_ = state;
209 network_state_last_ = now; 230 network_state_last_ = now;
210 } 231 }
211 232
212 MetricsDaemon::NetworkState 233 MetricsDaemon::NetworkState
213 MetricsDaemon::LookupNetworkState(const char* state_name) { 234 MetricsDaemon::LookupNetworkState(const char* state_name) {
214 for (int i = 0; i < kNumberNetworkStates; i++) { 235 for (int i = 0; i < kNumberNetworkStates; i++) {
215 if (strcmp(state_name, kNetworkStates_[i]) == 0) { 236 if (strcmp(state_name, kNetworkStates_[i]) == 0) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 user_active_last_ = now; 318 user_active_last_ = now;
298 } 319 }
299 320
300 void MetricsDaemon::LogDailyUseRecord(int day, int seconds) { 321 void MetricsDaemon::LogDailyUseRecord(int day, int seconds) {
301 // If there's no new active use today and the last record in the 322 // If there's no new active use today and the last record in the
302 // usage aggregation file is today, there's nothing to do. 323 // usage aggregation file is today, there's nothing to do.
303 if (seconds == 0 && day == daily_use_day_last_) 324 if (seconds == 0 && day == daily_use_day_last_)
304 return; 325 return;
305 326
306 DLOG(INFO) << "day: " << day << " usage: " << seconds << " seconds"; 327 DLOG(INFO) << "day: " << day << " usage: " << seconds << " seconds";
307 int fd = HANDLE_EINTR(open(kDailyUseRecordFile, 328 int fd = HANDLE_EINTR(open(daily_use_record_file_,
308 O_RDWR | O_CREAT, 329 O_RDWR | O_CREAT,
309 S_IRUSR | S_IWUSR)); 330 S_IRUSR | S_IWUSR));
310 if (fd < 0) { 331 if (fd < 0) {
311 DLOG(WARNING) << "Unable to open the daily use file."; 332 PLOG(WARNING) << "Unable to open the daily use file";
312 return; 333 return;
313 } 334 }
314 335
315 bool same_day = false; 336 bool same_day = false;
316 UseRecord record; 337 UseRecord record;
317 if (HANDLE_EINTR(read(fd, &record, sizeof(record))) == sizeof(record)) { 338 if (HANDLE_EINTR(read(fd, &record, sizeof(record))) == sizeof(record)) {
318 if (record.day_ == day) { 339 if (record.day_ == day) {
319 // If there's an existing record for today, aggregates the usage 340 // If there's an existing record for today, aggregates the usage
320 // time. 341 // time.
321 same_day = true; 342 same_day = true;
322 record.seconds_ += seconds; 343 record.seconds_ += seconds;
323 } else { 344 } else {
324 // If there's an existing record for a day in the past, rounds 345 // If there's an existing record for a day in the past, rounds
325 // the usage to the nearest minute and sends it to UMA. 346 // the usage to the nearest minute and sends it to UMA.
326 int minutes = 347 int minutes =
327 (record.seconds_ + kSecondsPerMinute / 2) / kSecondsPerMinute; 348 (record.seconds_ + kSecondsPerMinute / 2) / kSecondsPerMinute;
328 PublishMetric("Logging.DailyUseTime", 349 PublishMetric(kMetricDailyUseTimeName, minutes,
329 minutes, 1, kMinutesPerDay, 50); 350 kMetricDailyUseTimeMin,
351 kMetricDailyUseTimeMax,
352 kMetricDailyUseTimeBuckets);
330 353
331 // Truncates the usage file to ensure that no duplicate usage is 354 // Truncates the usage file to ensure that no duplicate usage is
332 // sent to UMA. 355 // sent to UMA.
333 LOG_IF(WARNING, HANDLE_EINTR(ftruncate(fd, 0)) != 0); 356 PLOG_IF(WARNING, HANDLE_EINTR(ftruncate(fd, 0)) != 0);
334 } 357 }
335 } 358 }
336 359
337 // Updates the use record in the daily usage file if there's new 360 // Updates the use record in the daily usage file if there's new
338 // usage today. 361 // usage today.
339 if (seconds > 0) { 362 if (seconds > 0) {
340 if (!same_day) { 363 if (!same_day) {
341 record.day_ = day; 364 record.day_ = day;
342 record.seconds_ = seconds; 365 record.seconds_ = seconds;
343 } 366 }
344 // else an already existing record for the same day will be 367 // else an already existing record for the same day will be
345 // overwritten with updated usage below. 368 // overwritten with updated usage below.
346 369
347 LOG_IF(WARNING, HANDLE_EINTR(lseek(fd, 0, SEEK_SET)) != 0); 370 PLOG_IF(WARNING, HANDLE_EINTR(lseek(fd, 0, SEEK_SET)) != 0);
348 LOG_IF(WARNING, 371 PLOG_IF(WARNING,
349 HANDLE_EINTR(write(fd, &record, sizeof(record))) != sizeof(record)); 372 HANDLE_EINTR(write(fd, &record, sizeof(record))) !=
373 sizeof(record));
350 } 374 }
351 375
352 HANDLE_EINTR(close(fd)); 376 HANDLE_EINTR(close(fd));
353 377
354 // Remembers the day of the use record in the usage aggregation file 378 // Remembers the day of the use record in the usage aggregation file
355 // to reduce file I/O. This is not really useful now but potentially 379 // to reduce file I/O. This is not really useful now but potentially
356 // allows frequent LogDailyUseRecord calls with no unnecessary I/O 380 // allows frequent LogDailyUseRecord calls with no unnecessary I/O
357 // overhead. 381 // overhead.
358 daily_use_day_last_ = day; 382 daily_use_day_last_ = day;
359 } 383 }
360 384
361 // static 385 // static
362 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) { 386 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) {
363 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE; 387 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE;
364 } 388 }
365 389
366 bool MetricsDaemon::UseMonitor() { 390 bool MetricsDaemon::UseMonitor() {
367 SetUserActiveState(user_active_, time(NULL)); 391 SetUserActiveState(user_active_, time(NULL));
368 392
369 // If a new monitor source/instance is scheduled, returns false to 393 // If a new monitor source/instance is scheduled, returns false to
370 // tell GLib to destroy this monitor source/instance. Returns true 394 // tell GLib to destroy this monitor source/instance. Returns true
371 // otherwise to keep calling back this monitor. 395 // otherwise to keep calling back this monitor.
372 return !ScheduleUseMonitor(usemon_interval_ * 2, /* backoff */ true); 396 return !ScheduleUseMonitor(usemon_interval_ * 2, /* backoff */ true);
373 } 397 }
374 398
375 bool MetricsDaemon::ScheduleUseMonitor(int interval, bool backoff) 399 bool MetricsDaemon::ScheduleUseMonitor(int interval, bool backoff)
376 { 400 {
401 if (testing_)
kmixter1 2010/05/10 19:06:31 Ideally you'd want to make this function available
402 return false;
403
377 // Caps the interval -- the bigger the interval, the more active use 404 // Caps the interval -- the bigger the interval, the more active use
378 // time will be potentially dropped on system shutdown. 405 // time will be potentially dropped on system shutdown.
379 if (interval > kUseMonitorIntervalMax) 406 if (interval > kUseMonitorIntervalMax)
380 interval = kUseMonitorIntervalMax; 407 interval = kUseMonitorIntervalMax;
381 408
382 if (backoff) { 409 if (backoff) {
383 // Back-off mode is used by the use monitor to reschedule itself 410 // Back-off mode is used by the use monitor to reschedule itself
384 // with exponential back-off in time. This mode doesn't create a 411 // with exponential back-off in time. This mode doesn't create a
385 // new timeout source if the new interval is the same as the old 412 // new timeout source if the new interval is the same as the old
386 // one. Also, if a new timeout source is created, the old one is 413 // one. Also, if a new timeout source is created, the old one is
(...skipping 23 matching lines...) Expand all
410 return; 437 return;
411 438
412 DLOG(INFO) << "destroying use monitor"; 439 DLOG(INFO) << "destroying use monitor";
413 g_source_destroy(usemon_source_); 440 g_source_destroy(usemon_source_);
414 usemon_source_ = NULL; 441 usemon_source_ = NULL;
415 usemon_interval_ = 0; 442 usemon_interval_ = 0;
416 } 443 }
417 444
418 void MetricsDaemon::PublishMetric(const char* name, int sample, 445 void MetricsDaemon::PublishMetric(const char* name, int sample,
419 int min, int max, int nbuckets) { 446 int min, int max, int nbuckets) {
420 DLOG(INFO) << "received metric: " << name << " " << sample << " " 447 LOG(INFO) << "received metric: " << name << " " << sample << " "
421 << min << " " << max << " " << nbuckets; 448 << min << " " << max << " " << nbuckets;
422 if (!testing_) { 449 if (!testing_) {
423 MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets); 450 MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets);
424 } 451 }
425 } 452 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698