Add # daily crashes metrics and separate kernel crashes out.
BUG=5340
Review URL: http://codereview.chromium.org/3181015
diff --git a/metrics/counter.cc b/metrics/counter.cc
index b81a0d1..4de1db1 100644
--- a/metrics/counter.cc
+++ b/metrics/counter.cc
@@ -183,4 +183,32 @@
}
}
+FrequencyCounter::FrequencyCounter() : cycle_duration_(1) {
+}
+
+FrequencyCounter::~FrequencyCounter() {
+}
+
+void FrequencyCounter::Init(const char* filename,
+ TaggedCounterInterface::Reporter reporter,
+ void* reporter_handle,
+ time_t cycle_duration) {
+ // Allow tests to inject tagged_counter_ dependency.
+ if (tagged_counter_.get() == NULL) {
+ tagged_counter_.reset(new TaggedCounter());
+ }
+ tagged_counter_->Init(filename, reporter, reporter_handle);
+ DCHECK(cycle_duration > 0);
+ cycle_duration_ = cycle_duration;
+}
+
+void FrequencyCounter::UpdateInternal(int32 count, time_t now) {
+ DCHECK(tagged_counter_.get() != NULL);
+ tagged_counter_->Update(GetCycleNumber(now), count);
+}
+
+int32 FrequencyCounter::GetCycleNumber(time_t now) {
+ return now / cycle_duration_;
+}
+
} // namespace chromeos_metrics
diff --git a/metrics/counter.h b/metrics/counter.h
index 1cfcb51..a5e5302 100644
--- a/metrics/counter.h
+++ b/metrics/counter.h
@@ -5,11 +5,18 @@
#ifndef METRICS_COUNTER_H_
#define METRICS_COUNTER_H_
+#include <time.h>
+
#include <base/basictypes.h>
+#include <base/scoped_ptr.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
namespace chromeos_metrics {
+// Constants useful for frequency statistics.
+const int kSecondsPerDay = 60 * 60 * 24;
+const int kSecondsPerWeek = kSecondsPerDay * 7;
+
// TaggedCounter maintains a persistent storage (i.e., a file)
// aggregation counter for a given tag (e.g., day, hour) that survives
// system shutdowns, reboots and crashes, as well as daemon process
@@ -152,6 +159,45 @@
RecordState record_state_;
};
+// FrequencyCounter uses TaggedCounter to maintain a persistent
+// storage of the number of events that occur in a given cycle
+// duration (in other words, a frequency count). For example, to
+// count the number of blips per day, initialize |cycle_duration| to
+// chromeos_metrics::kSecondsPerDay, and call Update with the number
+// of blips that happen concurrently (usually 1). Reporting of the
+// value is done through TaggedCounter's reporter function.
+class FrequencyCounter {
+ public:
+ // Create a new frequency counter.
+ FrequencyCounter();
+ virtual ~FrequencyCounter();
+
+ // Initialize a frequency counter, which is necessary before first use.
+ // |filename|, |reporter|, and |reporter_handle| are used as in
+ // TaggedCounter::Init. |cycle_duration| is the number of seconds
+ // in a cycle.
+ virtual void Init(const char* filename,
+ TaggedCounterInterface::Reporter reporter,
+ void* reporter_handle,
+ time_t cycle_duration);
+ // Record that an event occurred. |count| is the number of concurrent
+ // events that have occurred. The time is implicitly assumed to be the
+ // time of the call.
+ virtual void Update(int32 count) {
+ UpdateInternal(count, time(NULL));
+ }
+
+ private:
+ friend class FrequencyCounterTest;
+ FRIEND_TEST(FrequencyCounterTest, UpdateInternal);
+
+ void UpdateInternal(int32 count, time_t now);
+ int32 GetCycleNumber(time_t now);
+
+ time_t cycle_duration_;
+ scoped_ptr<TaggedCounterInterface> tagged_counter_;
+};
+
} // namespace chromeos_metrics
#endif // METRICS_COUNTER_H_
diff --git a/metrics/counter_mock.h b/metrics/counter_mock.h
index baa97b0..701cce4 100644
--- a/metrics/counter_mock.h
+++ b/metrics/counter_mock.h
@@ -21,7 +21,15 @@
MOCK_METHOD0(Flush, void());
};
+class FrequencyCounterMock : public FrequencyCounter {
+ public:
+ MOCK_METHOD4(Init, void(const char* filename,
+ TaggedCounterInterface::Reporter reporter,
+ void* reporter_handle,
+ time_t cycle_duration));
+ MOCK_METHOD1(Update, void(int32 count));
+};
+
} // namespace chromeos_metrics
#endif // METRICS_COUNTER_MOCK_H_
-
diff --git a/metrics/counter_test.cc b/metrics/counter_test.cc
index fd5a389..eb68b2a 100644
--- a/metrics/counter_test.cc
+++ b/metrics/counter_test.cc
@@ -12,6 +12,7 @@
#include <gtest/gtest.h>
#include "counter.h"
+#include "counter_mock.h" // For TaggedCounterMock.
using ::testing::_;
using ::testing::MockFunction;
@@ -255,6 +256,64 @@
EXPECT_EQ(TaggedCounter::kRecordValid, counter_.record_state_);
}
+class FrequencyCounterTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ tagged_counter_ = new StrictMock<TaggedCounterMock>;
+ frequency_counter_.tagged_counter_.reset(tagged_counter_);
+ }
+
+ static void FakeReporter(void *, int32, int32) {
+ }
+
+ void CheckInit(int32 cycle_duration);
+ void CheckCycleNumber(int32 cycle_duration);
+
+ FrequencyCounter frequency_counter_;
+ StrictMock<TaggedCounterMock>* tagged_counter_;
+
+ TaggedCounter::Reporter reporter_;
+};
+
+void FrequencyCounterTest::CheckInit(int32 cycle_duration) {
+ EXPECT_CALL(*tagged_counter_, Init(kTestRecordFile, FakeReporter, this))
+ .Times(1)
+ .RetiresOnSaturation();
+ frequency_counter_.Init(kTestRecordFile,
+ FakeReporter,
+ this,
+ cycle_duration);
+ EXPECT_EQ(cycle_duration, frequency_counter_.cycle_duration_);
+}
+
+TEST_F(FrequencyCounterTest, Init) {
+ CheckInit(100);
+}
+
+void FrequencyCounterTest::CheckCycleNumber(int32 cycle_duration) {
+ CheckInit(cycle_duration);
+ EXPECT_EQ(150, frequency_counter_.GetCycleNumber(cycle_duration * 150));
+ EXPECT_EQ(150, frequency_counter_.GetCycleNumber(cycle_duration * 150 +
+ cycle_duration - 1));
+ EXPECT_EQ(151, frequency_counter_.GetCycleNumber(cycle_duration * 151 + 1));
+ EXPECT_EQ(0, frequency_counter_.GetCycleNumber(0));
+}
+
+
+TEST_F(FrequencyCounterTest, GetCycleNumberForWeek) {
+ CheckCycleNumber(kSecondsPerWeek);
+}
+
+TEST_F(FrequencyCounterTest, GetCycleNumberForDay) {
+ CheckCycleNumber(kSecondsPerDay);
+}
+
+TEST_F(FrequencyCounterTest, UpdateInternal) {
+ CheckInit(kSecondsPerWeek);
+ EXPECT_CALL(*tagged_counter_, Update(150, 2));
+ frequency_counter_.UpdateInternal(2, kSecondsPerWeek * 150);
+}
+
} // namespace chromeos_metrics
int main(int argc, char** argv) {
diff --git a/metrics/metrics_daemon.cc b/metrics/metrics_daemon.cc
index 30d3da8..0171fde 100644
--- a/metrics/metrics_daemon.cc
+++ b/metrics/metrics_daemon.cc
@@ -39,6 +39,10 @@
static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute;
static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute;
+const char kKernelCrashDetectedFile[] = "/tmp/kernel-crash-detected";
+static const char kUncleanShutdownDetectedFile[] =
+ "/tmp/unclean-shutdown-detected";
+
// static metrics parameters.
const char MetricsDaemon::kMetricDailyUseTimeName[] =
"Logging.DailyUseTime";
@@ -46,12 +50,6 @@
const int MetricsDaemon::kMetricDailyUseTimeMax = kMinutesPerDay;
const int MetricsDaemon::kMetricDailyUseTimeBuckets = 50;
-const char MetricsDaemon::kMetricKernelCrashIntervalName[] =
- "Logging.KernelCrashInterval";
-const int MetricsDaemon::kMetricKernelCrashIntervalMin = 1;
-const int MetricsDaemon::kMetricKernelCrashIntervalMax = 4 * kSecondsPerWeek;
-const int MetricsDaemon::kMetricKernelCrashIntervalBuckets = 50;
-
const char MetricsDaemon::kMetricTimeToNetworkDropName[] =
"Network.TimeToDrop";
const int MetricsDaemon::kMetricTimeToNetworkDropMin = 1;
@@ -59,11 +57,33 @@
8 /* hours */ * kMinutesPerHour * kSecondsPerMinute;
const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50;
+// crash interval metrics
+const char MetricsDaemon::kMetricKernelCrashIntervalName[] =
+ "Logging.KernelCrashInterval";
+const char MetricsDaemon::kMetricUncleanShutdownIntervalName[] =
+ "Logging.UncleanShutdownInterval";
const char MetricsDaemon::kMetricUserCrashIntervalName[] =
"Logging.UserCrashInterval";
-const int MetricsDaemon::kMetricUserCrashIntervalMin = 1;
-const int MetricsDaemon::kMetricUserCrashIntervalMax = 4 * kSecondsPerWeek;
-const int MetricsDaemon::kMetricUserCrashIntervalBuckets = 50;
+
+const int MetricsDaemon::kMetricCrashIntervalMin = 1;
+const int MetricsDaemon::kMetricCrashIntervalMax =
+ 4 * kSecondsPerWeek;
+const int MetricsDaemon::kMetricCrashIntervalBuckets = 50;
+
+// crash frequency metrics
+const char MetricsDaemon::kMetricAnyCrashesDailyName[] =
+ "Logging.AnyCrashesDaily";
+const char MetricsDaemon::kMetricKernelCrashesDailyName[] =
+ "Logging.KernelCrashesDaily";
+const char MetricsDaemon::kMetricUncleanShutdownsDailyName[] =
+ "Logging.UncleanShutdownsDaily";
+const char MetricsDaemon::kMetricUserCrashesDailyName[] =
+ "Logging.UserCrashesDaily";
+const char MetricsDaemon::kMetricCrashesDailyMin = 1;
+const char MetricsDaemon::kMetricCrashesDailyMax = 100;
+const char MetricsDaemon::kMetricCrashesDailyBuckets = 50;
+
+
// static
const char* MetricsDaemon::kDBusMatches_[] = {
@@ -168,8 +188,14 @@
if (run_as_daemon && daemon(0, 0) != 0)
return;
- static const char kKernelCrashDetectedFile[] = "/tmp/kernel-crash-detected";
- CheckKernelCrash(kKernelCrashDetectedFile);
+ if (CheckSystemCrash(kKernelCrashDetectedFile)) {
+ ProcessKernelCrash();
+ }
+
+ if (CheckSystemCrash(kUncleanShutdownDetectedFile)) {
+ ProcessUncleanShutdown();
+ }
+
Loop();
}
@@ -180,19 +206,57 @@
static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
daily_use_.reset(new chromeos_metrics::TaggedCounter());
- daily_use_->Init(kDailyUseRecordFile, &DailyUseReporter, this);
+ daily_use_->Init(kDailyUseRecordFile, &ReportDailyUse, this);
static const char kUserCrashIntervalRecordFile[] =
"/var/log/metrics/user-crash-interval";
user_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
user_crash_interval_->Init(kUserCrashIntervalRecordFile,
- &UserCrashIntervalReporter, this);
+ &ReportUserCrashInterval, this);
static const char kKernelCrashIntervalRecordFile[] =
"/var/log/metrics/kernel-crash-interval";
kernel_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
kernel_crash_interval_->Init(kKernelCrashIntervalRecordFile,
- &KernelCrashIntervalReporter, this);
+ &ReportKernelCrashInterval, this);
+
+ static const char kUncleanShutdownDetectedFile[] =
+ "/var/log/metrics/unclean-shutdown-interval";
+ unclean_shutdown_interval_.reset(new chromeos_metrics::TaggedCounter());
+ unclean_shutdown_interval_->Init(kUncleanShutdownDetectedFile,
+ &ReportUncleanShutdownInterval, this);
+
+ static const char kUserCrashesDailyRecordFile[] =
+ "/var/log/metrics/user-crashes-daily";
+ user_crashes_daily_.reset(new chromeos_metrics::FrequencyCounter());
+ user_crashes_daily_->Init(kUserCrashesDailyRecordFile,
+ &ReportUserCrashesDaily,
+ this,
+ chromeos_metrics::kSecondsPerDay);
+
+ static const char kKernelCrashesDailyRecordFile[] =
+ "/var/log/metrics/kernel-crashes-daily";
+ kernel_crashes_daily_.reset(new chromeos_metrics::FrequencyCounter());
+ kernel_crashes_daily_->Init(kKernelCrashesDailyRecordFile,
+ &ReportKernelCrashesDaily,
+ this,
+ chromeos_metrics::kSecondsPerDay);
+
+ static const char kUncleanShutdownsDailyRecordFile[] =
+ "/var/log/metrics/unclean-shutdowns-daily";
+ unclean_shutdowns_daily_.reset(new chromeos_metrics::FrequencyCounter());
+ unclean_shutdowns_daily_->Init(kUncleanShutdownsDailyRecordFile,
+ &ReportUncleanShutdownsDaily,
+ this,
+ chromeos_metrics::kSecondsPerDay);
+
+ static const char kAnyCrashesUserCrashDailyRecordFile[] =
+ "/var/log/metrics/any-crashes-daily";
+ any_crashes_daily_.reset(new chromeos_metrics::FrequencyCounter());
+ any_crashes_daily_->Init(kAnyCrashesUserCrashDailyRecordFile,
+ &ReportAnyCrashesDaily,
+ this,
+ chromeos_metrics::kSecondsPerDay);
// Don't setup D-Bus and GLib in test mode.
if (testing)
@@ -408,6 +472,9 @@
// Reports the active use time since the last crash and resets it.
user_crash_interval_->Flush();
+
+ user_crashes_daily_->Update(1);
+ any_crashes_daily_->Update(1);
}
void MetricsDaemon::ProcessKernelCrash() {
@@ -416,19 +483,32 @@
// Reports the active use time since the last crash and resets it.
kernel_crash_interval_->Flush();
+
+ kernel_crashes_daily_->Update(1);
+ any_crashes_daily_->Update(1);
}
-void MetricsDaemon::CheckKernelCrash(const std::string& crash_file) {
+void MetricsDaemon::ProcessUncleanShutdown() {
+ // Counts the active use time up to now.
+ SetUserActiveState(user_active_, Time::Now());
+
+ // Reports the active use time since the last crash and resets it.
+ unclean_shutdown_interval_->Flush();
+
+ unclean_shutdowns_daily_->Update(1);
+ any_crashes_daily_->Update(1);
+}
+
+bool MetricsDaemon::CheckSystemCrash(const std::string& crash_file) {
FilePath crash_detected(crash_file);
if (!file_util::PathExists(crash_detected))
- return;
-
- ProcessKernelCrash();
+ return false;
// Deletes the crash-detected file so that the daemon doesn't report
// another kernel crash in case it's restarted.
file_util::Delete(crash_detected,
false); // recursive
+ return true;
}
// static
@@ -492,7 +572,7 @@
}
// static
-void MetricsDaemon::DailyUseReporter(void* handle, int tag, int count) {
+void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) {
if (count <= 0)
return;
@@ -505,25 +585,68 @@
}
// static
-void MetricsDaemon::UserCrashIntervalReporter(void* handle,
- int tag, int count) {
+void MetricsDaemon::ReportCrashInterval(const char* histogram_name,
+ void* handle, int count) {
MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
- daemon->SendMetric(kMetricUserCrashIntervalName, count,
- kMetricUserCrashIntervalMin,
- kMetricUserCrashIntervalMax,
- kMetricUserCrashIntervalBuckets);
+ daemon->SendMetric(histogram_name, count,
+ kMetricCrashIntervalMin,
+ kMetricCrashIntervalMax,
+ kMetricCrashIntervalBuckets);
}
// static
-void MetricsDaemon::KernelCrashIntervalReporter(void* handle,
- int tag, int count) {
- MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
- daemon->SendMetric(kMetricKernelCrashIntervalName, count,
- kMetricKernelCrashIntervalMin,
- kMetricKernelCrashIntervalMax,
- kMetricKernelCrashIntervalBuckets);
+void MetricsDaemon::ReportUserCrashInterval(void* handle,
+ int tag, int count) {
+ ReportCrashInterval(kMetricUserCrashIntervalName, handle, count);
}
+// static
+void MetricsDaemon::ReportKernelCrashInterval(void* handle,
+ int tag, int count) {
+ ReportCrashInterval(kMetricKernelCrashIntervalName, handle, count);
+}
+
+// static
+void MetricsDaemon::ReportUncleanShutdownInterval(void* handle,
+ int tag, int count) {
+ ReportCrashInterval(kMetricUncleanShutdownIntervalName, handle, count);
+}
+
+// static
+void MetricsDaemon::ReportCrashesDailyFrequency(const char* histogram_name,
+ void* handle,
+ int count) {
+ MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
+ daemon->SendMetric(histogram_name, count,
+ kMetricCrashesDailyMin,
+ kMetricCrashesDailyMax,
+ kMetricCrashesDailyBuckets);
+}
+
+// static
+void MetricsDaemon::ReportUserCrashesDaily(void* handle,
+ int tag, int count) {
+ ReportCrashesDailyFrequency(kMetricUserCrashesDailyName, handle, count);
+}
+
+// static
+void MetricsDaemon::ReportKernelCrashesDaily(void* handle,
+ int tag, int count) {
+ ReportCrashesDailyFrequency(kMetricKernelCrashesDailyName, handle, count);
+}
+
+// static
+void MetricsDaemon::ReportUncleanShutdownsDaily(void* handle,
+ int tag, int count) {
+ ReportCrashesDailyFrequency(kMetricUncleanShutdownsDailyName, handle, count);
+}
+
+// static
+void MetricsDaemon::ReportAnyCrashesDaily(void* handle, int tag, int count) {
+ ReportCrashesDailyFrequency(kMetricAnyCrashesDailyName, handle, count);
+}
+
+
void MetricsDaemon::SendMetric(const string& name, int sample,
int min, int max, int nbuckets) {
DLOG(INFO) << "received metric: " << name << " " << sample << " "
diff --git a/metrics/metrics_daemon.h b/metrics/metrics_daemon.h
index 437cafd..f98c34c 100644
--- a/metrics/metrics_daemon.h
+++ b/metrics/metrics_daemon.h
@@ -14,7 +14,10 @@
#include "metrics_library.h"
-namespace chromeos_metrics { class TaggedCounterInterface; }
+namespace chromeos_metrics {
+class FrequencyCounter;
+class TaggedCounterInterface;
+}
class MetricsDaemon {
@@ -31,9 +34,7 @@
private:
friend class MetricsDaemonTest;
- FRIEND_TEST(MetricsDaemonTest, CheckKernelCrash);
- FRIEND_TEST(MetricsDaemonTest, DailyUseReporter);
- FRIEND_TEST(MetricsDaemonTest, KernelCrashIntervalReporter);
+ FRIEND_TEST(MetricsDaemonTest, CheckSystemCrash);
FRIEND_TEST(MetricsDaemonTest, LookupNetworkState);
FRIEND_TEST(MetricsDaemonTest, LookupPowerState);
FRIEND_TEST(MetricsDaemonTest, LookupScreenSaverState);
@@ -43,13 +44,18 @@
FRIEND_TEST(MetricsDaemonTest, NetStateChangedSuspend);
FRIEND_TEST(MetricsDaemonTest, PowerStateChanged);
FRIEND_TEST(MetricsDaemonTest, ProcessKernelCrash);
+ FRIEND_TEST(MetricsDaemonTest, ProcessUncleanShutdown);
FRIEND_TEST(MetricsDaemonTest, ProcessUserCrash);
+ FRIEND_TEST(MetricsDaemonTest, ReportCrashesDailyFrequency);
+ FRIEND_TEST(MetricsDaemonTest, ReportDailyUse);
+ FRIEND_TEST(MetricsDaemonTest, ReportKernelCrashInterval);
+ FRIEND_TEST(MetricsDaemonTest, ReportUncleanShutdownInterval);
+ FRIEND_TEST(MetricsDaemonTest, ReportUserCrashInterval);
FRIEND_TEST(MetricsDaemonTest, ScreenSaverStateChanged);
FRIEND_TEST(MetricsDaemonTest, SendMetric);
FRIEND_TEST(MetricsDaemonTest, SessionStateChanged);
FRIEND_TEST(MetricsDaemonTest, SetUserActiveState);
FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateTimeJump);
- FRIEND_TEST(MetricsDaemonTest, UserCrashIntervalReporter);
// The network states (see network_states.h).
enum NetworkState {
@@ -84,22 +90,27 @@
};
// Metric parameters.
+ static const char kMetricAnyCrashesDailyName[];
+ static const char kMetricCrashesDailyBuckets;
+ static const char kMetricCrashesDailyMax;
+ static const char kMetricCrashesDailyMin;
+ static const int kMetricCrashIntervalBuckets;
+ static const int kMetricCrashIntervalMax;
+ static const int kMetricCrashIntervalMin;
+ static const int kMetricDailyUseTimeBuckets;
+ static const int kMetricDailyUseTimeMax;
+ static const int kMetricDailyUseTimeMin;
static const char kMetricDailyUseTimeName[];
- static const int kMetricDailyUseTimeMin;
- static const int kMetricDailyUseTimeMax;
- static const int kMetricDailyUseTimeBuckets;
+ static const char kMetricKernelCrashesDailyName[];
static const char kMetricKernelCrashIntervalName[];
- static const int kMetricKernelCrashIntervalMin;
- static const int kMetricKernelCrashIntervalMax;
- static const int kMetricKernelCrashIntervalBuckets;
+ static const int kMetricTimeToNetworkDropBuckets;
+ static const int kMetricTimeToNetworkDropMax;
+ static const int kMetricTimeToNetworkDropMin;
static const char kMetricTimeToNetworkDropName[];
- static const int kMetricTimeToNetworkDropMin;
- static const int kMetricTimeToNetworkDropMax;
- static const int kMetricTimeToNetworkDropBuckets;
+ static const char kMetricUncleanShutdownIntervalName[];
+ static const char kMetricUncleanShutdownsDailyName[];
+ static const char kMetricUserCrashesDailyName[];
static const char kMetricUserCrashIntervalName[];
- static const int kMetricUserCrashIntervalMin;
- static const int kMetricUserCrashIntervalMax;
- static const int kMetricUserCrashIntervalBuckets;
// D-Bus message match strings.
static const char* kDBusMatches_[];
@@ -162,10 +173,14 @@
// Updates the active use time and logs time between kernel crashes.
void ProcessKernelCrash();
- // Checks if a kernel crash has been detected and processes if so.
- // The method assumes that a kernel crash has happened if
- // |crash_file| exists.
- void CheckKernelCrash(const std::string& crash_file);
+ // Updates the active use time and logs time between unclean shutdowns.
+ void ProcessUncleanShutdown();
+
+ // Checks if a kernel crash has been detected and returns true if
+ // so. The method assumes that a kernel crash has happened if
+ // |crash_file| exists. It removes the file immediately if it
+ // exists, so it must not be called more than once.
+ bool CheckSystemCrash(const std::string& crash_file);
// Callbacks for the daily use monitor. The daily use monitor uses
// LogDailyUseRecord to aggregate current usage data and send it to
@@ -196,15 +211,39 @@
// TaggedCounter callback to process aggregated daily usage data and
// send to UMA.
- static void DailyUseReporter(void* data, int tag, int count);
+ static void ReportDailyUse(void* data, int tag, int count);
+
+ // Helper to report a crash interval to UMA.
+ static void ReportCrashInterval(const char* histogram_name,
+ void* handle, int count);
// TaggedCounter callback to process time between user-space process
// crashes and send to UMA.
- static void UserCrashIntervalReporter(void* data, int tag, int count);
+ static void ReportUserCrashInterval(void* data, int tag, int count);
// TaggedCounter callback to process time between kernel crashes and
// send to UMA.
- static void KernelCrashIntervalReporter(void* data, int tag, int count);
+ static void ReportKernelCrashInterval(void* data, int tag, int count);
+
+ // TaggedCounter callback to process time between unclean shutdowns and
+ // send to UMA.
+ static void ReportUncleanShutdownInterval(void* data, int tag, int count);
+
+ // Helper to report a daily crash frequency to UMA.
+ static void ReportCrashesDailyFrequency(const char* histogram_name,
+ void* handle, int count);
+
+ // TaggedCounter callback to report daily crash frequency to UMA.
+ static void ReportUserCrashesDaily(void* handle, int tag, int count);
+
+ // TaggedCounter callback to report kernel crash frequency to UMA.
+ static void ReportKernelCrashesDaily(void* handle, int tag, int count);
+
+ // TaggedCounter callback to report unclean shutdown frequency to UMA.
+ static void ReportUncleanShutdownsDaily(void* handle, int tag, int count);
+
+ // TaggedCounter callback to report frequency of any crashes to UMA.
+ static void ReportAnyCrashesDaily(void* handle, int tag, int count);
// Test mode.
bool testing_;
@@ -244,6 +283,23 @@
// Active use time between kernel crashes.
scoped_ptr<chromeos_metrics::TaggedCounterInterface> kernel_crash_interval_;
+ // Active use time between unclean shutdowns crashes.
+ scoped_ptr<chromeos_metrics::TaggedCounterInterface>
+ unclean_shutdown_interval_;
+
+ // Daily count of user-space process crashes.
+ scoped_ptr<chromeos_metrics::FrequencyCounter> user_crashes_daily_;
+
+ // Daily count of kernel crashes.
+ scoped_ptr<chromeos_metrics::FrequencyCounter> kernel_crashes_daily_;
+
+ // Daily count of unclean shutdowns.
+ scoped_ptr<chromeos_metrics::FrequencyCounter> unclean_shutdowns_daily_;
+
+ // Daily count of any crashes (user-space processes, kernel, or
+ // unclean shutdowns).
+ scoped_ptr<chromeos_metrics::FrequencyCounter> any_crashes_daily_;
+
// Sleep period until the next daily usage aggregation performed by
// the daily use monitor (see ScheduleUseMonitor).
int usemon_interval_;
diff --git a/metrics/metrics_daemon_test.cc b/metrics/metrics_daemon_test.cc
index e75c161..e551cf9 100644
--- a/metrics/metrics_daemon_test.cc
+++ b/metrics/metrics_daemon_test.cc
@@ -11,6 +11,7 @@
using base::Time;
using base::TimeTicks;
+using chromeos_metrics::FrequencyCounterMock;
using chromeos_metrics::TaggedCounterMock;
using ::testing::_;
using ::testing::Return;
@@ -59,6 +60,16 @@
daemon_.kernel_crash_interval_.reset(kernel_crash_interval_);
user_crash_interval_ = new StrictMock<TaggedCounterMock>();
daemon_.user_crash_interval_.reset(user_crash_interval_);
+ unclean_shutdown_interval_ = new StrictMock<TaggedCounterMock>();
+ daemon_.unclean_shutdown_interval_.reset(unclean_shutdown_interval_);
+ kernel_crashes_daily_ = new StrictMock<FrequencyCounterMock>();
+ daemon_.kernel_crashes_daily_.reset(kernel_crashes_daily_);
+ user_crashes_daily_ = new StrictMock<FrequencyCounterMock>();
+ daemon_.user_crashes_daily_.reset(user_crashes_daily_);
+ unclean_shutdowns_daily_ = new StrictMock<FrequencyCounterMock>();
+ daemon_.unclean_shutdowns_daily_.reset(unclean_shutdowns_daily_);
+ any_crashes_daily_ = new StrictMock<FrequencyCounterMock>();
+ daemon_.any_crashes_daily_.reset(any_crashes_daily_);
EXPECT_FALSE(daemon_.user_active_);
EXPECT_TRUE(daemon_.user_active_last_.is_null());
@@ -172,40 +183,54 @@
StrictMock<TaggedCounterMock>* daily_use_;
StrictMock<TaggedCounterMock>* kernel_crash_interval_;
StrictMock<TaggedCounterMock>* user_crash_interval_;
+ StrictMock<TaggedCounterMock>* unclean_shutdown_interval_;
+
+ StrictMock<FrequencyCounterMock>* kernel_crashes_daily_;
+ StrictMock<FrequencyCounterMock>* user_crashes_daily_;
+ StrictMock<FrequencyCounterMock>* unclean_shutdowns_daily_;
+ StrictMock<FrequencyCounterMock>* any_crashes_daily_;
};
-TEST_F(MetricsDaemonTest, CheckKernelCrash) {
+TEST_F(MetricsDaemonTest, CheckSystemCrash) {
static const char kKernelCrashDetected[] = "test-kernel-crash-detected";
- daemon_.CheckKernelCrash(kKernelCrashDetected);
+ EXPECT_FALSE(daemon_.CheckSystemCrash(kKernelCrashDetected));
FilePath crash_detected(kKernelCrashDetected);
file_util::WriteFile(crash_detected, "", 0);
- IgnoreActiveUseUpdate();
- EXPECT_CALL(*kernel_crash_interval_, Flush())
- .Times(1)
- .RetiresOnSaturation();
- daemon_.CheckKernelCrash(kKernelCrashDetected);
+ EXPECT_TRUE(file_util::PathExists(crash_detected));
+ EXPECT_TRUE(daemon_.CheckSystemCrash(kKernelCrashDetected));
+ EXPECT_FALSE(file_util::PathExists(crash_detected));
+ EXPECT_FALSE(daemon_.CheckSystemCrash(kKernelCrashDetected));
+ EXPECT_FALSE(file_util::PathExists(crash_detected));
file_util::Delete(crash_detected, false);
}
-TEST_F(MetricsDaemonTest, DailyUseReporter) {
+TEST_F(MetricsDaemonTest, ReportDailyUse) {
ExpectDailyUseTimeMetric(/* sample */ 2);
- MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 20, /* count */ 90);
+ MetricsDaemon::ReportDailyUse(&daemon_, /* tag */ 20, /* count */ 90);
ExpectDailyUseTimeMetric(/* sample */ 1);
- MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 23, /* count */ 89);
+ MetricsDaemon::ReportDailyUse(&daemon_, /* tag */ 23, /* count */ 89);
// There should be no metrics generated for the calls below.
- MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 50, /* count */ 0);
- MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 60, /* count */ -5);
+ MetricsDaemon::ReportDailyUse(&daemon_, /* tag */ 50, /* count */ 0);
+ MetricsDaemon::ReportDailyUse(&daemon_, /* tag */ 60, /* count */ -5);
}
-TEST_F(MetricsDaemonTest, KernelCrashIntervalReporter) {
+TEST_F(MetricsDaemonTest, ReportKernelCrashInterval) {
ExpectMetric(MetricsDaemon::kMetricKernelCrashIntervalName, 50,
- MetricsDaemon::kMetricKernelCrashIntervalMin,
- MetricsDaemon::kMetricKernelCrashIntervalMax,
- MetricsDaemon::kMetricKernelCrashIntervalBuckets);
- MetricsDaemon::KernelCrashIntervalReporter(&daemon_, 0, 50);
+ MetricsDaemon::kMetricCrashIntervalMin,
+ MetricsDaemon::kMetricCrashIntervalMax,
+ MetricsDaemon::kMetricCrashIntervalBuckets);
+ MetricsDaemon::ReportKernelCrashInterval(&daemon_, 0, 50);
+}
+
+TEST_F(MetricsDaemonTest, ReportUncleanShutdownInterval) {
+ ExpectMetric(MetricsDaemon::kMetricUncleanShutdownIntervalName, 50,
+ MetricsDaemon::kMetricCrashIntervalMin,
+ MetricsDaemon::kMetricCrashIntervalMax,
+ MetricsDaemon::kMetricCrashIntervalBuckets);
+ MetricsDaemon::ReportUncleanShutdownInterval(&daemon_, 0, 50);
}
TEST_F(MetricsDaemonTest, LookupNetworkState) {
@@ -246,6 +271,12 @@
EXPECT_CALL(*user_crash_interval_, Flush())
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*user_crashes_daily_, Update(1))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*any_crashes_daily_, Update(1))
+ .Times(1)
+ .RetiresOnSaturation();
msg = NewDBusSignalString("/",
"org.chromium.CrashReporter",
"UserCrash",
@@ -379,14 +410,28 @@
EXPECT_CALL(*kernel_crash_interval_, Flush())
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*kernel_crashes_daily_, Update(1));
+ EXPECT_CALL(*any_crashes_daily_, Update(1));
daemon_.ProcessKernelCrash();
}
+TEST_F(MetricsDaemonTest, ProcessUncleanShutdown) {
+ IgnoreActiveUseUpdate();
+ EXPECT_CALL(*unclean_shutdown_interval_, Flush())
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*unclean_shutdowns_daily_, Update(1));
+ EXPECT_CALL(*any_crashes_daily_, Update(1));
+ daemon_.ProcessUncleanShutdown();
+}
+
TEST_F(MetricsDaemonTest, ProcessUserCrash) {
IgnoreActiveUseUpdate();
EXPECT_CALL(*user_crash_interval_, Flush())
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*user_crashes_daily_, Update(1));
+ EXPECT_CALL(*any_crashes_daily_, Update(1));
daemon_.ProcessUserCrash();
}
@@ -469,12 +514,20 @@
EXPECT_EQ(TestTime(10 * kSecondsPerDay + 1000), daemon_.user_active_last_);
}
-TEST_F(MetricsDaemonTest, UserCrashIntervalReporter) {
+TEST_F(MetricsDaemonTest, ReportUserCrashInterval) {
ExpectMetric(MetricsDaemon::kMetricUserCrashIntervalName, 50,
- MetricsDaemon::kMetricUserCrashIntervalMin,
- MetricsDaemon::kMetricUserCrashIntervalMax,
- MetricsDaemon::kMetricUserCrashIntervalBuckets);
- MetricsDaemon::UserCrashIntervalReporter(&daemon_, 0, 50);
+ MetricsDaemon::kMetricCrashIntervalMin,
+ MetricsDaemon::kMetricCrashIntervalMax,
+ MetricsDaemon::kMetricCrashIntervalBuckets);
+ MetricsDaemon::ReportUserCrashInterval(&daemon_, 0, 50);
+}
+
+TEST_F(MetricsDaemonTest, ReportCrashesDailyFrequency) {
+ ExpectMetric("foobar", 50,
+ MetricsDaemon::kMetricCrashesDailyMin,
+ MetricsDaemon::kMetricCrashesDailyMax,
+ MetricsDaemon::kMetricCrashesDailyBuckets);
+ MetricsDaemon::ReportCrashesDailyFrequency("foobar", &daemon_, 50);
}
int main(int argc, char** argv) {