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

Side by Side Diff: metrics_daemon.cc

Issue 6486021: Collect some disk statistics. (Closed) Base URL: http://git.chromium.org/git/metrics.git@master
Patch Set: Change metrix prefix Filesystem back to Platform Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « metrics_daemon.h ('k') | metrics_daemon_main.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 <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
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
90 // The {Read,Write}Sectors numbers are in sectors/second.
91 // A sector is usually 512 bytes.
92
93 const char MetricsDaemon::kMetricReadSectorsLongName[] =
94 "Platform.ReadSectorsLong";
95 const char MetricsDaemon::kMetricWriteSectorsLongName[] =
96 "Platform.WriteSectorsLong";
97 const char MetricsDaemon::kMetricReadSectorsShortName[] =
98 "Platform.ReadSectorsShort";
99 const char MetricsDaemon::kMetricWriteSectorsShortName[] =
100 "Platform.WriteSectorsShort";
101
102 const int MetricsDaemon::kMetricDiskStatsShortInterval = 1; // seconds
103 const int MetricsDaemon::kMetricDiskStatsLongInterval = 30; // seconds
104
105 // Assume a max rate of 250Mb/s for reads (worse for writes) and 512 byte
106 // sectors.
107 const int MetricsDaemon::kMetricSectorsIOMax = 500000; // sectors/second
108 const int MetricsDaemon::kMetricSectorsBuckets = 50; // buckets
109
87 // persistent metrics path 110 // persistent metrics path
88 const char MetricsDaemon::kMetricsPath[] = "/var/log/metrics"; 111 const char MetricsDaemon::kMetricsPath[] = "/var/log/metrics";
89 112
90 113
91 // static 114 // static
92 const char* MetricsDaemon::kDBusMatches_[] = { 115 const char* MetricsDaemon::kDBusMatches_[] = {
93 "type='signal'," 116 "type='signal',"
94 "interface='" DBUS_IFACE_CRASH_REPORTER "'," 117 "interface='" DBUS_IFACE_CRASH_REPORTER "',"
95 "path='/'," 118 "path='/',"
96 "member='UserCrash'", 119 "member='UserCrash'",
(...skipping 19 matching lines...) Expand all
116 const char* MetricsDaemon::kSessionStates_[] = { 139 const char* MetricsDaemon::kSessionStates_[] = {
117 #define STATE(name, capname) #name, 140 #define STATE(name, capname) #name,
118 #include "session_states.h" 141 #include "session_states.h"
119 }; 142 };
120 143
121 MetricsDaemon::MetricsDaemon() 144 MetricsDaemon::MetricsDaemon()
122 : power_state_(kUnknownPowerState), 145 : power_state_(kUnknownPowerState),
123 session_state_(kUnknownSessionState), 146 session_state_(kUnknownSessionState),
124 user_active_(false), 147 user_active_(false),
125 usemon_interval_(0), 148 usemon_interval_(0),
126 usemon_source_(NULL) {} 149 usemon_source_(NULL),
150 diskstats_path_(NULL) {}
127 151
128 MetricsDaemon::~MetricsDaemon() { 152 MetricsDaemon::~MetricsDaemon() {
129 DeleteFrequencyCounters(); 153 DeleteFrequencyCounters();
130 } 154 }
131 155
132 void MetricsDaemon::DeleteFrequencyCounters() { 156 void MetricsDaemon::DeleteFrequencyCounters() {
133 for (FrequencyCounters::iterator i = frequency_counters_.begin(); 157 for (FrequencyCounters::iterator i = frequency_counters_.begin();
134 i != frequency_counters_.end(); ++i) { 158 i != frequency_counters_.end(); ++i) {
135 delete i->second; 159 delete i->second;
136 i->second = NULL; 160 i->second = NULL;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 time_t cycle_duration = strstr(histogram_name, "Weekly") != NULL ? 207 time_t cycle_duration = strstr(histogram_name, "Weekly") != NULL ?
184 chromeos_metrics::kSecondsPerWeek : 208 chromeos_metrics::kSecondsPerWeek :
185 chromeos_metrics::kSecondsPerDay; 209 chromeos_metrics::kSecondsPerDay;
186 new_counter->Init( 210 new_counter->Init(
187 static_cast<chromeos_metrics::TaggedCounterInterface*>( 211 static_cast<chromeos_metrics::TaggedCounterInterface*>(
188 reporter.release()), 212 reporter.release()),
189 cycle_duration); 213 cycle_duration);
190 frequency_counters_[histogram_name] = new_counter.release(); 214 frequency_counters_[histogram_name] = new_counter.release();
191 } 215 }
192 216
193 void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) { 217 void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib,
218 const char* diskstats_path) {
194 testing_ = testing; 219 testing_ = testing;
195 DCHECK(metrics_lib != NULL); 220 DCHECK(metrics_lib != NULL);
196 metrics_lib_ = metrics_lib; 221 metrics_lib_ = metrics_lib;
197 chromeos_metrics::TaggedCounterReporter:: 222 chromeos_metrics::TaggedCounterReporter::
198 SetMetricsLibraryInterface(metrics_lib); 223 SetMetricsLibraryInterface(metrics_lib);
199 224
200 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage"; 225 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
201 daily_use_.reset(new chromeos_metrics::TaggedCounter()); 226 daily_use_.reset(new chromeos_metrics::TaggedCounter());
202 daily_use_->Init(kDailyUseRecordFile, &ReportDailyUse, this); 227 daily_use_->Init(kDailyUseRecordFile, &ReportDailyUse, this);
203 228
204 ConfigureCrashIntervalReporter(kMetricKernelCrashIntervalName, 229 ConfigureCrashIntervalReporter(kMetricKernelCrashIntervalName,
205 &kernel_crash_interval_); 230 &kernel_crash_interval_);
206 ConfigureCrashIntervalReporter(kMetricUncleanShutdownIntervalName, 231 ConfigureCrashIntervalReporter(kMetricUncleanShutdownIntervalName,
207 &unclean_shutdown_interval_); 232 &unclean_shutdown_interval_);
208 ConfigureCrashIntervalReporter(kMetricUserCrashIntervalName, 233 ConfigureCrashIntervalReporter(kMetricUserCrashIntervalName,
209 &user_crash_interval_); 234 &user_crash_interval_);
210 235
211 DeleteFrequencyCounters(); 236 DeleteFrequencyCounters();
212 ConfigureCrashFrequencyReporter(kMetricAnyCrashesDailyName); 237 ConfigureCrashFrequencyReporter(kMetricAnyCrashesDailyName);
213 ConfigureCrashFrequencyReporter(kMetricAnyCrashesWeeklyName); 238 ConfigureCrashFrequencyReporter(kMetricAnyCrashesWeeklyName);
214 ConfigureCrashFrequencyReporter(kMetricKernelCrashesDailyName); 239 ConfigureCrashFrequencyReporter(kMetricKernelCrashesDailyName);
215 ConfigureCrashFrequencyReporter(kMetricKernelCrashesWeeklyName); 240 ConfigureCrashFrequencyReporter(kMetricKernelCrashesWeeklyName);
216 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsDailyName); 241 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsDailyName);
217 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsWeeklyName); 242 ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsWeeklyName);
218 ConfigureCrashFrequencyReporter(kMetricUserCrashesDailyName); 243 ConfigureCrashFrequencyReporter(kMetricUserCrashesDailyName);
219 ConfigureCrashFrequencyReporter(kMetricUserCrashesWeeklyName); 244 ConfigureCrashFrequencyReporter(kMetricUserCrashesWeeklyName);
220 245
246 diskstats_path_ = diskstats_path;
247 DiskStatsReporterInit();
248
221 // Don't setup D-Bus and GLib in test mode. 249 // Don't setup D-Bus and GLib in test mode.
222 if (testing) 250 if (testing)
223 return; 251 return;
224 252
225 g_thread_init(NULL); 253 g_thread_init(NULL);
226 g_type_init(); 254 g_type_init();
227 dbus_g_thread_init(); 255 dbus_g_thread_init();
228 256
229 DBusError error; 257 DBusError error;
230 dbus_error_init(&error); 258 dbus_error_init(&error);
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 // If there's a use monitor scheduled already, destroys it. 515 // If there's a use monitor scheduled already, destroys it.
488 if (usemon_source_ == NULL) 516 if (usemon_source_ == NULL)
489 return; 517 return;
490 518
491 DLOG(INFO) << "destroying use monitor"; 519 DLOG(INFO) << "destroying use monitor";
492 g_source_destroy(usemon_source_); 520 g_source_destroy(usemon_source_);
493 usemon_source_ = NULL; 521 usemon_source_ = NULL;
494 usemon_interval_ = 0; 522 usemon_interval_ = 0;
495 } 523 }
496 524
525 void MetricsDaemon::DiskStatsReporterInit() {
526 DiskStatsReadStats(&read_sectors_, &write_sectors_);
527 // The first time around just run the long stat, so we don't delay boot.
528 diskstats_state_ = kDiskStatsLong;
529 ScheduleDiskStatsCallback(kMetricDiskStatsLongInterval);
530 }
531
532 void MetricsDaemon::ScheduleDiskStatsCallback(int wait) {
533 if (testing_) {
534 return;
535 }
536 g_timeout_add_seconds(wait, DiskStatsCallbackStatic, this);
537 }
538
539 void MetricsDaemon::DiskStatsReadStats(long int* read_sectors,
540 long int* write_sectors) {
541 int nchars;
542 int nitems;
543 char line[200];
544 int file = HANDLE_EINTR(open(diskstats_path_, O_RDONLY));
545 if (file < 0) {
546 PLOG(WARNING) << "cannot open " << diskstats_path_;
547 return;
548 }
549 nchars = HANDLE_EINTR(read(file, line, sizeof(line)));
550 if (nchars < 0) {
551 PLOG(WARNING) << "cannot read from " << diskstats_path_;
552 } else {
553 LOG_IF(WARNING, nchars == sizeof(line)) << "line too long in "
554 << diskstats_path_;
555 line[nchars] = '\0';
556 nitems = sscanf(line, "%*d %*d %ld %*d %*d %*d %ld",
557 read_sectors, write_sectors);
558 LOG_IF(WARNING, nitems != 2) << "found " << nitems << " items in "
559 << diskstats_path_ << ", expected 2";
560 }
561 HANDLE_EINTR(close(file));
562 }
563
564 // static
565 gboolean MetricsDaemon::DiskStatsCallbackStatic(void* handle) {
566 (static_cast<MetricsDaemon*>(handle))->DiskStatsCallback();
567 return false; // one-time callback
568 }
569
570 void MetricsDaemon::DiskStatsCallback() {
571 long int read_sectors_now, write_sectors_now;
572 DiskStatsReadStats(&read_sectors_now, &write_sectors_now);
573
574 switch (diskstats_state_) {
575 case kDiskStatsShort:
576 SendMetric(kMetricReadSectorsShortName,
577 (int) (read_sectors_now - read_sectors_) /
578 kMetricDiskStatsShortInterval,
579 1,
580 kMetricSectorsIOMax,
581 kMetricSectorsBuckets);
582 SendMetric(kMetricWriteSectorsShortName,
583 (int) (write_sectors_now - write_sectors_) /
584 kMetricDiskStatsShortInterval,
585 1,
586 kMetricSectorsIOMax,
587 kMetricSectorsBuckets);
588 // Schedule long callback.
589 diskstats_state_ = kDiskStatsLong;
590 ScheduleDiskStatsCallback(kMetricDiskStatsLongInterval -
591 kMetricDiskStatsShortInterval);
592 break;
593 case kDiskStatsLong:
594 SendMetric(kMetricReadSectorsLongName,
595 (int) (read_sectors_now - read_sectors_) /
596 kMetricDiskStatsLongInterval,
597 1,
598 kMetricSectorsIOMax,
599 kMetricSectorsBuckets);
600 SendMetric(kMetricWriteSectorsLongName,
601 (int) (write_sectors_now - write_sectors_) /
602 kMetricDiskStatsLongInterval,
603 1,
604 kMetricSectorsIOMax,
605 kMetricSectorsBuckets);
606 // Reset sector counters
607 read_sectors_ = read_sectors_now;
608 write_sectors_ = write_sectors_now;
609 // Schedule short callback.
610 diskstats_state_ = kDiskStatsShort;
611 ScheduleDiskStatsCallback(kMetricDiskStatsShortInterval);
612 break;
613 default:
614 LOG(FATAL) << "Invalid disk stats state";
615 }
616 }
617
497 // static 618 // static
498 void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) { 619 void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) {
499 if (count <= 0) 620 if (count <= 0)
500 return; 621 return;
501 622
502 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle); 623 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
503 int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute; 624 int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute;
504 daemon->SendMetric(kMetricDailyUseTimeName, minutes, 625 daemon->SendMetric(kMetricDailyUseTimeName, minutes,
505 kMetricDailyUseTimeMin, 626 kMetricDailyUseTimeMin,
506 kMetricDailyUseTimeMax, 627 kMetricDailyUseTimeMax,
507 kMetricDailyUseTimeBuckets); 628 kMetricDailyUseTimeBuckets);
508 } 629 }
509 630
510 void MetricsDaemon::SendMetric(const string& name, int sample, 631 void MetricsDaemon::SendMetric(const string& name, int sample,
511 int min, int max, int nbuckets) { 632 int min, int max, int nbuckets) {
512 DLOG(INFO) << "received metric: " << name << " " << sample << " " 633 DLOG(INFO) << "received metric: " << name << " " << sample << " "
513 << min << " " << max << " " << nbuckets; 634 << min << " " << max << " " << nbuckets;
514 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets); 635 metrics_lib_->SendToUMA(name, sample, min, max, nbuckets);
515 } 636 }
OLDNEW
« no previous file with comments | « metrics_daemon.h ('k') | metrics_daemon_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698