Add weekly crash counters, refactor metrics_daemon, respect opt-in in library.
BUG=5340,5814 Change-Id: I2c207055f1ebe48051193395e2dbe38d9140b025 Review URL: http://codereview.chromium.org/3171023
This commit is contained in:
parent
ccd84c03d2
commit
4c5daa4794
|
@ -26,8 +26,8 @@ extern "C" void CMetricsLibraryInit(CMetricsLibrary handle) {
|
|||
}
|
||||
|
||||
extern "C" int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
|
||||
const char* name, int sample,
|
||||
int min, int max, int nbuckets) {
|
||||
const char* name, int sample,
|
||||
int min, int max, int nbuckets) {
|
||||
MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
|
||||
if (lib == NULL)
|
||||
return 0;
|
||||
|
@ -35,10 +35,17 @@ extern "C" int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
|
|||
}
|
||||
|
||||
extern "C" int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
|
||||
const char* name, int sample,
|
||||
int max) {
|
||||
const char* name, int sample,
|
||||
int max) {
|
||||
MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
|
||||
if (lib == NULL)
|
||||
return 0;
|
||||
return lib->SendEnumToUMA(std::string(name), sample, max);
|
||||
}
|
||||
|
||||
extern "C" int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle) {
|
||||
MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
|
||||
if (lib == NULL)
|
||||
return 0;
|
||||
return lib->AreMetricsEnabled();
|
||||
}
|
||||
|
|
|
@ -21,13 +21,17 @@ void CMetricsLibraryInit(CMetricsLibrary handle);
|
|||
|
||||
// C wrapper for MetricsLibrary::SendToUMA.
|
||||
int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
|
||||
const char* name, int sample,
|
||||
int min, int max, int nbuckets);
|
||||
const char* name, int sample,
|
||||
int min, int max, int nbuckets);
|
||||
|
||||
// C wrapper for MetricsLibrary::SendEnumToUMA.
|
||||
int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
|
||||
const char* name, int sample, int max);
|
||||
const char* name, int sample, int max);
|
||||
|
||||
// C wrapper for MetricsLibrary::AreMetricsEnabled.
|
||||
int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif // C_METRICS_LIBRARY_H_
|
||||
#endif // C_METRICS_LIBRARY_H_
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <base/eintr_wrapper.h>
|
||||
#include <base/logging.h>
|
||||
#include "metrics_library.h"
|
||||
|
||||
namespace chromeos_metrics {
|
||||
|
||||
|
@ -31,8 +32,7 @@ void TaggedCounter::Record::Add(int32 count) {
|
|||
|
||||
// TaggedCounter implementation.
|
||||
TaggedCounter::TaggedCounter()
|
||||
: filename_(NULL),
|
||||
reporter_(NULL),
|
||||
: reporter_(NULL),
|
||||
reporter_handle_(NULL),
|
||||
record_state_(kRecordInvalid) {}
|
||||
|
||||
|
@ -72,12 +72,13 @@ void TaggedCounter::UpdateInternal(int32 tag, int32 count, bool flush) {
|
|||
}
|
||||
|
||||
DLOG(INFO) << "tag: " << tag << " count: " << count << " flush: " << flush;
|
||||
DCHECK(filename_);
|
||||
DCHECK(!filename_.empty());
|
||||
|
||||
// NOTE: The assumption is that this TaggedCounter object is the
|
||||
// sole owner of the persistent storage file so no locking is
|
||||
// necessary.
|
||||
int fd = HANDLE_EINTR(open(filename_, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
|
||||
int fd = HANDLE_EINTR(open(filename_.c_str(),
|
||||
O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
|
||||
if (fd < 0) {
|
||||
PLOG(WARNING) << "Unable to open the persistent counter file";
|
||||
return;
|
||||
|
@ -183,21 +184,57 @@ void TaggedCounter::WriteRecord(int fd) {
|
|||
}
|
||||
}
|
||||
|
||||
MetricsLibraryInterface* TaggedCounterReporter::metrics_lib_ = NULL;
|
||||
|
||||
TaggedCounterReporter::TaggedCounterReporter()
|
||||
: tagged_counter_(new TaggedCounter()),
|
||||
min_(0),
|
||||
max_(0),
|
||||
buckets_(0) {
|
||||
}
|
||||
|
||||
TaggedCounterReporter::~TaggedCounterReporter() {
|
||||
}
|
||||
|
||||
void TaggedCounterReporter::Init(const char* filename,
|
||||
const char* histogram_name,
|
||||
int min,
|
||||
int max,
|
||||
int buckets) {
|
||||
tagged_counter_->Init(filename, Report, this);
|
||||
histogram_name_ = histogram_name;
|
||||
min_ = min;
|
||||
max_ = max;
|
||||
buckets_ = buckets;
|
||||
CHECK(min_ >= 0);
|
||||
CHECK(max_ > min_);
|
||||
CHECK(buckets_ > 0);
|
||||
}
|
||||
|
||||
void TaggedCounterReporter::Report(void* handle, int32 tag, int32 count) {
|
||||
TaggedCounterReporter* this_reporter =
|
||||
reinterpret_cast<TaggedCounterReporter*>(handle);
|
||||
DLOG(INFO) << "received metric: " << this_reporter->histogram_name_
|
||||
<< " " << count << " " << this_reporter->min_ << " "
|
||||
<< this_reporter->max_ << " " << this_reporter->buckets_;
|
||||
CHECK(metrics_lib_ != NULL);
|
||||
CHECK(this_reporter->buckets_ > 0);
|
||||
metrics_lib_->SendToUMA(this_reporter->histogram_name_,
|
||||
count,
|
||||
this_reporter->min_,
|
||||
this_reporter->max_,
|
||||
this_reporter->buckets_);
|
||||
}
|
||||
|
||||
FrequencyCounter::FrequencyCounter() : cycle_duration_(1) {
|
||||
}
|
||||
|
||||
FrequencyCounter::~FrequencyCounter() {
|
||||
}
|
||||
|
||||
void FrequencyCounter::Init(const char* filename,
|
||||
TaggedCounterInterface::Reporter reporter,
|
||||
void* reporter_handle,
|
||||
void FrequencyCounter::Init(TaggedCounterInterface* tagged_counter,
|
||||
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);
|
||||
tagged_counter_.reset(tagged_counter);
|
||||
DCHECK(cycle_duration > 0);
|
||||
cycle_duration_ = cycle_duration;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,15 @@
|
|||
#ifndef METRICS_COUNTER_H_
|
||||
#define METRICS_COUNTER_H_
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
#include <base/basictypes.h>
|
||||
#include <base/scoped_ptr.h>
|
||||
#include <gtest/gtest_prod.h> // for FRIEND_TEST
|
||||
|
||||
class MetricsLibraryInterface;
|
||||
|
||||
namespace chromeos_metrics {
|
||||
|
||||
// Constants useful for frequency statistics.
|
||||
|
@ -44,16 +47,6 @@ class TaggedCounterInterface {
|
|||
|
||||
virtual ~TaggedCounterInterface() {}
|
||||
|
||||
// Initializes the counter by providing the persistent storage
|
||||
// location |filename| and a |reporter| callback for reporting
|
||||
// aggregated counts. |reporter_handle| is sent to the |reporter|
|
||||
// along with the aggregated counts.
|
||||
//
|
||||
// NOTE: The assumption is that this object is the sole owner of the
|
||||
// persistent storage file so no locking is currently implemented.
|
||||
virtual void Init(const char* filename,
|
||||
Reporter reporter, void* reporter_handle) = 0;
|
||||
|
||||
// Adds |count| of events for the given |tag|. If there's an
|
||||
// existing aggregated count for a different tag, it's reported
|
||||
// through the reporter callback and discarded.
|
||||
|
@ -67,12 +60,21 @@ class TaggedCounterInterface {
|
|||
class TaggedCounter : public TaggedCounterInterface {
|
||||
public:
|
||||
TaggedCounter();
|
||||
~TaggedCounter();
|
||||
virtual ~TaggedCounter();
|
||||
|
||||
// Initializes the counter by providing the persistent storage
|
||||
// location |filename| and a |reporter| callback for reporting
|
||||
// aggregated counts. |reporter_handle| is sent to the |reporter|
|
||||
// along with the aggregated counts.
|
||||
//
|
||||
// NOTE: The assumption is that this object is the sole owner of the
|
||||
// persistent storage file so no locking is currently implemented.
|
||||
virtual void Init(const char* filename,
|
||||
Reporter reporter, void* reporter_handle);
|
||||
|
||||
// Implementation of interface methods.
|
||||
void Init(const char* filename, Reporter reporter, void* reporter_handle);
|
||||
void Update(int32 tag, int32 count);
|
||||
void Flush();
|
||||
virtual void Update(int32 tag, int32 count);
|
||||
virtual void Flush();
|
||||
|
||||
private:
|
||||
friend class RecordTest;
|
||||
|
@ -146,7 +148,7 @@ class TaggedCounter : public TaggedCounterInterface {
|
|||
void WriteRecord(int fd);
|
||||
|
||||
// Persistent storage file path.
|
||||
const char* filename_;
|
||||
std::string filename_;
|
||||
|
||||
// Aggregated data reporter callback and handle to pass-through.
|
||||
Reporter reporter_;
|
||||
|
@ -159,6 +161,71 @@ class TaggedCounter : public TaggedCounterInterface {
|
|||
RecordState record_state_;
|
||||
};
|
||||
|
||||
// TaggedCounterReporter provides a TaggedCounterInterface which both
|
||||
// counts tagged events and reports them up through the metrics
|
||||
// library to UMA.
|
||||
class TaggedCounterReporter : public TaggedCounterInterface {
|
||||
public:
|
||||
TaggedCounterReporter();
|
||||
virtual ~TaggedCounterReporter();
|
||||
|
||||
// Set the metrics library used by all TaggedCounterReporter
|
||||
// instances. We assume there is only one metrics library
|
||||
// shared amongst all reporters.
|
||||
static void SetMetricsLibraryInterface(MetricsLibraryInterface* metrics_lib) {
|
||||
metrics_lib_ = metrics_lib;
|
||||
}
|
||||
|
||||
// Initializes the counter by providing the persistent storage
|
||||
// location |filename|, a |histogram_name| (a linear histogram) to
|
||||
// report to with |min|, |max|, and |buckets| attributes for the
|
||||
// histogram.
|
||||
virtual void Init(const char* filename,
|
||||
const char* histogram_name,
|
||||
int min,
|
||||
int max,
|
||||
int buckets);
|
||||
|
||||
// Implementation of interface method.
|
||||
virtual void Update(int32 tag, int32 count) {
|
||||
tagged_counter_->Update(tag, count);
|
||||
}
|
||||
// Implementation of interface method.
|
||||
virtual void Flush() {
|
||||
tagged_counter_->Flush();
|
||||
}
|
||||
|
||||
// Accessor functions.
|
||||
const std::string& histogram_name() const {
|
||||
return histogram_name_;
|
||||
}
|
||||
|
||||
int min() const {
|
||||
return min_;
|
||||
}
|
||||
|
||||
int max() const {
|
||||
return max_;
|
||||
}
|
||||
|
||||
int buckets() const {
|
||||
return buckets_;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class TaggedCounterReporterTest;
|
||||
FRIEND_TEST(TaggedCounterReporterTest, Report);
|
||||
|
||||
static void Report(void* handle, int32 tag, int32 count);
|
||||
|
||||
static MetricsLibraryInterface* metrics_lib_;
|
||||
scoped_ptr<TaggedCounter> tagged_counter_;
|
||||
std::string histogram_name_;
|
||||
int min_;
|
||||
int max_;
|
||||
int buckets_;
|
||||
};
|
||||
|
||||
// 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
|
||||
|
@ -172,13 +239,11 @@ class FrequencyCounter {
|
|||
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,
|
||||
// Initialize a frequency counter, which is necessary before first
|
||||
// use. |tagged_counter| is used to store the counts, its memory
|
||||
// will be managed by this FrequencyCounter. |cycle_duration| is
|
||||
// the number of seconds in a cycle.
|
||||
virtual void Init(TaggedCounterInterface* tagged_counter,
|
||||
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
|
||||
|
@ -187,9 +252,29 @@ class FrequencyCounter {
|
|||
UpdateInternal(count, time(NULL));
|
||||
}
|
||||
|
||||
// Update the frequency counter based on the current time. If a
|
||||
// cycle has finished, this will have the effect of flushing the
|
||||
// cycle's count, without first requiring another update to the
|
||||
// frequency counter. The more often this is called, the lower the
|
||||
// latency to have a new sample submitted.
|
||||
virtual void FlushFinishedCycles() {
|
||||
Update(0);
|
||||
}
|
||||
|
||||
// Accessor function.
|
||||
const TaggedCounterInterface& tagged_counter() const {
|
||||
return *tagged_counter_;
|
||||
}
|
||||
|
||||
time_t cycle_duration() const {
|
||||
return cycle_duration_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class FrequencyCounterTest;
|
||||
FRIEND_TEST(FrequencyCounterTest, UpdateInternal);
|
||||
FRIEND_TEST(FrequencyCounterTest, GetCycleNumberForWeek);
|
||||
FRIEND_TEST(FrequencyCounterTest, GetCycleNumberForDay);
|
||||
|
||||
void UpdateInternal(int32 count, time_t now);
|
||||
int32 GetCycleNumber(time_t now);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace chromeos_metrics {
|
||||
|
||||
class TaggedCounterMock : public TaggedCounterInterface {
|
||||
class TaggedCounterMock : public TaggedCounter {
|
||||
public:
|
||||
MOCK_METHOD3(Init, void(const char* filename,
|
||||
Reporter reporter, void* reporter_handle));
|
||||
|
@ -21,6 +21,17 @@ class TaggedCounterMock : public TaggedCounterInterface {
|
|||
MOCK_METHOD0(Flush, void());
|
||||
};
|
||||
|
||||
class TaggedCounterReporterMock : public TaggedCounterReporter {
|
||||
public:
|
||||
MOCK_METHOD5(Init, void(const char* filename,
|
||||
const char* histogram_name,
|
||||
int min,
|
||||
int max,
|
||||
int nbuckets));
|
||||
MOCK_METHOD2(Update, void(int32 tag, int32 count));
|
||||
MOCK_METHOD0(Flush, void());
|
||||
};
|
||||
|
||||
class FrequencyCounterMock : public FrequencyCounter {
|
||||
public:
|
||||
MOCK_METHOD4(Init, void(const char* filename,
|
||||
|
@ -28,6 +39,7 @@ class FrequencyCounterMock : public FrequencyCounter {
|
|||
void* reporter_handle,
|
||||
time_t cycle_duration));
|
||||
MOCK_METHOD1(Update, void(int32 count));
|
||||
MOCK_METHOD0(FlushFinishedCycles, void());
|
||||
};
|
||||
|
||||
} // namespace chromeos_metrics
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "counter.h"
|
||||
#include "counter_mock.h" // For TaggedCounterMock.
|
||||
#include "metrics_library_mock.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::MockFunction;
|
||||
|
@ -37,7 +38,7 @@ class RecordTest : public testing::Test {
|
|||
class TaggedCounterTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
EXPECT_EQ(NULL, counter_.filename_);
|
||||
EXPECT_TRUE(counter_.filename_.empty());
|
||||
EXPECT_TRUE(NULL == counter_.reporter_);
|
||||
EXPECT_EQ(NULL, counter_.reporter_handle_);
|
||||
EXPECT_EQ(TaggedCounter::kRecordInvalid, counter_.record_state_);
|
||||
|
@ -256,14 +257,85 @@ TEST_F(TaggedCounterTest, Update) {
|
|||
EXPECT_EQ(TaggedCounter::kRecordValid, counter_.record_state_);
|
||||
}
|
||||
|
||||
static const char kTestFilename[] = "test_filename";
|
||||
static const char kTestHistogram[] = "test_histogram";
|
||||
const int kHistogramMin = 15;
|
||||
const int kHistogramMax = 1024;
|
||||
const int kHistogramBuckets = 23;
|
||||
|
||||
class TaggedCounterReporterTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
tagged_counter_ = new StrictMock<TaggedCounterMock>();
|
||||
reporter_.tagged_counter_.reset(tagged_counter_);
|
||||
metrics_lib_.reset(new StrictMock<MetricsLibraryMock>);
|
||||
reporter_.SetMetricsLibraryInterface(metrics_lib_.get());
|
||||
ASSERT_TRUE(metrics_lib_.get() == reporter_.metrics_lib_);
|
||||
}
|
||||
virtual void TearDown() {
|
||||
reporter_.SetMetricsLibraryInterface(NULL);
|
||||
}
|
||||
|
||||
void DoInit();
|
||||
StrictMock<TaggedCounterMock>* tagged_counter_;
|
||||
TaggedCounterReporter reporter_;
|
||||
scoped_ptr<MetricsLibraryMock> metrics_lib_;
|
||||
};
|
||||
|
||||
void TaggedCounterReporterTest::DoInit() {
|
||||
EXPECT_CALL(*tagged_counter_,
|
||||
Init(kTestFilename,
|
||||
TaggedCounterReporter::Report,
|
||||
&reporter_))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
reporter_.Init(kTestFilename,
|
||||
kTestHistogram,
|
||||
kHistogramMin,
|
||||
kHistogramMax,
|
||||
kHistogramBuckets);
|
||||
EXPECT_EQ(kTestHistogram, reporter_.histogram_name_);
|
||||
EXPECT_EQ(kHistogramBuckets, reporter_.buckets_);
|
||||
EXPECT_EQ(kHistogramMax, reporter_.max_);
|
||||
EXPECT_EQ(kHistogramMin, reporter_.min_);
|
||||
}
|
||||
|
||||
TEST_F(TaggedCounterReporterTest, Init) {
|
||||
DoInit();
|
||||
}
|
||||
|
||||
TEST_F(TaggedCounterReporterTest, Update) {
|
||||
DoInit();
|
||||
EXPECT_CALL(*tagged_counter_, Update(1, 2))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
reporter_.Update(1, 2);
|
||||
}
|
||||
|
||||
TEST_F(TaggedCounterReporterTest, Flush) {
|
||||
DoInit();
|
||||
EXPECT_CALL(*tagged_counter_, Flush())
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
reporter_.Flush();
|
||||
}
|
||||
|
||||
TEST_F(TaggedCounterReporterTest, Report) {
|
||||
DoInit();
|
||||
EXPECT_CALL(*metrics_lib_, SendToUMA(kTestHistogram,
|
||||
301,
|
||||
kHistogramMin,
|
||||
kHistogramMax,
|
||||
kHistogramBuckets))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
reporter_.Report(&reporter_, 127, 301);
|
||||
}
|
||||
|
||||
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) {
|
||||
tagged_counter_ = NULL;
|
||||
}
|
||||
|
||||
void CheckInit(int32 cycle_duration);
|
||||
|
@ -276,14 +348,10 @@ class FrequencyCounterTest : public testing::Test {
|
|||
};
|
||||
|
||||
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);
|
||||
tagged_counter_ = new StrictMock<TaggedCounterMock>;
|
||||
frequency_counter_.Init(tagged_counter_, cycle_duration);
|
||||
EXPECT_EQ(cycle_duration, frequency_counter_.cycle_duration_);
|
||||
EXPECT_EQ(tagged_counter_, frequency_counter_.tagged_counter_.get());
|
||||
}
|
||||
|
||||
TEST_F(FrequencyCounterTest, Init) {
|
||||
|
@ -292,10 +360,12 @@ TEST_F(FrequencyCounterTest, Init) {
|
|||
|
||||
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(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));
|
||||
}
|
||||
|
||||
|
@ -310,7 +380,9 @@ TEST_F(FrequencyCounterTest, GetCycleNumberForDay) {
|
|||
|
||||
TEST_F(FrequencyCounterTest, UpdateInternal) {
|
||||
CheckInit(kSecondsPerWeek);
|
||||
EXPECT_CALL(*tagged_counter_, Update(150, 2));
|
||||
EXPECT_CALL(*tagged_counter_, Update(150, 2))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
frequency_counter_.UpdateInternal(2, kSecondsPerWeek * 150);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
|
||||
#include "metrics_daemon.h"
|
||||
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <base/file_util.h>
|
||||
#include <base/logging.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
|
||||
#include "counter.h"
|
||||
|
||||
|
@ -43,7 +44,7 @@ const char kKernelCrashDetectedFile[] = "/tmp/kernel-crash-detected";
|
|||
static const char kUncleanShutdownDetectedFile[] =
|
||||
"/tmp/unclean-shutdown-detected";
|
||||
|
||||
// static metrics parameters.
|
||||
// static metrics parameters
|
||||
const char MetricsDaemon::kMetricDailyUseTimeName[] =
|
||||
"Logging.DailyUseTime";
|
||||
const int MetricsDaemon::kMetricDailyUseTimeMin = 1;
|
||||
|
@ -73,16 +74,26 @@ const int MetricsDaemon::kMetricCrashIntervalBuckets = 50;
|
|||
// crash frequency metrics
|
||||
const char MetricsDaemon::kMetricAnyCrashesDailyName[] =
|
||||
"Logging.AnyCrashesDaily";
|
||||
const char MetricsDaemon::kMetricAnyCrashesWeeklyName[] =
|
||||
"Logging.AnyCrashesWeekly";
|
||||
const char MetricsDaemon::kMetricKernelCrashesDailyName[] =
|
||||
"Logging.KernelCrashesDaily";
|
||||
const char MetricsDaemon::kMetricKernelCrashesWeeklyName[] =
|
||||
"Logging.KernelCrashesWeekly";
|
||||
const char MetricsDaemon::kMetricUncleanShutdownsDailyName[] =
|
||||
"Logging.UncleanShutdownsDaily";
|
||||
const char MetricsDaemon::kMetricUncleanShutdownsWeeklyName[] =
|
||||
"Logging.UncleanShutdownsWeekly";
|
||||
const char MetricsDaemon::kMetricUserCrashesDailyName[] =
|
||||
"Logging.UserCrashesDaily";
|
||||
const char MetricsDaemon::kMetricCrashesDailyMin = 1;
|
||||
const char MetricsDaemon::kMetricCrashesDailyMax = 100;
|
||||
const char MetricsDaemon::kMetricCrashesDailyBuckets = 50;
|
||||
const char MetricsDaemon::kMetricUserCrashesWeeklyName[] =
|
||||
"Logging.UserCrashesWeekly";
|
||||
const char MetricsDaemon::kMetricCrashFrequencyMin = 1;
|
||||
const char MetricsDaemon::kMetricCrashFrequencyMax = 100;
|
||||
const char MetricsDaemon::kMetricCrashFrequencyBuckets = 50;
|
||||
|
||||
// persistent metrics path
|
||||
const char MetricsDaemon::kMetricsPath[] = "/var/log/metrics";
|
||||
|
||||
|
||||
// static
|
||||
|
@ -182,7 +193,17 @@ MetricsDaemon::MetricsDaemon()
|
|||
usemon_interval_(0),
|
||||
usemon_source_(NULL) {}
|
||||
|
||||
MetricsDaemon::~MetricsDaemon() {}
|
||||
MetricsDaemon::~MetricsDaemon() {
|
||||
DeleteFrequencyCounters();
|
||||
}
|
||||
|
||||
void MetricsDaemon::DeleteFrequencyCounters() {
|
||||
for (FrequencyCounters::iterator i = frequency_counters_.begin();
|
||||
i != frequency_counters_.end(); ++i) {
|
||||
delete i->second;
|
||||
i->second = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void MetricsDaemon::Run(bool run_as_daemon) {
|
||||
if (run_as_daemon && daemon(0, 0) != 0)
|
||||
|
@ -199,64 +220,72 @@ void MetricsDaemon::Run(bool run_as_daemon) {
|
|||
Loop();
|
||||
}
|
||||
|
||||
FilePath MetricsDaemon::GetHistogramPath(const char* histogram_name) {
|
||||
return FilePath(kMetricsPath).Append(histogram_name);
|
||||
}
|
||||
|
||||
void MetricsDaemon::ConfigureCrashIntervalReporter(
|
||||
const char* histogram_name,
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterReporter>* reporter) {
|
||||
reporter->reset(new chromeos_metrics::TaggedCounterReporter());
|
||||
FilePath file_path = GetHistogramPath(histogram_name);
|
||||
(*reporter)->Init(file_path.value().c_str(),
|
||||
histogram_name,
|
||||
kMetricCrashIntervalMin,
|
||||
kMetricCrashIntervalMax,
|
||||
kMetricCrashIntervalBuckets);
|
||||
}
|
||||
|
||||
void MetricsDaemon::ConfigureCrashFrequencyReporter(
|
||||
const char* histogram_name) {
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterReporter> reporter(
|
||||
new chromeos_metrics::TaggedCounterReporter());
|
||||
FilePath file_path = GetHistogramPath(histogram_name);
|
||||
reporter->Init(file_path.value().c_str(),
|
||||
histogram_name,
|
||||
kMetricCrashFrequencyMin,
|
||||
kMetricCrashFrequencyMax,
|
||||
kMetricCrashFrequencyBuckets);
|
||||
scoped_ptr<chromeos_metrics::FrequencyCounter> new_counter(
|
||||
new chromeos_metrics::FrequencyCounter());
|
||||
time_t cycle_duration = strstr(histogram_name, "Weekly") != NULL ?
|
||||
chromeos_metrics::kSecondsPerWeek :
|
||||
chromeos_metrics::kSecondsPerDay;
|
||||
new_counter->Init(
|
||||
static_cast<chromeos_metrics::TaggedCounterInterface*>(
|
||||
reporter.release()),
|
||||
cycle_duration);
|
||||
frequency_counters_[histogram_name] = new_counter.release();
|
||||
}
|
||||
|
||||
void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) {
|
||||
testing_ = testing;
|
||||
DCHECK(metrics_lib != NULL);
|
||||
metrics_lib_ = metrics_lib;
|
||||
chromeos_metrics::TaggedCounterReporter::
|
||||
SetMetricsLibraryInterface(metrics_lib);
|
||||
|
||||
static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
|
||||
daily_use_.reset(new chromeos_metrics::TaggedCounter());
|
||||
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,
|
||||
&ReportUserCrashInterval, this);
|
||||
ConfigureCrashIntervalReporter(kMetricKernelCrashIntervalName,
|
||||
&kernel_crash_interval_);
|
||||
ConfigureCrashIntervalReporter(kMetricUncleanShutdownIntervalName,
|
||||
&unclean_shutdown_interval_);
|
||||
ConfigureCrashIntervalReporter(kMetricUserCrashIntervalName,
|
||||
&user_crash_interval_);
|
||||
|
||||
static const char kKernelCrashIntervalRecordFile[] =
|
||||
"/var/log/metrics/kernel-crash-interval";
|
||||
kernel_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
|
||||
kernel_crash_interval_->Init(kKernelCrashIntervalRecordFile,
|
||||
&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);
|
||||
DeleteFrequencyCounters();
|
||||
ConfigureCrashFrequencyReporter(kMetricAnyCrashesDailyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricAnyCrashesDailyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricAnyCrashesWeeklyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricKernelCrashesDailyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricKernelCrashesWeeklyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsDailyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricUncleanShutdownsWeeklyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricUserCrashesDailyName);
|
||||
ConfigureCrashFrequencyReporter(kMetricUserCrashesWeeklyName);
|
||||
|
||||
// Don't setup D-Bus and GLib in test mode.
|
||||
if (testing)
|
||||
|
@ -453,6 +482,12 @@ void MetricsDaemon::SetUserActiveState(bool active, Time now) {
|
|||
user_crash_interval_->Update(0, seconds);
|
||||
kernel_crash_interval_->Update(0, seconds);
|
||||
|
||||
// Flush finished cycles of all frequency counters.
|
||||
for (FrequencyCounters::iterator i = frequency_counters_.begin();
|
||||
i != frequency_counters_.end(); ++i) {
|
||||
i->second->FlushFinishedCycles();
|
||||
}
|
||||
|
||||
// Schedules a use monitor on inactive->active transitions and
|
||||
// unschedules it on active->inactive transitions.
|
||||
if (!user_active_ && active)
|
||||
|
@ -473,8 +508,10 @@ void MetricsDaemon::ProcessUserCrash() {
|
|||
// 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);
|
||||
frequency_counters_[kMetricUserCrashesDailyName]->Update(1);
|
||||
frequency_counters_[kMetricUserCrashesWeeklyName]->Update(1);
|
||||
frequency_counters_[kMetricAnyCrashesDailyName]->Update(1);
|
||||
frequency_counters_[kMetricAnyCrashesWeeklyName]->Update(1);
|
||||
}
|
||||
|
||||
void MetricsDaemon::ProcessKernelCrash() {
|
||||
|
@ -484,8 +521,10 @@ void MetricsDaemon::ProcessKernelCrash() {
|
|||
// 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);
|
||||
frequency_counters_[kMetricKernelCrashesDailyName]->Update(1);
|
||||
frequency_counters_[kMetricKernelCrashesWeeklyName]->Update(1);
|
||||
frequency_counters_[kMetricAnyCrashesDailyName]->Update(1);
|
||||
frequency_counters_[kMetricAnyCrashesWeeklyName]->Update(1);
|
||||
}
|
||||
|
||||
void MetricsDaemon::ProcessUncleanShutdown() {
|
||||
|
@ -495,8 +534,10 @@ void MetricsDaemon::ProcessUncleanShutdown() {
|
|||
// 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);
|
||||
frequency_counters_[kMetricUncleanShutdownsDailyName]->Update(1);
|
||||
frequency_counters_[kMetricUncleanShutdownsWeeklyName]->Update(1);
|
||||
frequency_counters_[kMetricAnyCrashesDailyName]->Update(1);
|
||||
frequency_counters_[kMetricAnyCrashesWeeklyName]->Update(1);
|
||||
}
|
||||
|
||||
bool MetricsDaemon::CheckSystemCrash(const std::string& crash_file) {
|
||||
|
@ -584,69 +625,6 @@ void MetricsDaemon::ReportDailyUse(void* handle, int tag, int count) {
|
|||
kMetricDailyUseTimeBuckets);
|
||||
}
|
||||
|
||||
// static
|
||||
void MetricsDaemon::ReportCrashInterval(const char* histogram_name,
|
||||
void* handle, int count) {
|
||||
MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
|
||||
daemon->SendMetric(histogram_name, count,
|
||||
kMetricCrashIntervalMin,
|
||||
kMetricCrashIntervalMax,
|
||||
kMetricCrashIntervalBuckets);
|
||||
}
|
||||
|
||||
// static
|
||||
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 << " "
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
#include <dbus/dbus.h>
|
||||
#include <glib.h>
|
||||
#include <map>
|
||||
|
||||
#include <base/file_path.h>
|
||||
#include <base/scoped_ptr.h>
|
||||
#include <base/time.h>
|
||||
#include <gtest/gtest_prod.h> // for FRIEND_TEST
|
||||
|
@ -16,7 +18,8 @@
|
|||
|
||||
namespace chromeos_metrics {
|
||||
class FrequencyCounter;
|
||||
class TaggedCounterInterface;
|
||||
class TaggedCounter;
|
||||
class TaggedCounterReporter;
|
||||
}
|
||||
|
||||
class MetricsDaemon {
|
||||
|
@ -35,6 +38,10 @@ class MetricsDaemon {
|
|||
private:
|
||||
friend class MetricsDaemonTest;
|
||||
FRIEND_TEST(MetricsDaemonTest, CheckSystemCrash);
|
||||
FRIEND_TEST(MetricsDaemonTest, ComputeEpochNoCurrent);
|
||||
FRIEND_TEST(MetricsDaemonTest, ComputeEpochNoLast);
|
||||
FRIEND_TEST(MetricsDaemonTest, GetHistogramPath);
|
||||
FRIEND_TEST(MetricsDaemonTest, IsNewEpoch);
|
||||
FRIEND_TEST(MetricsDaemonTest, LookupNetworkState);
|
||||
FRIEND_TEST(MetricsDaemonTest, LookupPowerState);
|
||||
FRIEND_TEST(MetricsDaemonTest, LookupScreenSaverState);
|
||||
|
@ -89,11 +96,15 @@ class MetricsDaemon {
|
|||
int seconds_;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, chromeos_metrics::FrequencyCounter*>
|
||||
FrequencyCounters;
|
||||
|
||||
// Metric parameters.
|
||||
static const char kMetricAnyCrashesDailyName[];
|
||||
static const char kMetricCrashesDailyBuckets;
|
||||
static const char kMetricCrashesDailyMax;
|
||||
static const char kMetricCrashesDailyMin;
|
||||
static const char kMetricAnyCrashesWeeklyName[];
|
||||
static const char kMetricCrashFrequencyBuckets;
|
||||
static const char kMetricCrashFrequencyMax;
|
||||
static const char kMetricCrashFrequencyMin;
|
||||
static const int kMetricCrashIntervalBuckets;
|
||||
static const int kMetricCrashIntervalMax;
|
||||
static const int kMetricCrashIntervalMin;
|
||||
|
@ -102,14 +113,18 @@ class MetricsDaemon {
|
|||
static const int kMetricDailyUseTimeMin;
|
||||
static const char kMetricDailyUseTimeName[];
|
||||
static const char kMetricKernelCrashesDailyName[];
|
||||
static const char kMetricKernelCrashesWeeklyName[];
|
||||
static const char kMetricKernelCrashIntervalName[];
|
||||
static const char kMetricsPath[];
|
||||
static const int kMetricTimeToNetworkDropBuckets;
|
||||
static const int kMetricTimeToNetworkDropMax;
|
||||
static const int kMetricTimeToNetworkDropMin;
|
||||
static const char kMetricTimeToNetworkDropName[];
|
||||
static const char kMetricUncleanShutdownIntervalName[];
|
||||
static const char kMetricUncleanShutdownsDailyName[];
|
||||
static const char kMetricUncleanShutdownsWeeklyName[];
|
||||
static const char kMetricUserCrashesDailyName[];
|
||||
static const char kMetricUserCrashesWeeklyName[];
|
||||
static const char kMetricUserCrashIntervalName[];
|
||||
|
||||
// D-Bus message match strings.
|
||||
|
@ -124,6 +139,20 @@ class MetricsDaemon {
|
|||
// Array of user session states.
|
||||
static const char* kSessionStates_[kNumberSessionStates];
|
||||
|
||||
// Clears and deletes the data contained in frequency_counters_.
|
||||
void DeleteFrequencyCounters();
|
||||
|
||||
// Configures the given crash interval reporter.
|
||||
void ConfigureCrashIntervalReporter(
|
||||
const char* histogram_name,
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterReporter>* reporter);
|
||||
|
||||
// Configures the given frequency counter reporter.
|
||||
void ConfigureCrashFrequencyReporter(const char* histogram_name);
|
||||
|
||||
// Returns file path to persistent file for generating given histogram.
|
||||
FilePath GetHistogramPath(const char* histogram_name);
|
||||
|
||||
// Creates the event loop and enters it.
|
||||
void Loop();
|
||||
|
||||
|
@ -203,48 +232,15 @@ class MetricsDaemon {
|
|||
// Unschedules a scheduled use monitor, if any.
|
||||
void UnscheduleUseMonitor();
|
||||
|
||||
// Report daily use through UMA.
|
||||
static void ReportDailyUse(void* handle, int tag, int count);
|
||||
|
||||
// Sends a regular (exponential) histogram sample to Chrome for
|
||||
// transport to UMA. See MetricsLibrary::SendToUMA in
|
||||
// metrics_library.h for a description of the arguments.
|
||||
void SendMetric(const std::string& name, int sample,
|
||||
int min, int max, int nbuckets);
|
||||
|
||||
// TaggedCounter callback to process aggregated daily usage data and
|
||||
// send to UMA.
|
||||
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 ReportUserCrashInterval(void* data, int tag, int count);
|
||||
|
||||
// TaggedCounter callback to process time between kernel crashes and
|
||||
// send to UMA.
|
||||
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_;
|
||||
|
||||
|
@ -275,30 +271,20 @@ class MetricsDaemon {
|
|||
base::Time user_active_last_;
|
||||
|
||||
// Daily active use time in seconds.
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterInterface> daily_use_;
|
||||
scoped_ptr<chromeos_metrics::TaggedCounter> daily_use_;
|
||||
|
||||
// Active use time between user-space process crashes.
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterInterface> user_crash_interval_;
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterReporter> user_crash_interval_;
|
||||
|
||||
// Active use time between kernel crashes.
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterInterface> kernel_crash_interval_;
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterReporter> kernel_crash_interval_;
|
||||
|
||||
// Active use time between unclean shutdowns crashes.
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterInterface>
|
||||
scoped_ptr<chromeos_metrics::TaggedCounterReporter>
|
||||
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_;
|
||||
// Map of all frequency counters, to simplify flushing them.
|
||||
FrequencyCounters frequency_counters_;
|
||||
|
||||
// Sleep period until the next daily usage aggregation performed by
|
||||
// the daily use monitor (see ScheduleUseMonitor).
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <utime.h>
|
||||
|
||||
#include <base/file_util.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
@ -11,14 +13,21 @@
|
|||
|
||||
using base::Time;
|
||||
using base::TimeTicks;
|
||||
using chromeos_metrics::FrequencyCounter;
|
||||
using chromeos_metrics::FrequencyCounterMock;
|
||||
using chromeos_metrics::TaggedCounterMock;
|
||||
using chromeos_metrics::TaggedCounterReporter;
|
||||
using chromeos_metrics::TaggedCounterReporterMock;
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
static const int kSecondsPerDay = 24 * 60 * 60;
|
||||
|
||||
static const char kTestDir[] = "test";
|
||||
static const char kLastFile[] = "test/last";
|
||||
static const char kCurrentFile[] = "test/current";
|
||||
|
||||
// This class allows a TimeTicks object to be initialized with seconds
|
||||
// (rather than microseconds) through the protected TimeTicks(int64)
|
||||
// constructor.
|
||||
|
@ -48,6 +57,38 @@ class MetricsDaemonTest : public testing::Test {
|
|||
EXPECT_EQ(NULL, daemon_.user_crash_interval_.get());
|
||||
daemon_.Init(true, &metrics_lib_);
|
||||
|
||||
// Check configuration of a few histograms.
|
||||
FrequencyCounter* frequency_counter =
|
||||
daemon_.frequency_counters_[MetricsDaemon::kMetricAnyCrashesDailyName];
|
||||
const TaggedCounterReporter* reporter = GetReporter(frequency_counter);
|
||||
EXPECT_EQ(MetricsDaemon::kMetricAnyCrashesDailyName,
|
||||
reporter->histogram_name());
|
||||
EXPECT_EQ(chromeos_metrics::kSecondsPerDay,
|
||||
frequency_counter->cycle_duration());
|
||||
EXPECT_EQ(MetricsDaemon::kMetricCrashFrequencyMin, reporter->min());
|
||||
EXPECT_EQ(MetricsDaemon::kMetricCrashFrequencyMax, reporter->max());
|
||||
EXPECT_EQ(MetricsDaemon::kMetricCrashFrequencyBuckets, reporter->buckets());
|
||||
|
||||
frequency_counter =
|
||||
daemon_.frequency_counters_[MetricsDaemon::kMetricAnyCrashesWeeklyName];
|
||||
reporter = GetReporter(frequency_counter);
|
||||
EXPECT_EQ(MetricsDaemon::kMetricAnyCrashesWeeklyName,
|
||||
reporter->histogram_name());
|
||||
EXPECT_EQ(chromeos_metrics::kSecondsPerWeek,
|
||||
frequency_counter->cycle_duration());
|
||||
|
||||
EXPECT_EQ(MetricsDaemon::kMetricKernelCrashIntervalName,
|
||||
daemon_.kernel_crash_interval_->histogram_name());
|
||||
EXPECT_EQ(MetricsDaemon::kMetricCrashIntervalMin,
|
||||
daemon_.kernel_crash_interval_->min());
|
||||
EXPECT_EQ(MetricsDaemon::kMetricCrashIntervalMax,
|
||||
daemon_.kernel_crash_interval_->max());
|
||||
EXPECT_EQ(MetricsDaemon::kMetricCrashIntervalBuckets,
|
||||
daemon_.kernel_crash_interval_->buckets());
|
||||
|
||||
EXPECT_EQ(MetricsDaemon::kMetricUncleanShutdownIntervalName,
|
||||
daemon_.unclean_shutdown_interval_->histogram_name());
|
||||
|
||||
// Tests constructor initialization. Switches to mock counters.
|
||||
EXPECT_TRUE(NULL != daemon_.daily_use_.get());
|
||||
EXPECT_TRUE(NULL != daemon_.kernel_crash_interval_.get());
|
||||
|
@ -56,20 +97,20 @@ class MetricsDaemonTest : public testing::Test {
|
|||
// Allocates mock counter and transfers ownership.
|
||||
daily_use_ = new StrictMock<TaggedCounterMock>();
|
||||
daemon_.daily_use_.reset(daily_use_);
|
||||
kernel_crash_interval_ = new StrictMock<TaggedCounterMock>();
|
||||
kernel_crash_interval_ = new StrictMock<TaggedCounterReporterMock>();
|
||||
daemon_.kernel_crash_interval_.reset(kernel_crash_interval_);
|
||||
user_crash_interval_ = new StrictMock<TaggedCounterMock>();
|
||||
user_crash_interval_ = new StrictMock<TaggedCounterReporterMock>();
|
||||
daemon_.user_crash_interval_.reset(user_crash_interval_);
|
||||
unclean_shutdown_interval_ = new StrictMock<TaggedCounterMock>();
|
||||
unclean_shutdown_interval_ = new StrictMock<TaggedCounterReporterMock>();
|
||||
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_);
|
||||
|
||||
// Reset all frequency counter reporters to mocks for further testing.
|
||||
MetricsDaemon::FrequencyCounters::iterator i;
|
||||
for (i = daemon_.frequency_counters_.begin();
|
||||
i != daemon_.frequency_counters_.end(); ++i) {
|
||||
delete i->second;
|
||||
i->second = new StrictMock<FrequencyCounterMock>();
|
||||
}
|
||||
|
||||
EXPECT_FALSE(daemon_.user_active_);
|
||||
EXPECT_TRUE(daemon_.user_active_last_.is_null());
|
||||
|
@ -77,10 +118,29 @@ class MetricsDaemonTest : public testing::Test {
|
|||
EXPECT_TRUE(daemon_.network_state_last_.is_null());
|
||||
EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
|
||||
EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
|
||||
|
||||
file_util::Delete(FilePath(kTestDir), true);
|
||||
file_util::CreateDirectory(FilePath(kTestDir));
|
||||
}
|
||||
|
||||
virtual void TearDown() {}
|
||||
|
||||
const TaggedCounterReporter*
|
||||
GetReporter(FrequencyCounter* frequency_counter) const {
|
||||
return static_cast<const TaggedCounterReporter*>(
|
||||
&frequency_counter->tagged_counter());
|
||||
}
|
||||
|
||||
void ExpectFrequencyFlushCalls() {
|
||||
MetricsDaemon::FrequencyCounters::iterator i;
|
||||
for (i = daemon_.frequency_counters_.begin();
|
||||
i != daemon_.frequency_counters_.end(); ++i) {
|
||||
FrequencyCounterMock* mock =
|
||||
static_cast<FrequencyCounterMock*>(i->second);
|
||||
EXPECT_CALL(*mock, FlushFinishedCycles());
|
||||
}
|
||||
}
|
||||
|
||||
// Adds active use aggregation counters update expectations that the
|
||||
// specified tag/count update will be generated.
|
||||
void ExpectActiveUseUpdate(int daily_tag, int count) {
|
||||
|
@ -93,6 +153,7 @@ class MetricsDaemonTest : public testing::Test {
|
|||
EXPECT_CALL(*user_crash_interval_, Update(0, count))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
ExpectFrequencyFlushCalls();
|
||||
}
|
||||
|
||||
// Adds active use aggregation counters update expectations that
|
||||
|
@ -107,6 +168,7 @@ class MetricsDaemonTest : public testing::Test {
|
|||
EXPECT_CALL(*user_crash_interval_, Update(_, _))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
ExpectFrequencyFlushCalls();
|
||||
}
|
||||
|
||||
// Adds a metrics library mock expectation that the specified metric
|
||||
|
@ -170,6 +232,12 @@ class MetricsDaemonTest : public testing::Test {
|
|||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
// Get the frequency counter for the given name.
|
||||
FrequencyCounterMock& GetFrequencyMock(const char* histogram_name) {
|
||||
return *static_cast<FrequencyCounterMock*>(
|
||||
daemon_.frequency_counters_[histogram_name]);
|
||||
}
|
||||
|
||||
// The MetricsDaemon under test.
|
||||
MetricsDaemon daemon_;
|
||||
|
||||
|
@ -181,14 +249,9 @@ class MetricsDaemonTest : public testing::Test {
|
|||
// update calls are marked as failures. They are pointers so that
|
||||
// they can replace the scoped_ptr's allocated by the daemon.
|
||||
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_;
|
||||
StrictMock<TaggedCounterReporterMock>* kernel_crash_interval_;
|
||||
StrictMock<TaggedCounterReporterMock>* user_crash_interval_;
|
||||
StrictMock<TaggedCounterReporterMock>* unclean_shutdown_interval_;
|
||||
};
|
||||
|
||||
TEST_F(MetricsDaemonTest, CheckSystemCrash) {
|
||||
|
@ -217,22 +280,6 @@ TEST_F(MetricsDaemonTest, ReportDailyUse) {
|
|||
MetricsDaemon::ReportDailyUse(&daemon_, /* tag */ 60, /* count */ -5);
|
||||
}
|
||||
|
||||
TEST_F(MetricsDaemonTest, ReportKernelCrashInterval) {
|
||||
ExpectMetric(MetricsDaemon::kMetricKernelCrashIntervalName, 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) {
|
||||
EXPECT_EQ(MetricsDaemon::kNetworkStateOnline,
|
||||
daemon_.LookupNetworkState("online"));
|
||||
|
@ -268,15 +315,25 @@ TEST_F(MetricsDaemonTest, MessageFilter) {
|
|||
DeleteDBusMessage(msg);
|
||||
|
||||
IgnoreActiveUseUpdate();
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesDailyName),
|
||||
Update(1))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesWeeklyName),
|
||||
Update(1))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricUserCrashesDailyName),
|
||||
Update(1))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricUserCrashesWeeklyName),
|
||||
Update(1))
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
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",
|
||||
|
@ -410,8 +467,14 @@ TEST_F(MetricsDaemonTest, ProcessKernelCrash) {
|
|||
EXPECT_CALL(*kernel_crash_interval_, Flush())
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(*kernel_crashes_daily_, Update(1));
|
||||
EXPECT_CALL(*any_crashes_daily_, Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesDailyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesWeeklyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricKernelCrashesDailyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricKernelCrashesWeeklyName),
|
||||
Update(1));
|
||||
daemon_.ProcessKernelCrash();
|
||||
}
|
||||
|
||||
|
@ -420,8 +483,15 @@ TEST_F(MetricsDaemonTest, ProcessUncleanShutdown) {
|
|||
EXPECT_CALL(*unclean_shutdown_interval_, Flush())
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(*unclean_shutdowns_daily_, Update(1));
|
||||
EXPECT_CALL(*any_crashes_daily_, Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesDailyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesWeeklyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricUncleanShutdownsDailyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(
|
||||
GetFrequencyMock(MetricsDaemon::kMetricUncleanShutdownsWeeklyName),
|
||||
Update(1));
|
||||
daemon_.ProcessUncleanShutdown();
|
||||
}
|
||||
|
||||
|
@ -430,8 +500,14 @@ TEST_F(MetricsDaemonTest, ProcessUserCrash) {
|
|||
EXPECT_CALL(*user_crash_interval_, Flush())
|
||||
.Times(1)
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(*user_crashes_daily_, Update(1));
|
||||
EXPECT_CALL(*any_crashes_daily_, Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesDailyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricAnyCrashesWeeklyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricUserCrashesDailyName),
|
||||
Update(1));
|
||||
EXPECT_CALL(GetFrequencyMock(MetricsDaemon::kMetricUserCrashesWeeklyName),
|
||||
Update(1));
|
||||
daemon_.ProcessUserCrash();
|
||||
}
|
||||
|
||||
|
@ -514,20 +590,10 @@ TEST_F(MetricsDaemonTest, SetUserActiveStateTimeJump) {
|
|||
EXPECT_EQ(TestTime(10 * kSecondsPerDay + 1000), daemon_.user_active_last_);
|
||||
}
|
||||
|
||||
TEST_F(MetricsDaemonTest, ReportUserCrashInterval) {
|
||||
ExpectMetric(MetricsDaemon::kMetricUserCrashIntervalName, 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);
|
||||
TEST_F(MetricsDaemonTest, GetHistogramPath) {
|
||||
EXPECT_EQ("/var/log/metrics/Logging.AnyCrashesDaily",
|
||||
daemon_.GetHistogramPath(
|
||||
MetricsDaemon::kMetricAnyCrashesDailyName).value());
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
@ -14,12 +15,14 @@
|
|||
#define READ_WRITE_ALL_FILE_FLAGS \
|
||||
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||
|
||||
static const char kAutotestPath[] =
|
||||
"/var/log/metrics/autotest-events";
|
||||
static const char kUMAEventsPath[] =
|
||||
"/var/log/metrics/uma-events";
|
||||
static const char kAutotestPath[] = "/var/log/metrics/autotest-events";
|
||||
static const char kUMAEventsPath[] = "/var/log/metrics/uma-events";
|
||||
static const char kConsentFile[] = "/home/chronos/Consent To Send Stats";
|
||||
static const int32_t kBufferSize = 1024;
|
||||
|
||||
time_t MetricsLibrary::cached_enabled_time_ = 0;
|
||||
bool MetricsLibrary::cached_enabled_ = false;
|
||||
|
||||
using std::string;
|
||||
|
||||
// TODO(sosa@chromium.org) - use Chromium logger instead of stderr
|
||||
|
@ -38,9 +41,24 @@ static void PrintError(const char* message, const char* file,
|
|||
}
|
||||
|
||||
MetricsLibrary::MetricsLibrary()
|
||||
: uma_events_file_(NULL) {}
|
||||
: uma_events_file_(NULL),
|
||||
consent_file_(kConsentFile) {}
|
||||
|
||||
bool MetricsLibrary::AreMetricsEnabled() {
|
||||
static struct stat stat_buffer;
|
||||
time_t this_check_time = time(NULL);
|
||||
|
||||
if (this_check_time != cached_enabled_time_) {
|
||||
cached_enabled_time_ = this_check_time;
|
||||
cached_enabled_ = (stat(consent_file_, &stat_buffer) >= 0);
|
||||
}
|
||||
return cached_enabled_;
|
||||
}
|
||||
|
||||
bool MetricsLibrary::SendMessageToChrome(int32_t length, const char* message) {
|
||||
if (!AreMetricsEnabled())
|
||||
return true;
|
||||
|
||||
int chrome_fd = open(uma_events_file_,
|
||||
O_WRONLY | O_APPEND | O_CREAT,
|
||||
READ_WRITE_ALL_FILE_FLAGS);
|
||||
|
|
|
@ -27,6 +27,9 @@ class MetricsLibrary : public MetricsLibraryInterface {
|
|||
// Initializes the library.
|
||||
void Init();
|
||||
|
||||
// Returns whether or not metrics collection is enabled.
|
||||
bool AreMetricsEnabled();
|
||||
|
||||
// Sends histogram data to Chrome for transport to UMA and returns
|
||||
// true on success. This method results in the equivalent of an
|
||||
// asynchronous non-blocking RPC to UMA_HISTOGRAM_CUSTOM_COUNTS
|
||||
|
@ -69,6 +72,7 @@ class MetricsLibrary : public MetricsLibraryInterface {
|
|||
private:
|
||||
friend class CMetricsLibraryTest;
|
||||
friend class MetricsLibraryTest;
|
||||
FRIEND_TEST(MetricsLibraryTest, AreMetricsEnabled);
|
||||
FRIEND_TEST(MetricsLibraryTest, FormatChromeMessage);
|
||||
FRIEND_TEST(MetricsLibraryTest, FormatChromeMessageTooLong);
|
||||
FRIEND_TEST(MetricsLibraryTest, SendMessageToChrome);
|
||||
|
@ -89,7 +93,14 @@ class MetricsLibrary : public MetricsLibraryInterface {
|
|||
int32_t FormatChromeMessage(int32_t buffer_size, char* buffer,
|
||||
const char* format, ...);
|
||||
|
||||
// Time at which we last checked if metrics were enabled.
|
||||
static time_t cached_enabled_time_;
|
||||
|
||||
// Cached state of whether or not metrics were enabled.
|
||||
static bool cached_enabled_;
|
||||
|
||||
const char* uma_events_file_;
|
||||
const char* consent_file_;
|
||||
};
|
||||
|
||||
#endif // METRICS_LIBRARY_H_
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
|
||||
static const FilePath kTestUMAEventsFile("test-uma-events");
|
||||
|
||||
static const char kTestConsent[] = "test-consent";
|
||||
|
||||
static void SetMetricsEnabled(bool enabled) {
|
||||
if (enabled)
|
||||
ASSERT_EQ(1, file_util::WriteFile(FilePath(kTestConsent) , "0", 1));
|
||||
else
|
||||
file_util::Delete(FilePath(kTestConsent), false);
|
||||
}
|
||||
|
||||
class MetricsLibraryTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
|
@ -19,15 +28,63 @@ class MetricsLibraryTest : public testing::Test {
|
|||
lib_.Init();
|
||||
EXPECT_TRUE(NULL != lib_.uma_events_file_);
|
||||
lib_.uma_events_file_ = kTestUMAEventsFile.value().c_str();
|
||||
SetMetricsEnabled(true);
|
||||
// Defeat metrics enabled caching between tests.
|
||||
lib_.cached_enabled_time_ = 0;
|
||||
lib_.consent_file_ = kTestConsent;
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
file_util::Delete(kTestUMAEventsFile, false);
|
||||
}
|
||||
|
||||
void VerifyEnabledCacheHit(bool to_value);
|
||||
void VerifyEnabledCacheEviction(bool to_value);
|
||||
|
||||
MetricsLibrary lib_;
|
||||
};
|
||||
|
||||
TEST_F(MetricsLibraryTest, AreMetricsEnabledFalse) {
|
||||
SetMetricsEnabled(false);
|
||||
EXPECT_FALSE(lib_.AreMetricsEnabled());
|
||||
}
|
||||
|
||||
TEST_F(MetricsLibraryTest, AreMetricsEnabledTrue) {
|
||||
EXPECT_TRUE(lib_.AreMetricsEnabled());
|
||||
}
|
||||
|
||||
void MetricsLibraryTest::VerifyEnabledCacheHit(bool to_value) {
|
||||
// We might step from one second to the next one time, but not 100
|
||||
// times in a row.
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
lib_.cached_enabled_time_ = 0;
|
||||
SetMetricsEnabled(!to_value);
|
||||
ASSERT_EQ(!to_value, lib_.AreMetricsEnabled());
|
||||
SetMetricsEnabled(to_value);
|
||||
if (lib_.AreMetricsEnabled() == !to_value)
|
||||
return;
|
||||
}
|
||||
ADD_FAILURE() << "Did not see evidence of caching";
|
||||
}
|
||||
|
||||
void MetricsLibraryTest::VerifyEnabledCacheEviction(bool to_value) {
|
||||
lib_.cached_enabled_time_ = 0;
|
||||
SetMetricsEnabled(!to_value);
|
||||
ASSERT_EQ(!to_value, lib_.AreMetricsEnabled());
|
||||
SetMetricsEnabled(to_value);
|
||||
ASSERT_LT(abs(time(NULL) - lib_.cached_enabled_time_), 5);
|
||||
// Sleep one second (or cheat to be faster).
|
||||
--lib_.cached_enabled_time_;
|
||||
ASSERT_EQ(to_value, lib_.AreMetricsEnabled());
|
||||
}
|
||||
|
||||
TEST_F(MetricsLibraryTest, AreMetricsEnabledCaching) {
|
||||
VerifyEnabledCacheHit(false);
|
||||
VerifyEnabledCacheHit(true);
|
||||
VerifyEnabledCacheEviction(false);
|
||||
VerifyEnabledCacheEviction(true);
|
||||
}
|
||||
|
||||
TEST_F(MetricsLibraryTest, FormatChromeMessage) {
|
||||
char buf[7];
|
||||
const int kLen = 6;
|
||||
|
@ -55,6 +112,12 @@ TEST_F(MetricsLibraryTest, SendEnumToUMA) {
|
|||
EXPECT_EQ(0, memcmp(exp, buf, kLen));
|
||||
}
|
||||
|
||||
TEST_F(MetricsLibraryTest, SendEnumToUMANotEnabled) {
|
||||
SetMetricsEnabled(false);
|
||||
EXPECT_TRUE(lib_.SendEnumToUMA("Test.EnumMetric", 1, 3));
|
||||
EXPECT_FALSE(file_util::PathExists(kTestUMAEventsFile));
|
||||
}
|
||||
|
||||
TEST_F(MetricsLibraryTest, SendMessageToChrome) {
|
||||
EXPECT_TRUE(lib_.SendMessageToChrome(4, "test"));
|
||||
EXPECT_TRUE(lib_.SendMessageToChrome(7, "content"));
|
||||
|
@ -84,6 +147,12 @@ TEST_F(MetricsLibraryTest, SendToUMA) {
|
|||
EXPECT_EQ(0, memcmp(exp, buf, kLen));
|
||||
}
|
||||
|
||||
TEST_F(MetricsLibraryTest, SendToUMANotEnabled) {
|
||||
SetMetricsEnabled(false);
|
||||
EXPECT_TRUE(lib_.SendToUMA("Test.Metric", 2, 1, 100, 50));
|
||||
EXPECT_FALSE(file_util::PathExists(kTestUMAEventsFile));
|
||||
}
|
||||
|
||||
class CMetricsLibraryTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
|
@ -93,6 +162,9 @@ class CMetricsLibraryTest : public testing::Test {
|
|||
CMetricsLibraryInit(lib_);
|
||||
EXPECT_TRUE(NULL != ml.uma_events_file_);
|
||||
ml.uma_events_file_ = kTestUMAEventsFile.value().c_str();
|
||||
SetMetricsEnabled(true);
|
||||
reinterpret_cast<MetricsLibrary*>(lib_)->cached_enabled_time_ = 0;
|
||||
reinterpret_cast<MetricsLibrary*>(lib_)->consent_file_ = kTestConsent;
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
|
@ -103,6 +175,15 @@ class CMetricsLibraryTest : public testing::Test {
|
|||
CMetricsLibrary lib_;
|
||||
};
|
||||
|
||||
TEST_F(CMetricsLibraryTest, AreMetricsEnabledFalse) {
|
||||
SetMetricsEnabled(false);
|
||||
EXPECT_FALSE(CMetricsLibraryAreMetricsEnabled(lib_));
|
||||
}
|
||||
|
||||
TEST_F(CMetricsLibraryTest, AreMetricsEnabledTrue) {
|
||||
EXPECT_TRUE(CMetricsLibraryAreMetricsEnabled(lib_));
|
||||
}
|
||||
|
||||
TEST_F(CMetricsLibraryTest, SendEnumToUMA) {
|
||||
char buf[100];
|
||||
const int kLen = 40;
|
||||
|
|
Loading…
Reference in New Issue