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

Side by Side Diff: metrics_daemon.cc

Issue 2736008: Measure and report time between user-space process crashes. (Closed) Base URL: ssh://git@chromiumos-git/metrics.git
Patch Set: No need to start the back off again on crashes. 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/logging.h> 9 #include <base/logging.h>
10 10
11 #include "counter.h" 11 #include "counter.h"
12 12
13 using base::Time; 13 using base::Time;
14 using base::TimeDelta; 14 using base::TimeDelta;
15 using base::TimeTicks; 15 using base::TimeTicks;
16 16
17 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error") 17 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
18 #define DBUS_IFACE_CRASH_REPORTER "org.chromium.CrashReporter"
18 #define DBUS_IFACE_FLIMFLAM_MANAGER "org.chromium.flimflam.Manager" 19 #define DBUS_IFACE_FLIMFLAM_MANAGER "org.chromium.flimflam.Manager"
19 #define DBUS_IFACE_POWER_MANAGER "org.chromium.PowerManager" 20 #define DBUS_IFACE_POWER_MANAGER "org.chromium.PowerManager"
20 #define DBUS_IFACE_SESSION_MANAGER "org.chromium.SessionManagerInterface" 21 #define DBUS_IFACE_SESSION_MANAGER "org.chromium.SessionManagerInterface"
21 22
22 // File to aggregate daily usage before sending to UMA. 23 // File to aggregate daily usage before sending to UMA.
23 // TODO(petkov): This file should probably live in a user-specific stateful 24 // TODO(petkov): This file should probably live in a user-specific stateful
24 // location, e.g., /home/chronos/user. 25 // location, e.g., /home/chronos/user.
25 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage"; 26 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
27 static const char kUserCrashIntervalRecordFile[] =
28 "/var/log/metrics/user-crash-interval";
26 29
27 static const int kSecondsPerMinute = 60; 30 static const int kSecondsPerMinute = 60;
28 static const int kMinutesPerHour = 60; 31 static const int kMinutesPerHour = 60;
29 static const int kHoursPerDay = 24; 32 static const int kHoursPerDay = 24;
30 static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour; 33 static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
34 static const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
35 static const int kDaysPerWeek = 7;
36 static const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
31 37
32 // The daily use monitor is scheduled to a 1-minute interval after 38 // The daily use monitor is scheduled to a 1-minute interval after
33 // initial user activity and then it's exponentially backed off to 39 // initial user activity and then it's exponentially backed off to
34 // 10-minute intervals. Although not required, the back off is 40 // 10-minute intervals. Although not required, the back off is
35 // implemented because the histogram buckets are spaced exponentially 41 // implemented because the histogram buckets are spaced exponentially
36 // anyway and to avoid too frequent metrics daemon process wake-ups 42 // anyway and to avoid too frequent metrics daemon process wake-ups
37 // and file I/O. 43 // and file I/O.
38 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute; 44 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute;
39 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute; 45 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute;
40 46
41 // static metrics parameters. 47 // static metrics parameters.
42 const char MetricsDaemon::kMetricDailyUseTimeName[] = 48 const char MetricsDaemon::kMetricDailyUseTimeName[] =
43 "Logging.DailyUseTime"; 49 "Logging.DailyUseTime";
44 const int MetricsDaemon::kMetricDailyUseTimeMin = 1; 50 const int MetricsDaemon::kMetricDailyUseTimeMin = 1;
45 const int MetricsDaemon::kMetricDailyUseTimeMax = kMinutesPerDay; 51 const int MetricsDaemon::kMetricDailyUseTimeMax = kMinutesPerDay;
46 const int MetricsDaemon::kMetricDailyUseTimeBuckets = 50; 52 const int MetricsDaemon::kMetricDailyUseTimeBuckets = 50;
47 53
48 const char MetricsDaemon::kMetricTimeToNetworkDropName[] = 54 const char MetricsDaemon::kMetricTimeToNetworkDropName[] =
49 "Network.TimeToDrop"; 55 "Network.TimeToDrop";
50 const int MetricsDaemon::kMetricTimeToNetworkDropMin = 1; 56 const int MetricsDaemon::kMetricTimeToNetworkDropMin = 1;
51 const int MetricsDaemon::kMetricTimeToNetworkDropMax = 57 const int MetricsDaemon::kMetricTimeToNetworkDropMax =
52 8 /* hours */ * kMinutesPerHour * kSecondsPerMinute; 58 8 /* hours */ * kMinutesPerHour * kSecondsPerMinute;
53 const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50; 59 const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50;
54 60
61 const char MetricsDaemon::kMetricUserCrashIntervalName[] =
62 "Logging.UserCrashInterval";
63 const int MetricsDaemon::kMetricUserCrashIntervalMin = 1;
64 const int MetricsDaemon::kMetricUserCrashIntervalMax = 4 * kSecondsPerWeek;
65 const int MetricsDaemon::kMetricUserCrashIntervalBuckets = 50;
66
55 // static 67 // static
56 const char* MetricsDaemon::kDBusMatches_[] = { 68 const char* MetricsDaemon::kDBusMatches_[] = {
57 "type='signal'," 69 "type='signal',"
70 "interface='" DBUS_IFACE_CRASH_REPORTER "',"
71 "path='/',"
72 "member='UserCrash'",
73
74 "type='signal',"
58 "sender='org.chromium.flimflam'," 75 "sender='org.chromium.flimflam',"
59 "interface='" DBUS_IFACE_FLIMFLAM_MANAGER "'," 76 "interface='" DBUS_IFACE_FLIMFLAM_MANAGER "',"
60 "path='/'," 77 "path='/',"
61 "member='StateChanged'", 78 "member='StateChanged'",
62 79
63 "type='signal'," 80 "type='signal',"
64 "interface='" DBUS_IFACE_POWER_MANAGER "'," 81 "interface='" DBUS_IFACE_POWER_MANAGER "',"
65 "path='/'", 82 "path='/'",
66 83
67 "type='signal'," 84 "type='signal',"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 Loop(); 121 Loop();
105 } 122 }
106 } 123 }
107 124
108 void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) { 125 void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) {
109 testing_ = testing; 126 testing_ = testing;
110 DCHECK(metrics_lib != NULL); 127 DCHECK(metrics_lib != NULL);
111 metrics_lib_ = metrics_lib; 128 metrics_lib_ = metrics_lib;
112 daily_use_.reset(new chromeos_metrics::TaggedCounter()); 129 daily_use_.reset(new chromeos_metrics::TaggedCounter());
113 daily_use_->Init(kDailyUseRecordFile, &DailyUseReporter, this); 130 daily_use_->Init(kDailyUseRecordFile, &DailyUseReporter, this);
131 user_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
132 user_crash_interval_->Init(kUserCrashIntervalRecordFile,
133 &UserCrashIntervalReporter, this);
114 134
115 // Don't setup D-Bus and GLib in test mode. 135 // Don't setup D-Bus and GLib in test mode.
116 if (testing) 136 if (testing)
117 return; 137 return;
118 138
119 g_thread_init(NULL); 139 g_thread_init(NULL);
120 g_type_init(); 140 g_type_init();
121 dbus_g_thread_init(); 141 dbus_g_thread_init();
122 142
123 DBusError error; 143 DBusError error;
124 dbus_error_init(&error); 144 dbus_error_init(&error);
125 145
126 DBusConnection* connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); 146 DBusConnection* connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
127 LOG_IF(FATAL, dbus_error_is_set(&error)) << 147 LOG_IF(FATAL, dbus_error_is_set(&error)) <<
128 "No D-Bus connection: " << SAFE_MESSAGE(error); 148 "No D-Bus connection: " << SAFE_MESSAGE(error);
129 149
130 dbus_connection_setup_with_g_main(connection, NULL); 150 dbus_connection_setup_with_g_main(connection, NULL);
131 151
132 // Registers D-Bus matches for the signals we would like to catch. 152 // Registers D-Bus matches for the signals we would like to catch.
133 for (unsigned int m = 0; m < sizeof(kDBusMatches_) / sizeof(char*); m++) { 153 for (unsigned int m = 0; m < arraysize(kDBusMatches_); m++) {
134 const char* match = kDBusMatches_[m]; 154 const char* match = kDBusMatches_[m];
135 DLOG(INFO) << "adding dbus match: " << match; 155 DLOG(INFO) << "adding dbus match: " << match;
136 dbus_bus_add_match(connection, match, &error); 156 dbus_bus_add_match(connection, match, &error);
137 LOG_IF(FATAL, dbus_error_is_set(&error)) << 157 LOG_IF(FATAL, dbus_error_is_set(&error)) <<
138 "unable to add a match: " << SAFE_MESSAGE(error); 158 "unable to add a match: " << SAFE_MESSAGE(error);
139 } 159 }
140 160
141 // Adds the D-Bus filter routine to be called back whenever one of 161 // Adds the D-Bus filter routine to be called back whenever one of
142 // the registered D-Bus matches is successful. The daemon is not 162 // the registered D-Bus matches is successful. The daemon is not
143 // activated for D-Bus messages that don't match. 163 // activated for D-Bus messages that don't match.
(...skipping 20 matching lines...) Expand all
164 } 184 }
165 185
166 // Signal messages always have interfaces. 186 // Signal messages always have interfaces.
167 const char* interface = dbus_message_get_interface(message); 187 const char* interface = dbus_message_get_interface(message);
168 CHECK(interface != NULL); 188 CHECK(interface != NULL);
169 189
170 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(user_data); 190 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(user_data);
171 191
172 DBusMessageIter iter; 192 DBusMessageIter iter;
173 dbus_message_iter_init(message, &iter); 193 dbus_message_iter_init(message, &iter);
174 if (strcmp(interface, DBUS_IFACE_FLIMFLAM_MANAGER) == 0) { 194 if (strcmp(interface, DBUS_IFACE_CRASH_REPORTER) == 0) {
195 CHECK(strcmp(dbus_message_get_member(message),
196 "UserCrash") == 0);
197 daemon->ProcessUserCrash();
198 } else if (strcmp(interface, DBUS_IFACE_FLIMFLAM_MANAGER) == 0) {
175 CHECK(strcmp(dbus_message_get_member(message), 199 CHECK(strcmp(dbus_message_get_member(message),
176 "StateChanged") == 0); 200 "StateChanged") == 0);
177 201
178 char* state_name; 202 char* state_name;
179 dbus_message_iter_get_basic(&iter, &state_name); 203 dbus_message_iter_get_basic(&iter, &state_name);
180 daemon->NetStateChanged(state_name, ticks); 204 daemon->NetStateChanged(state_name, ticks);
181 } else if (strcmp(interface, DBUS_IFACE_POWER_MANAGER) == 0) { 205 } else if (strcmp(interface, DBUS_IFACE_POWER_MANAGER) == 0) {
182 const char* member = dbus_message_get_member(message); 206 const char* member = dbus_message_get_member(message);
183 if (strcmp(member, "ScreenIsLocked") == 0) { 207 if (strcmp(member, "ScreenIsLocked") == 0) {
184 daemon->SetUserActiveState(false, now); 208 daemon->SetUserActiveState(false, now);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 if (user_active_ && now > user_active_last_) { 312 if (user_active_ && now > user_active_last_) {
289 TimeDelta since_active = now - user_active_last_; 313 TimeDelta since_active = now - user_active_last_;
290 if (since_active < TimeDelta::FromSeconds( 314 if (since_active < TimeDelta::FromSeconds(
291 kUseMonitorIntervalMax + kSecondsPerMinute)) { 315 kUseMonitorIntervalMax + kSecondsPerMinute)) {
292 seconds = static_cast<int>(since_active.InSeconds()); 316 seconds = static_cast<int>(since_active.InSeconds());
293 } 317 }
294 } 318 }
295 TimeDelta since_epoch = now - Time(); 319 TimeDelta since_epoch = now - Time();
296 int day = since_epoch.InDays(); 320 int day = since_epoch.InDays();
297 daily_use_->Update(day, seconds); 321 daily_use_->Update(day, seconds);
322 user_crash_interval_->Update(0, seconds);
298 323
299 // Schedules a use monitor on inactive->active transitions and 324 // Schedules a use monitor on inactive->active transitions and
300 // unschedules it on active->inactive transitions. 325 // unschedules it on active->inactive transitions.
301 if (!user_active_ && active) 326 if (!user_active_ && active)
302 ScheduleUseMonitor(kUseMonitorIntervalInit, /* backoff */ false); 327 ScheduleUseMonitor(kUseMonitorIntervalInit, /* backoff */ false);
303 else if (user_active_ && !active) 328 else if (user_active_ && !active)
304 UnscheduleUseMonitor(); 329 UnscheduleUseMonitor();
305 330
306 // Remembers the current active state and the time of the last 331 // Remembers the current active state and the time of the last
307 // activity update. 332 // activity update.
308 user_active_ = active; 333 user_active_ = active;
309 user_active_last_ = now; 334 user_active_last_ = now;
310 } 335 }
311 336
337 void MetricsDaemon::ProcessUserCrash() {
338 // Counts the active use time up to now.
339 SetUserActiveState(user_active_, Time::Now());
340
341 // Reports the active use time since the last crash and resets it.
342 user_crash_interval_->Flush();
343 }
344
312 // static 345 // static
313 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) { 346 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) {
314 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE; 347 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE;
315 } 348 }
316 349
317 bool MetricsDaemon::UseMonitor() { 350 bool MetricsDaemon::UseMonitor() {
318 SetUserActiveState(user_active_, Time::Now()); 351 SetUserActiveState(user_active_, Time::Now());
319 352
320 // If a new monitor source/instance is scheduled, returns false to 353 // If a new monitor source/instance is scheduled, returns false to
321 // tell GLib to destroy this monitor source/instance. Returns true 354 // tell GLib to destroy this monitor source/instance. Returns true
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 return; 397 return;
365 398
366 DLOG(INFO) << "destroying use monitor"; 399 DLOG(INFO) << "destroying use monitor";
367 g_source_destroy(usemon_source_); 400 g_source_destroy(usemon_source_);
368 usemon_source_ = NULL; 401 usemon_source_ = NULL;
369 usemon_interval_ = 0; 402 usemon_interval_ = 0;
370 } 403 }
371 404
372 // static 405 // static
373 void MetricsDaemon::DailyUseReporter(void* handle, int tag, int count) { 406 void MetricsDaemon::DailyUseReporter(void* handle, int tag, int count) {
407 if (count <= 0)
408 return;
409
374 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle); 410 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
375 int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute; 411 int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute;
376 daemon->SendMetric(kMetricDailyUseTimeName, minutes, 412 daemon->SendMetric(kMetricDailyUseTimeName, minutes,
377 kMetricDailyUseTimeMin, 413 kMetricDailyUseTimeMin,
378 kMetricDailyUseTimeMax, 414 kMetricDailyUseTimeMax,
379 kMetricDailyUseTimeBuckets); 415 kMetricDailyUseTimeBuckets);
380 } 416 }
381 417
418 // static
419 void MetricsDaemon::UserCrashIntervalReporter(void* handle,
420 int tag, int count) {
421 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
422 daemon->SendMetric(kMetricUserCrashIntervalName, count,
423 kMetricUserCrashIntervalMin,
424 kMetricUserCrashIntervalMax,
425 kMetricUserCrashIntervalBuckets);
426 }
427
382 void MetricsDaemon::SendMetric(const std::string& name, int sample, 428 void MetricsDaemon::SendMetric(const std::string& name, int sample,
383 int min, int max, int nbuckets) { 429 int min, int max, int nbuckets) {
384 DLOG(INFO) << "received metric: " << name << " " << sample << " " 430 DLOG(INFO) << "received metric: " << name << " " << sample << " "
385 << min << " " << max << " " << nbuckets; 431 << min << " " << max << " " << nbuckets;
386 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets); 432 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets);
387 } 433 }
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