OLD | NEW |
---|---|
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 <fcntl.h> | |
7 #include <string.h> | 8 #include <string.h> |
8 | 9 |
9 #include <base/file_util.h> | 10 #include <base/file_util.h> |
10 #include <base/logging.h> | 11 #include <base/logging.h> |
11 #include <dbus/dbus-glib-lowlevel.h> | 12 #include <dbus/dbus-glib-lowlevel.h> |
12 | 13 |
13 #include "counter.h" | 14 #include "counter.h" |
14 | 15 |
15 using base::Time; | 16 using base::Time; |
16 using base::TimeDelta; | 17 using base::TimeDelta; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 const char MetricsDaemon::kMetricUncleanShutdownsWeeklyName[] = | 78 const char MetricsDaemon::kMetricUncleanShutdownsWeeklyName[] = |
78 "Logging.UncleanShutdownsWeekly"; | 79 "Logging.UncleanShutdownsWeekly"; |
79 const char MetricsDaemon::kMetricUserCrashesDailyName[] = | 80 const char MetricsDaemon::kMetricUserCrashesDailyName[] = |
80 "Logging.UserCrashesDaily"; | 81 "Logging.UserCrashesDaily"; |
81 const char MetricsDaemon::kMetricUserCrashesWeeklyName[] = | 82 const char MetricsDaemon::kMetricUserCrashesWeeklyName[] = |
82 "Logging.UserCrashesWeekly"; | 83 "Logging.UserCrashesWeekly"; |
83 const char MetricsDaemon::kMetricCrashFrequencyMin = 1; | 84 const char MetricsDaemon::kMetricCrashFrequencyMin = 1; |
84 const char MetricsDaemon::kMetricCrashFrequencyMax = 100; | 85 const char MetricsDaemon::kMetricCrashFrequencyMax = 100; |
85 const char MetricsDaemon::kMetricCrashFrequencyBuckets = 50; | 86 const char MetricsDaemon::kMetricCrashFrequencyBuckets = 50; |
86 | 87 |
88 // disk stats metrics | |
89 const char MetricsDaemon::kMetricReadSectorsLongName[] = | |
90 "Platform.ReadSectorsLong"; | |
petkov
2011/02/11 06:42:30
maybe add a comment about the units -- sectors/sec
| |
91 const char MetricsDaemon::kMetricWriteSectorsLongName[] = | |
92 "Platform.WriteSectorsLong"; | |
93 const char MetricsDaemon::kMetricReadSectorsShortName[] = | |
94 "Platform.ReadSectorsShort"; | |
95 const char MetricsDaemon::kMetricWriteSectorsShortName[] = | |
96 "Platform.WriteSectorsShort"; | |
97 | |
98 const int MetricsDaemon::kMetricDiskStatsShortInterval = 1; // seconds | |
petkov
2011/02/11 06:42:30
just two spaces before //
| |
99 const int MetricsDaemon::kMetricDiskStatsLongInterval = 30; // seconds | |
100 | |
101 // Assume a max rate of 250Mb/s for reads, worse for writes. | |
102 const int MetricsDaemon::kMetricSectorsIOMax = 500000; | |
103 const int MetricsDaemon::kMetricSectorsBuckets = 50; | |
104 | |
105 // Path to disk stats. | |
106 const char MetricsDaemon::kMetricsDiskStatsPath[] = "/sys/class/block/sda/stat"; | |
petkov
2011/02/11 06:42:30
x86 specific... is it easy to make this work for A
Luigi Semenzato
2011/02/12 00:33:02
ARM uses the same path, at least on my machine.
| |
107 | |
87 // persistent metrics path | 108 // persistent metrics path |
88 const char MetricsDaemon::kMetricsPath[] = "/var/log/metrics"; | 109 const char MetricsDaemon::kMetricsPath[] = "/var/log/metrics"; |
89 | 110 |
90 | 111 |
91 // static | 112 // static |
92 const char* MetricsDaemon::kDBusMatches_[] = { | 113 const char* MetricsDaemon::kDBusMatches_[] = { |
93 "type='signal'," | 114 "type='signal'," |
94 "interface='" DBUS_IFACE_CRASH_REPORTER "'," | 115 "interface='" DBUS_IFACE_CRASH_REPORTER "'," |
95 "path='/'," | 116 "path='/'," |
96 "member='UserCrash'", | 117 "member='UserCrash'", |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 DeleteFrequencyCounters(); | 232 DeleteFrequencyCounters(); |
212 ConfigureCrashFrequencyReporter(kMetricAnyCrashesDailyName); | 233 ConfigureCrashFrequencyReporter(kMetricAnyCrashesDailyName); |
213 ConfigureCrashFrequencyReporter(kMetricAnyCrashesWeeklyName); | 234 ConfigureCrashFrequencyReporter(kMetricAnyCrashesWeeklyName); |
214 ConfigureCrashFrequencyReporter(kMetricKernelCrashesDailyName); | 235 ConfigureCrashFrequencyReporter(kMetricKernelCrashesDailyName); |
215 ConfigureCrashFrequencyReporter(kMetricKernelCrashesWeeklyName); | 236 ConfigureCrashFrequencyReporter(kMetricKernelCrashesWeeklyName); |
216 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsDailyName); | 237 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsDailyName); |
217 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsWeeklyName); | 238 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsWeeklyName); |
218 ConfigureCrashFrequencyReporter(kMetricUserCrashesDailyName); | 239 ConfigureCrashFrequencyReporter(kMetricUserCrashesDailyName); |
219 ConfigureCrashFrequencyReporter(kMetricUserCrashesWeeklyName); | 240 ConfigureCrashFrequencyReporter(kMetricUserCrashesWeeklyName); |
220 | 241 |
242 DiskStatsReporterInit(); | |
243 | |
221 // Don't setup D-Bus and GLib in test mode. | 244 // Don't setup D-Bus and GLib in test mode. |
222 if (testing) | 245 if (testing) |
223 return; | 246 return; |
224 | 247 |
225 g_thread_init(NULL); | 248 g_thread_init(NULL); |
226 g_type_init(); | 249 g_type_init(); |
227 dbus_g_thread_init(); | 250 dbus_g_thread_init(); |
228 | 251 |
229 DBusError error; | 252 DBusError error; |
230 dbus_error_init(&error); | 253 dbus_error_init(&error); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
487 // If there's a use monitor scheduled already, destroys it. | 510 // If there's a use monitor scheduled already, destroys it. |
488 if (usemon_source_ == NULL) | 511 if (usemon_source_ == NULL) |
489 return; | 512 return; |
490 | 513 |
491 DLOG(INFO) << "destroying use monitor"; | 514 DLOG(INFO) << "destroying use monitor"; |
492 g_source_destroy(usemon_source_); | 515 g_source_destroy(usemon_source_); |
493 usemon_source_ = NULL; | 516 usemon_source_ = NULL; |
494 usemon_interval_ = 0; | 517 usemon_interval_ = 0; |
495 } | 518 } |
496 | 519 |
520 void MetricsDaemon::DiskStatsReporterInit() { | |
521 diskstats_source_ = NULL; | |
522 DiskStatsReadStats(&read_sectors_, &write_sectors_); | |
523 // The first time around just run the long stat, so we don't delay boot. | |
524 diskstats_state_ = kDiskStatsLong; | |
525 ScheduleDiskStatsCallback(kMetricDiskStatsLongInterval); | |
526 } | |
527 | |
528 void MetricsDaemon::ScheduleDiskStatsCallback(int wait) { | |
529 diskstats_source_ = g_timeout_source_new_seconds(wait); | |
petkov
2011/02/11 06:42:30
You don't really need to store the source for this
Luigi Semenzato
2011/02/12 00:33:02
Splendid, thanks!
| |
530 g_source_set_callback(diskstats_source_, DiskStatsCallbackStatic, this, NULL); | |
531 g_source_attach(diskstats_source_, NULL); | |
532 } | |
533 | |
534 void MetricsDaemon::DiskStatsReadStats(long int* read_sectors, | |
535 long int* write_sectors) { | |
536 int nchars; | |
537 int nitems; | |
538 char line[200]; | |
539 int file = open(kMetricsDiskStatsPath, O_RDONLY); | |
petkov
2011/02/11 06:42:30
want to use HANDLE_EINTR macro here and below for
Luigi Semenzato
2011/02/12 00:33:02
Thanks, good suggestion.
| |
540 LOG_IF(FATAL, file < 0) << "cannot open " << kMetricsDiskStatsPath << ": " | |
petkov
2011/02/11 06:42:30
FATAL? This would cause the process to crash every
Luigi Semenzato
2011/02/12 00:33:02
You are completely right. Making non-fatal.
| |
541 << strerror(errno); | |
542 nchars = read(file, line, sizeof(line)); | |
543 LOG_IF(FATAL, nchars == sizeof(line)) << "line too long in " | |
544 << kMetricsDiskStatsPath; | |
545 line[nchars] = '\0'; | |
546 nitems = sscanf(line, "%*d %*d %ld %*d %*d %*d %ld", | |
547 read_sectors, write_sectors); | |
548 LOG_IF(FATAL, nitems != 2) << "found " << nitems << " in " | |
549 << kMetricsDiskStatsPath << ", expected 2"; | |
550 close(file); | |
551 } | |
552 | |
553 // static | |
554 gboolean MetricsDaemon::DiskStatsCallbackStatic(void* handle) { | |
555 (static_cast<MetricsDaemon*>(handle))->DiskStatsCallback(); | |
556 return false; // destroy this source instance | |
petkov
2011/02/11 06:42:30
just 2 spaces before //
| |
557 } | |
558 | |
559 void MetricsDaemon::DiskStatsCallback() { | |
560 long int read_sectors_now, write_sectors_now; | |
561 DiskStatsReadStats(&read_sectors_now, &write_sectors_now); | |
562 | |
563 switch (diskstats_state_) { | |
564 | |
565 case kDiskStatsShort: | |
petkov
2011/02/11 06:42:30
per style, case needs to be 2-space indented relat
Luigi Semenzato
2011/02/12 00:33:02
I was overriding some indentation variables by mis
| |
566 SendMetric(kMetricReadSectorsShortName, | |
567 (int) (read_sectors_now - read_sectors_) / | |
568 kMetricDiskStatsShortInterval, | |
569 0, | |
570 kMetricSectorsIOMax, | |
571 kMetricSectorsBuckets); | |
572 SendMetric(kMetricWriteSectorsShortName, | |
573 (int) (write_sectors_now - write_sectors_) / | |
574 kMetricDiskStatsShortInterval, | |
575 0, | |
576 kMetricSectorsIOMax, | |
577 kMetricSectorsBuckets); | |
578 // Schedule long callback. | |
579 diskstats_state_ = kDiskStatsLong; | |
580 ScheduleDiskStatsCallback(kMetricDiskStatsLongInterval - | |
581 kMetricDiskStatsShortInterval); | |
582 break; | |
583 | |
584 case kDiskStatsLong: | |
585 SendMetric(kMetricReadSectorsLongName, | |
586 (int) (read_sectors_now - read_sectors_) / | |
587 kMetricDiskStatsLongInterval, | |
588 0, | |
589 kMetricSectorsIOMax, | |
590 kMetricSectorsBuckets); | |
591 SendMetric(kMetricWriteSectorsLongName, | |
592 (int) (write_sectors_now - write_sectors_) / | |
593 kMetricDiskStatsLongInterval, | |
594 0, | |
595 kMetricSectorsIOMax, | |
596 kMetricSectorsBuckets); | |
597 // Reset sector counters | |
598 read_sectors_ = read_sectors_now; | |
599 write_sectors_ = write_sectors_now; | |
600 | |
601 // Schedule short callback. | |
602 diskstats_state_ = kDiskStatsShort; | |
603 ScheduleDiskStatsCallback(kMetricDiskStatsShortInterval); | |
604 break; | |
605 | |
606 default: | |
607 LOG(FATAL) << "Invalid disk stats state"; | |
608 } | |
609 } | |
610 | |
497 // static | 611 // static |
498 void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) { | 612 void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) { |
499 if (count <= 0) | 613 if (count <= 0) |
500 return; | 614 return; |
501 | 615 |
502 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle); | 616 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle); |
503 int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute; | 617 int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute; |
504 daemon->SendMetric(kMetricDailyUseTimeName, minutes, | 618 daemon->SendMetric(kMetricDailyUseTimeName, minutes, |
505 kMetricDailyUseTimeMin, | 619 kMetricDailyUseTimeMin, |
506 kMetricDailyUseTimeMax, | 620 kMetricDailyUseTimeMax, |
507 kMetricDailyUseTimeBuckets); | 621 kMetricDailyUseTimeBuckets); |
508 } | 622 } |
509 | 623 |
510 void MetricsDaemon::SendMetric(const string& name, int sample, | 624 void MetricsDaemon::SendMetric(const string& name, int sample, |
511 int min, int max, int nbuckets) { | 625 int min, int max, int nbuckets) { |
512 DLOG(INFO) << "received metric: " << name << " " << sample << " " | 626 DLOG(INFO) << "received metric: " << name << " " << sample << " " |
513 << min << " " << max << " " << nbuckets; | 627 << min << " " << max << " " << nbuckets; |
514 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets); | 628 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets); |
515 } | 629 } |
OLD | NEW |