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

Side by Side Diff: metrics_daemon.cc

Issue 2864009: Log active use time between kernel crashes. (Closed) Base URL: ssh://git@chromiumos-git/metrics.git
Patch Set: Fix potential memory leaks and usage of freed resources. Created 10 years, 6 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
« no previous file with comments | « metrics_daemon.h ('k') | metrics_daemon_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 6
7 #include <dbus/dbus-glib-lowlevel.h> 7 #include <dbus/dbus-glib-lowlevel.h>
8 8
9 #include <base/file_util.h>
9 #include <base/logging.h> 10 #include <base/logging.h>
10 11
11 #include "counter.h" 12 #include "counter.h"
12 13
13 using base::Time; 14 using base::Time;
14 using base::TimeDelta; 15 using base::TimeDelta;
15 using base::TimeTicks; 16 using base::TimeTicks;
17 using std::string;
16 18
17 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error") 19 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
18 #define DBUS_IFACE_CRASH_REPORTER "org.chromium.CrashReporter" 20 #define DBUS_IFACE_CRASH_REPORTER "org.chromium.CrashReporter"
19 #define DBUS_IFACE_FLIMFLAM_MANAGER "org.chromium.flimflam.Manager" 21 #define DBUS_IFACE_FLIMFLAM_MANAGER "org.chromium.flimflam.Manager"
20 #define DBUS_IFACE_POWER_MANAGER "org.chromium.PowerManager" 22 #define DBUS_IFACE_POWER_MANAGER "org.chromium.PowerManager"
21 #define DBUS_IFACE_SESSION_MANAGER "org.chromium.SessionManagerInterface" 23 #define DBUS_IFACE_SESSION_MANAGER "org.chromium.SessionManagerInterface"
22 24
23 // File to aggregate daily usage before sending to UMA.
24 // TODO(petkov): This file should probably live in a user-specific stateful
25 // location, e.g., /home/chronos/user.
26 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
27 static const char kUserCrashIntervalRecordFile[] =
28 "/var/log/metrics/user-crash-interval";
29
30 static const int kSecondsPerMinute = 60; 25 static const int kSecondsPerMinute = 60;
31 static const int kMinutesPerHour = 60; 26 static const int kMinutesPerHour = 60;
32 static const int kHoursPerDay = 24; 27 static const int kHoursPerDay = 24;
33 static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour; 28 static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
34 static const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay; 29 static const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
35 static const int kDaysPerWeek = 7; 30 static const int kDaysPerWeek = 7;
36 static const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek; 31 static const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
37 32
38 // The daily use monitor is scheduled to a 1-minute interval after 33 // The daily use monitor is scheduled to a 1-minute interval after
39 // initial user activity and then it's exponentially backed off to 34 // initial user activity and then it's exponentially backed off to
40 // 10-minute intervals. Although not required, the back off is 35 // 10-minute intervals. Although not required, the back off is
41 // implemented because the histogram buckets are spaced exponentially 36 // implemented because the histogram buckets are spaced exponentially
42 // anyway and to avoid too frequent metrics daemon process wake-ups 37 // anyway and to avoid too frequent metrics daemon process wake-ups
43 // and file I/O. 38 // and file I/O.
44 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute; 39 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute;
45 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute; 40 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute;
46 41
47 // static metrics parameters. 42 // static metrics parameters.
48 const char MetricsDaemon::kMetricDailyUseTimeName[] = 43 const char MetricsDaemon::kMetricDailyUseTimeName[] =
49 "Logging.DailyUseTime"; 44 "Logging.DailyUseTime";
50 const int MetricsDaemon::kMetricDailyUseTimeMin = 1; 45 const int MetricsDaemon::kMetricDailyUseTimeMin = 1;
51 const int MetricsDaemon::kMetricDailyUseTimeMax = kMinutesPerDay; 46 const int MetricsDaemon::kMetricDailyUseTimeMax = kMinutesPerDay;
52 const int MetricsDaemon::kMetricDailyUseTimeBuckets = 50; 47 const int MetricsDaemon::kMetricDailyUseTimeBuckets = 50;
53 48
49 const char MetricsDaemon::kMetricKernelCrashIntervalName[] =
50 "Logging.KernelCrashInterval";
51 const int MetricsDaemon::kMetricKernelCrashIntervalMin = 1;
52 const int MetricsDaemon::kMetricKernelCrashIntervalMax = 4 * kSecondsPerWeek;
53 const int MetricsDaemon::kMetricKernelCrashIntervalBuckets = 50;
54
54 const char MetricsDaemon::kMetricTimeToNetworkDropName[] = 55 const char MetricsDaemon::kMetricTimeToNetworkDropName[] =
55 "Network.TimeToDrop"; 56 "Network.TimeToDrop";
56 const int MetricsDaemon::kMetricTimeToNetworkDropMin = 1; 57 const int MetricsDaemon::kMetricTimeToNetworkDropMin = 1;
57 const int MetricsDaemon::kMetricTimeToNetworkDropMax = 58 const int MetricsDaemon::kMetricTimeToNetworkDropMax =
58 8 /* hours */ * kMinutesPerHour * kSecondsPerMinute; 59 8 /* hours */ * kMinutesPerHour * kSecondsPerMinute;
59 const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50; 60 const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50;
60 61
61 const char MetricsDaemon::kMetricUserCrashIntervalName[] = 62 const char MetricsDaemon::kMetricUserCrashIntervalName[] =
62 "Logging.UserCrashInterval"; 63 "Logging.UserCrashInterval";
63 const int MetricsDaemon::kMetricUserCrashIntervalMin = 1; 64 const int MetricsDaemon::kMetricUserCrashIntervalMin = 1;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 #define STATE(name, capname) #name, 100 #define STATE(name, capname) #name,
100 #include "power_states.h" 101 #include "power_states.h"
101 }; 102 };
102 103
103 // static 104 // static
104 const char* MetricsDaemon::kSessionStates_[] = { 105 const char* MetricsDaemon::kSessionStates_[] = {
105 #define STATE(name, capname) #name, 106 #define STATE(name, capname) #name,
106 #include "session_states.h" 107 #include "session_states.h"
107 }; 108 };
108 109
110 // Invokes a remote method over D-Bus that takes no input arguments
111 // and returns a string result. The method call is issued with a 2
112 // second blocking timeout. Returns an empty string on failure or
113 // timeout.
114 static string DBusGetString(DBusConnection* connection,
115 const string& destination,
116 const string& path,
117 const string& interface,
118 const string& method) {
119 DBusMessage* message =
120 dbus_message_new_method_call(destination.c_str(),
121 path.c_str(),
122 interface.c_str(),
123 method.c_str());
124 if (!message) {
125 DLOG(WARNING) << "DBusGetString: unable to allocate a message";
126 return "";
127 }
128
129 DBusError error;
130 dbus_error_init(&error);
131 const int kTimeout = 2000; // ms
132 DLOG(INFO) << "DBusGetString: dest=" << destination << " path=" << path
133 << " iface=" << interface << " method=" << method;
134 DBusMessage* reply =
135 dbus_connection_send_with_reply_and_block(connection, message, kTimeout,
136 &error);
137 dbus_message_unref(message);
138 if (dbus_error_is_set(&error) || !reply) {
139 DLOG(WARNING) << "DBusGetString: call failed";
140 return "";
141 }
142 DBusMessageIter iter;
143 dbus_message_iter_init(reply, &iter);
144 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
145 NOTREACHED();
146 dbus_message_unref(reply);
147 return "";
148 }
149 const char* c_result = "";
150 dbus_message_iter_get_basic(&iter, &c_result);
151 string result = c_result;
152 DLOG(INFO) << "DBusGetString: result=" << result;
153 dbus_message_unref(reply);
154 return result;
155 }
156
109 MetricsDaemon::MetricsDaemon() 157 MetricsDaemon::MetricsDaemon()
110 : network_state_(kUnknownNetworkState), 158 : network_state_(kUnknownNetworkState),
111 power_state_(kUnknownPowerState), 159 power_state_(kUnknownPowerState),
112 session_state_(kUnknownSessionState), 160 session_state_(kUnknownSessionState),
113 user_active_(false), 161 user_active_(false),
114 usemon_interval_(0), 162 usemon_interval_(0),
115 usemon_source_(NULL) {} 163 usemon_source_(NULL) {}
116 164
117 MetricsDaemon::~MetricsDaemon() {} 165 MetricsDaemon::~MetricsDaemon() {}
118 166
119 void MetricsDaemon::Run(bool run_as_daemon) { 167 void MetricsDaemon::Run(bool run_as_daemon) {
120 if (!run_as_daemon || daemon(0, 0) == 0) { 168 if (run_as_daemon && daemon(0, 0) != 0)
121 Loop(); 169 return;
122 } 170
171 static const char kKernelCrashDetectedFile[] = "/tmp/kernel-crash-detected";
172 CheckKernelCrash(kKernelCrashDetectedFile);
173 Loop();
123 } 174 }
124 175
125 void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) { 176 void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) {
126 testing_ = testing; 177 testing_ = testing;
127 DCHECK(metrics_lib != NULL); 178 DCHECK(metrics_lib != NULL);
128 metrics_lib_ = metrics_lib; 179 metrics_lib_ = metrics_lib;
180
181 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
129 daily_use_.reset(new chromeos_metrics::TaggedCounter()); 182 daily_use_.reset(new chromeos_metrics::TaggedCounter());
130 daily_use_->Init(kDailyUseRecordFile, &DailyUseReporter, this); 183 daily_use_->Init(kDailyUseRecordFile, &DailyUseReporter, this);
184
185 static const char kUserCrashIntervalRecordFile[] =
186 "/var/log/metrics/user-crash-interval";
131 user_crash_interval_.reset(new chromeos_metrics::TaggedCounter()); 187 user_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
132 user_crash_interval_->Init(kUserCrashIntervalRecordFile, 188 user_crash_interval_->Init(kUserCrashIntervalRecordFile,
133 &UserCrashIntervalReporter, this); 189 &UserCrashIntervalReporter, this);
134 190
191 static const char kKernelCrashIntervalRecordFile[] =
192 "/var/log/metrics/kernel-crash-interval";
193 kernel_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
194 kernel_crash_interval_->Init(kKernelCrashIntervalRecordFile,
195 &KernelCrashIntervalReporter, this);
196
135 // Don't setup D-Bus and GLib in test mode. 197 // Don't setup D-Bus and GLib in test mode.
136 if (testing) 198 if (testing)
137 return; 199 return;
138 200
139 g_thread_init(NULL); 201 g_thread_init(NULL);
140 g_type_init(); 202 g_type_init();
141 dbus_g_thread_init(); 203 dbus_g_thread_init();
142 204
143 DBusError error; 205 DBusError error;
144 dbus_error_init(&error); 206 dbus_error_init(&error);
(...skipping 10 matching lines...) Expand all
155 DLOG(INFO) << "adding dbus match: " << match; 217 DLOG(INFO) << "adding dbus match: " << match;
156 dbus_bus_add_match(connection, match, &error); 218 dbus_bus_add_match(connection, match, &error);
157 LOG_IF(FATAL, dbus_error_is_set(&error)) << 219 LOG_IF(FATAL, dbus_error_is_set(&error)) <<
158 "unable to add a match: " << SAFE_MESSAGE(error); 220 "unable to add a match: " << SAFE_MESSAGE(error);
159 } 221 }
160 222
161 // Adds the D-Bus filter routine to be called back whenever one of 223 // Adds the D-Bus filter routine to be called back whenever one of
162 // the registered D-Bus matches is successful. The daemon is not 224 // the registered D-Bus matches is successful. The daemon is not
163 // activated for D-Bus messages that don't match. 225 // activated for D-Bus messages that don't match.
164 CHECK(dbus_connection_add_filter(connection, MessageFilter, this, NULL)); 226 CHECK(dbus_connection_add_filter(connection, MessageFilter, this, NULL));
227
228 // Initializes the current network state by retrieving it from flimflam.
229 string state_name = DBusGetString(connection, "org.chromium.flimflam", "/",
230 DBUS_IFACE_FLIMFLAM_MANAGER, "GetState");
231 NetStateChanged(state_name.c_str(), TimeTicks::Now());
165 } 232 }
166 233
167 void MetricsDaemon::Loop() { 234 void MetricsDaemon::Loop() {
168 GMainLoop* loop = g_main_loop_new(NULL, false); 235 GMainLoop* loop = g_main_loop_new(NULL, false);
169 g_main_loop_run(loop); 236 g_main_loop_run(loop);
170 } 237 }
171 238
172 // static 239 // static
173 DBusHandlerResult MetricsDaemon::MessageFilter(DBusConnection* connection, 240 DBusHandlerResult MetricsDaemon::MessageFilter(DBusConnection* connection,
174 DBusMessage* message, 241 DBusMessage* message,
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 TimeDelta since_active = now - user_active_last_; 380 TimeDelta since_active = now - user_active_last_;
314 if (since_active < TimeDelta::FromSeconds( 381 if (since_active < TimeDelta::FromSeconds(
315 kUseMonitorIntervalMax + kSecondsPerMinute)) { 382 kUseMonitorIntervalMax + kSecondsPerMinute)) {
316 seconds = static_cast<int>(since_active.InSeconds()); 383 seconds = static_cast<int>(since_active.InSeconds());
317 } 384 }
318 } 385 }
319 TimeDelta since_epoch = now - Time(); 386 TimeDelta since_epoch = now - Time();
320 int day = since_epoch.InDays(); 387 int day = since_epoch.InDays();
321 daily_use_->Update(day, seconds); 388 daily_use_->Update(day, seconds);
322 user_crash_interval_->Update(0, seconds); 389 user_crash_interval_->Update(0, seconds);
390 kernel_crash_interval_->Update(0, seconds);
323 391
324 // Schedules a use monitor on inactive->active transitions and 392 // Schedules a use monitor on inactive->active transitions and
325 // unschedules it on active->inactive transitions. 393 // unschedules it on active->inactive transitions.
326 if (!user_active_ && active) 394 if (!user_active_ && active)
327 ScheduleUseMonitor(kUseMonitorIntervalInit, /* backoff */ false); 395 ScheduleUseMonitor(kUseMonitorIntervalInit, /* backoff */ false);
328 else if (user_active_ && !active) 396 else if (user_active_ && !active)
329 UnscheduleUseMonitor(); 397 UnscheduleUseMonitor();
330 398
331 // Remembers the current active state and the time of the last 399 // Remembers the current active state and the time of the last
332 // activity update. 400 // activity update.
333 user_active_ = active; 401 user_active_ = active;
334 user_active_last_ = now; 402 user_active_last_ = now;
335 } 403 }
336 404
337 void MetricsDaemon::ProcessUserCrash() { 405 void MetricsDaemon::ProcessUserCrash() {
338 // Counts the active use time up to now. 406 // Counts the active use time up to now.
339 SetUserActiveState(user_active_, Time::Now()); 407 SetUserActiveState(user_active_, Time::Now());
340 408
341 // Reports the active use time since the last crash and resets it. 409 // Reports the active use time since the last crash and resets it.
342 user_crash_interval_->Flush(); 410 user_crash_interval_->Flush();
343 } 411 }
344 412
413 void MetricsDaemon::ProcessKernelCrash() {
414 // Counts the active use time up to now.
415 SetUserActiveState(user_active_, Time::Now());
416
417 // Reports the active use time since the last crash and resets it.
418 kernel_crash_interval_->Flush();
419 }
420
421 void MetricsDaemon::CheckKernelCrash(const std::string& crash_file) {
422 FilePath crash_detected(crash_file);
423 if (!file_util::PathExists(crash_detected))
424 return;
425
426 ProcessKernelCrash();
427
428 // Deletes the crash-detected file so that the daemon doesn't report
429 // another kernel crash in case it's restarted.
430 file_util::Delete(crash_detected,
431 false); // recursive
432 }
433
345 // static 434 // static
346 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) { 435 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) {
347 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE; 436 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE;
348 } 437 }
349 438
350 bool MetricsDaemon::UseMonitor() { 439 bool MetricsDaemon::UseMonitor() {
351 SetUserActiveState(user_active_, Time::Now()); 440 SetUserActiveState(user_active_, Time::Now());
352 441
353 // If a new monitor source/instance is scheduled, returns false to 442 // If a new monitor source/instance is scheduled, returns false to
354 // tell GLib to destroy this monitor source/instance. Returns true 443 // tell GLib to destroy this monitor source/instance. Returns true
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 // static 507 // static
419 void MetricsDaemon::UserCrashIntervalReporter(void* handle, 508 void MetricsDaemon::UserCrashIntervalReporter(void* handle,
420 int tag, int count) { 509 int tag, int count) {
421 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle); 510 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
422 daemon->SendMetric(kMetricUserCrashIntervalName, count, 511 daemon->SendMetric(kMetricUserCrashIntervalName, count,
423 kMetricUserCrashIntervalMin, 512 kMetricUserCrashIntervalMin,
424 kMetricUserCrashIntervalMax, 513 kMetricUserCrashIntervalMax,
425 kMetricUserCrashIntervalBuckets); 514 kMetricUserCrashIntervalBuckets);
426 } 515 }
427 516
428 void MetricsDaemon::SendMetric(const std::string& name, int sample, 517 // static
518 void MetricsDaemon::KernelCrashIntervalReporter(void* handle,
519 int tag, int count) {
520 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
521 daemon->SendMetric(kMetricKernelCrashIntervalName, count,
522 kMetricKernelCrashIntervalMin,
523 kMetricKernelCrashIntervalMax,
524 kMetricKernelCrashIntervalBuckets);
525 }
526
527 void MetricsDaemon::SendMetric(const string& name, int sample,
429 int min, int max, int nbuckets) { 528 int min, int max, int nbuckets) {
430 DLOG(INFO) << "received metric: " << name << " " << sample << " " 529 DLOG(INFO) << "received metric: " << name << " " << sample << " "
431 << min << " " << max << " " << nbuckets; 530 << min << " " << max << " " << nbuckets;
432 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets); 531 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets);
433 } 532 }
OLDNEW
« no previous file with comments | « metrics_daemon.h ('k') | metrics_daemon_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698