Chromium Code Reviews| Index: metrics_daemon.cc |
| diff --git a/metrics_daemon.cc b/metrics_daemon.cc |
| index a5059d9832bff092d4000a82746ba799f8759172..287555ad0c99c47391de6cf63019d5e68b7e0ad2 100644 |
| --- a/metrics_daemon.cc |
| +++ b/metrics_daemon.cc |
| @@ -4,6 +4,7 @@ |
| #include "metrics_daemon.h" |
| +#include <fcntl.h> |
| #include <string.h> |
| #include <base/file_util.h> |
| @@ -84,6 +85,26 @@ const char MetricsDaemon::kMetricCrashFrequencyMin = 1; |
| const char MetricsDaemon::kMetricCrashFrequencyMax = 100; |
| const char MetricsDaemon::kMetricCrashFrequencyBuckets = 50; |
| +// disk stats metrics |
| +const char MetricsDaemon::kMetricReadSectorsLongName[] = |
| + "Platform.ReadSectorsLong"; |
|
petkov
2011/02/11 06:42:30
maybe add a comment about the units -- sectors/sec
|
| +const char MetricsDaemon::kMetricWriteSectorsLongName[] = |
| + "Platform.WriteSectorsLong"; |
| +const char MetricsDaemon::kMetricReadSectorsShortName[] = |
| + "Platform.ReadSectorsShort"; |
| +const char MetricsDaemon::kMetricWriteSectorsShortName[] = |
| + "Platform.WriteSectorsShort"; |
| + |
| +const int MetricsDaemon::kMetricDiskStatsShortInterval = 1; // seconds |
|
petkov
2011/02/11 06:42:30
just two spaces before //
|
| +const int MetricsDaemon::kMetricDiskStatsLongInterval = 30; // seconds |
| + |
| +// Assume a max rate of 250Mb/s for reads, worse for writes. |
| +const int MetricsDaemon::kMetricSectorsIOMax = 500000; |
| +const int MetricsDaemon::kMetricSectorsBuckets = 50; |
| + |
| +// Path to disk stats. |
| +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.
|
| + |
| // persistent metrics path |
| const char MetricsDaemon::kMetricsPath[] = "/var/log/metrics"; |
| @@ -218,6 +239,8 @@ void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) { |
| ConfigureCrashFrequencyReporter(kMetricUserCrashesDailyName); |
| ConfigureCrashFrequencyReporter(kMetricUserCrashesWeeklyName); |
| + DiskStatsReporterInit(); |
| + |
| // Don't setup D-Bus and GLib in test mode. |
| if (testing) |
| return; |
| @@ -494,6 +517,97 @@ void MetricsDaemon::UnscheduleUseMonitor() { |
| usemon_interval_ = 0; |
| } |
| +void MetricsDaemon::DiskStatsReporterInit() { |
| + diskstats_source_ = NULL; |
| + DiskStatsReadStats(&read_sectors_, &write_sectors_); |
| + // The first time around just run the long stat, so we don't delay boot. |
| + diskstats_state_ = kDiskStatsLong; |
| + ScheduleDiskStatsCallback(kMetricDiskStatsLongInterval); |
| +} |
| + |
| +void MetricsDaemon::ScheduleDiskStatsCallback(int wait) { |
| + 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!
|
| + g_source_set_callback(diskstats_source_, DiskStatsCallbackStatic, this, NULL); |
| + g_source_attach(diskstats_source_, NULL); |
| +} |
| + |
| +void MetricsDaemon::DiskStatsReadStats(long int* read_sectors, |
| + long int* write_sectors) { |
| + int nchars; |
| + int nitems; |
| + char line[200]; |
| + 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.
|
| + 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.
|
| + << strerror(errno); |
| + nchars = read(file, line, sizeof(line)); |
| + LOG_IF(FATAL, nchars == sizeof(line)) << "line too long in " |
| + << kMetricsDiskStatsPath; |
| + line[nchars] = '\0'; |
| + nitems = sscanf(line, "%*d %*d %ld %*d %*d %*d %ld", |
| + read_sectors, write_sectors); |
| + LOG_IF(FATAL, nitems != 2) << "found " << nitems << " in " |
| + << kMetricsDiskStatsPath << ", expected 2"; |
| + close(file); |
| +} |
| + |
| +// static |
| +gboolean MetricsDaemon::DiskStatsCallbackStatic(void* handle) { |
| + (static_cast<MetricsDaemon*>(handle))->DiskStatsCallback(); |
| + return false; // destroy this source instance |
|
petkov
2011/02/11 06:42:30
just 2 spaces before //
|
| +} |
| + |
| +void MetricsDaemon::DiskStatsCallback() { |
| + long int read_sectors_now, write_sectors_now; |
| + DiskStatsReadStats(&read_sectors_now, &write_sectors_now); |
| + |
| + switch (diskstats_state_) { |
| + |
| + 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
|
| + SendMetric(kMetricReadSectorsShortName, |
| + (int) (read_sectors_now - read_sectors_) / |
| + kMetricDiskStatsShortInterval, |
| + 0, |
| + kMetricSectorsIOMax, |
| + kMetricSectorsBuckets); |
| + SendMetric(kMetricWriteSectorsShortName, |
| + (int) (write_sectors_now - write_sectors_) / |
| + kMetricDiskStatsShortInterval, |
| + 0, |
| + kMetricSectorsIOMax, |
| + kMetricSectorsBuckets); |
| + // Schedule long callback. |
| + diskstats_state_ = kDiskStatsLong; |
| + ScheduleDiskStatsCallback(kMetricDiskStatsLongInterval - |
| + kMetricDiskStatsShortInterval); |
| + break; |
| + |
| + case kDiskStatsLong: |
| + SendMetric(kMetricReadSectorsLongName, |
| + (int) (read_sectors_now - read_sectors_) / |
| + kMetricDiskStatsLongInterval, |
| + 0, |
| + kMetricSectorsIOMax, |
| + kMetricSectorsBuckets); |
| + SendMetric(kMetricWriteSectorsLongName, |
| + (int) (write_sectors_now - write_sectors_) / |
| + kMetricDiskStatsLongInterval, |
| + 0, |
| + kMetricSectorsIOMax, |
| + kMetricSectorsBuckets); |
| + // Reset sector counters |
| + read_sectors_ = read_sectors_now; |
| + write_sectors_ = write_sectors_now; |
| + |
| + // Schedule short callback. |
| + diskstats_state_ = kDiskStatsShort; |
| + ScheduleDiskStatsCallback(kMetricDiskStatsShortInterval); |
| + break; |
| + |
| + default: |
| + LOG(FATAL) << "Invalid disk stats state"; |
| + } |
| +} |
| + |
| // static |
| void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) { |
| if (count <= 0) |