Add unit tests for CountMetricProducer, EventMetricProducer
And other miscellaneous fixes. + clang-format + 2 bug fixes, one in dump-report command, one in ResourcePowerManagerPuller Test: statsd_test Change-Id: Ibd164d948ad62adcc529d813df1210781e38be47
This commit is contained in:
@@ -157,8 +157,10 @@ LOCAL_SRC_FILES := \
|
||||
tests/LogReader_test.cpp \
|
||||
tests/MetricsManager_test.cpp \
|
||||
tests/UidMap_test.cpp \
|
||||
tests/OringDurationTracker_test.cpp \
|
||||
tests/MaxDurationTracker_test.cpp
|
||||
tests/metrics/OringDurationTracker_test.cpp \
|
||||
tests/metrics/MaxDurationTracker_test.cpp \
|
||||
tests/metrics/CountMetricProducer_test.cpp \
|
||||
tests/metrics/EventMetricProducer_test.cpp
|
||||
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
|
||||
@@ -89,7 +89,7 @@ ConfigMetricsReport StatsLogProcessor::onDumpReport(const ConfigKey& key) {
|
||||
*dest = m;
|
||||
}
|
||||
auto temp = mUidMap->getOutput(key);
|
||||
report.set_allocated_uid_map(&temp);
|
||||
report.mutable_uid_map()->Swap(&temp);
|
||||
return report;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,28 +83,31 @@ bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEven
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t timestamp = time(nullptr) * NS_PER_SEC;
|
||||
|
||||
data->clear();
|
||||
Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
|
||||
[&data](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
|
||||
[&data, timestamp](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
|
||||
|
||||
if (status != Status::SUCCESS) return;
|
||||
|
||||
for (size_t i = 0; i < states.size(); i++) {
|
||||
const PowerStatePlatformSleepState& state = states[i];
|
||||
|
||||
auto statePtr = make_shared<LogEvent>(power_state_platform_sleep_state_tag);
|
||||
auto statePtr =
|
||||
make_shared<LogEvent>(power_state_platform_sleep_state_tag, timestamp);
|
||||
auto elemList = statePtr->GetAndroidLogEventList();
|
||||
*elemList << state.name;
|
||||
*elemList << state.residencyInMsecSinceBoot;
|
||||
*elemList << state.totalTransitions;
|
||||
*elemList << state.supportedOnlyInSuspend;
|
||||
statePtr->init();
|
||||
data->push_back(statePtr);
|
||||
|
||||
VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
|
||||
(long long)state.residencyInMsecSinceBoot,
|
||||
(long long)state.totalTransitions, state.supportedOnlyInSuspend ? 1 : 0);
|
||||
for (auto voter : state.voters) {
|
||||
auto voterPtr = make_shared<LogEvent>(power_state_voter_tag);
|
||||
auto voterPtr = make_shared<LogEvent>(power_state_voter_tag, timestamp);
|
||||
auto elemList = voterPtr->GetAndroidLogEventList();
|
||||
*elemList << state.name;
|
||||
*elemList << voter.name;
|
||||
@@ -128,7 +131,7 @@ bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEven
|
||||
android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
|
||||
if (gPowerHal_1_1 != nullptr) {
|
||||
ret = gPowerHal_1_1->getSubsystemLowPowerStats(
|
||||
[&data](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
|
||||
[&data, timestamp](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
|
||||
|
||||
if (status != Status::SUCCESS) return;
|
||||
|
||||
@@ -137,8 +140,8 @@ bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEven
|
||||
const PowerStateSubsystem& subsystem = subsystems[i];
|
||||
for (size_t j = 0; j < subsystem.states.size(); j++) {
|
||||
const PowerStateSubsystemSleepState& state = subsystem.states[j];
|
||||
auto subsystemStatePtr =
|
||||
make_shared<LogEvent>(power_state_subsystem_state_tag);
|
||||
auto subsystemStatePtr = make_shared<LogEvent>(
|
||||
power_state_subsystem_state_tag, timestamp);
|
||||
auto elemList = subsystemStatePtr->GetAndroidLogEventList();
|
||||
*elemList << subsystem.name;
|
||||
*elemList << state.name;
|
||||
@@ -146,6 +149,7 @@ bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEven
|
||||
*elemList << state.totalTransitions;
|
||||
*elemList << state.lastEntryTimestampMs;
|
||||
*elemList << state.supportedOnlyInSuspend;
|
||||
subsystemStatePtr->init();
|
||||
data->push_back(subsystemStatePtr);
|
||||
VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
|
||||
subsystem.name.c_str(), state.name.c_str(),
|
||||
|
||||
62
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
62
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
@@ -30,11 +30,11 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using std::make_shared;
|
||||
using std::map;
|
||||
using std::shared_ptr;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::make_shared;
|
||||
using std::shared_ptr;
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
@@ -42,40 +42,35 @@ namespace statsd {
|
||||
|
||||
StatsPullerManager::StatsPullerManager()
|
||||
: mCurrentPullingInterval(LONG_MAX), mPullStartTimeMs(get_pull_start_time_ms()) {
|
||||
shared_ptr<StatsPuller> statsCompanionServicePuller = make_shared<StatsCompanionServicePuller>();
|
||||
shared_ptr <StatsPuller>
|
||||
resourcePowerManagerPuller = make_shared<ResourcePowerManagerPuller>();
|
||||
shared_ptr<StatsPuller> statsCompanionServicePuller =
|
||||
make_shared<StatsCompanionServicePuller>();
|
||||
shared_ptr<StatsPuller> resourcePowerManagerPuller = make_shared<ResourcePowerManagerPuller>();
|
||||
|
||||
mPullers.insert({android::util::KERNEL_WAKELOCK_PULLED,
|
||||
statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::WIFI_BYTES_TRANSFERRED,
|
||||
statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::MOBILE_BYTES_TRANSFERRED,
|
||||
statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::WIFI_BYTES_TRANSFERRED_BY_FG_BG,
|
||||
statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::MOBILE_BYTES_TRANSFERRED_BY_FG_BG,
|
||||
statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::POWER_STATE_PLATFORM_SLEEP_STATE_PULLED,
|
||||
resourcePowerManagerPuller});
|
||||
mPullers.insert({android::util::POWER_STATE_VOTER_PULLED,
|
||||
resourcePowerManagerPuller});
|
||||
mPullers.insert({android::util::POWER_STATE_SUBSYSTEM_SLEEP_STATE_PULLED,
|
||||
resourcePowerManagerPuller});
|
||||
mPullers.insert({android::util::KERNEL_WAKELOCK_PULLED, statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::WIFI_BYTES_TRANSFERRED, statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::MOBILE_BYTES_TRANSFERRED, statsCompanionServicePuller});
|
||||
mPullers.insert({android::util::WIFI_BYTES_TRANSFERRED_BY_FG_BG, statsCompanionServicePuller});
|
||||
mPullers.insert(
|
||||
{android::util::MOBILE_BYTES_TRANSFERRED_BY_FG_BG, statsCompanionServicePuller});
|
||||
mPullers.insert(
|
||||
{android::util::POWER_STATE_PLATFORM_SLEEP_STATE_PULLED, resourcePowerManagerPuller});
|
||||
mPullers.insert({android::util::POWER_STATE_VOTER_PULLED, resourcePowerManagerPuller});
|
||||
mPullers.insert(
|
||||
{android::util::POWER_STATE_SUBSYSTEM_SLEEP_STATE_PULLED, resourcePowerManagerPuller});
|
||||
|
||||
mStatsCompanionService = StatsService::getStatsCompanionService();
|
||||
}
|
||||
|
||||
bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
|
||||
if (DEBUG) ALOGD("Initiating pulling %d", tagId);
|
||||
bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
|
||||
if (DEBUG) ALOGD("Initiating pulling %d", tagId);
|
||||
|
||||
if (mPullers.find(tagId) != mPullers.end()) {
|
||||
return mPullers.find(tagId)->second->Pull(tagId, data);
|
||||
} else {
|
||||
ALOGD("Unknown tagId %d", tagId);
|
||||
return false; // Return early since we don't know what to pull.
|
||||
}
|
||||
}
|
||||
if (mPullers.find(tagId) != mPullers.end()) {
|
||||
return mPullers.find(tagId)->second->Pull(tagId, data);
|
||||
} else {
|
||||
ALOGD("Unknown tagId %d", tagId);
|
||||
return false; // Return early since we don't know what to pull.
|
||||
}
|
||||
}
|
||||
|
||||
StatsPullerManager& StatsPullerManager::GetInstance() {
|
||||
static StatsPullerManager instance;
|
||||
@@ -91,7 +86,8 @@ long StatsPullerManager::get_pull_start_time_ms() {
|
||||
return time(nullptr) * 1000;
|
||||
}
|
||||
|
||||
void StatsPullerManager::RegisterReceiver(int tagId, sp<PullDataReceiver> receiver, long intervalMs) {
|
||||
void StatsPullerManager::RegisterReceiver(int tagId, sp<PullDataReceiver> receiver,
|
||||
long intervalMs) {
|
||||
AutoMutex _l(mReceiversLock);
|
||||
vector<ReceiverInfo>& receivers = mReceivers[tagId];
|
||||
for (auto it = receivers.begin(); it != receivers.end(); it++) {
|
||||
@@ -143,8 +139,8 @@ void StatsPullerManager::OnAlarmFired() {
|
||||
vector<pair<int, vector<ReceiverInfo*>>>();
|
||||
for (auto& pair : mReceivers) {
|
||||
vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>();
|
||||
if (pair.second.size() != 0){
|
||||
for(auto& receiverInfo : pair.second) {
|
||||
if (pair.second.size() != 0) {
|
||||
for (auto& receiverInfo : pair.second) {
|
||||
if (receiverInfo.timeInfo.first + receiverInfo.timeInfo.second > currentTimeMs) {
|
||||
receivers.push_back(&receiverInfo);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ LogEvent::LogEvent(log_msg& msg) : mList(msg) {
|
||||
init(msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec, &mList);
|
||||
}
|
||||
|
||||
LogEvent::LogEvent(int tag) : mList(tag) {
|
||||
LogEvent::LogEvent(int tag, uint64_t timestampNs) : mList(tag), mTimestampNs(timestampNs) {
|
||||
}
|
||||
|
||||
LogEvent::~LogEvent() {
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
* any of the values. This constructor is useful for unit-testing since we can't pass in an
|
||||
* android_log_event_list since there is no copy constructor or assignment operator available.
|
||||
*/
|
||||
explicit LogEvent(int tag);
|
||||
explicit LogEvent(int tag, uint64_t timestampNs);
|
||||
|
||||
~LogEvent();
|
||||
|
||||
@@ -123,7 +123,9 @@ private:
|
||||
vector<android_log_list_element> mElements;
|
||||
// Need a copy of the android_log_event_list so the strings are not cleared.
|
||||
android_log_event_list mList;
|
||||
long mTimestampNs;
|
||||
|
||||
uint64_t mTimestampNs;
|
||||
|
||||
int mTagId;
|
||||
};
|
||||
|
||||
|
||||
@@ -58,10 +58,9 @@ const int FIELD_ID_COUNT = 3;
|
||||
|
||||
// TODO: add back AnomalyTracker.
|
||||
CountMetricProducer::CountMetricProducer(const CountMetric& metric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard)
|
||||
// TODO: Pass in the start time from MetricsManager, instead of calling time() here.
|
||||
: MetricProducer((time(nullptr) * NANO_SECONDS_IN_A_SECOND), conditionIndex, wizard),
|
||||
mMetric(metric) {
|
||||
const sp<ConditionWizard>& wizard,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(startTimeNs, conditionIndex, wizard), mMetric(metric) {
|
||||
// TODO: evaluate initial conditions. and set mConditionMet.
|
||||
if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
|
||||
mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
@@ -114,15 +113,17 @@ void CountMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
|
||||
}
|
||||
|
||||
StatsLogReport CountMetricProducer::onDumpReport() {
|
||||
long long endTime = time(nullptr) * NANO_SECONDS_IN_A_SECOND;
|
||||
long long endTime = time(nullptr) * NS_PER_SEC;
|
||||
|
||||
// Dump current bucket if it's stale.
|
||||
// If current bucket is still on-going, don't force dump current bucket.
|
||||
// In finish(), We can force dump current bucket.
|
||||
flushCounterIfNeeded(endTime);
|
||||
VLOG("metric %lld dump report now...", mMetric.metric_id());
|
||||
|
||||
for (const auto& counter : mPastBucketProtos) {
|
||||
for (const auto& counter : mPastBuckets) {
|
||||
const HashableDimensionKey& hashableKey = counter.first;
|
||||
VLOG(" dimension key %s", hashableKey.c_str());
|
||||
auto it = mDimensionKeyMap.find(hashableKey);
|
||||
if (it == mDimensionKeyMap.end()) {
|
||||
ALOGE("Dimension key %s not found?!?! skip...", hashableKey.c_str());
|
||||
@@ -147,20 +148,17 @@ StatsLogReport CountMetricProducer::onDumpReport() {
|
||||
}
|
||||
|
||||
// Then fill bucket_info (CountBucketInfo).
|
||||
for (const auto& proto : counter.second) {
|
||||
size_t bufferSize = proto->size();
|
||||
char* buffer(new char[bufferSize]);
|
||||
size_t pos = 0;
|
||||
auto it = proto->data();
|
||||
while (it.readBuffer() != NULL) {
|
||||
size_t toRead = it.currentToRead();
|
||||
std::memcpy(&buffer[pos], it.readBuffer(), toRead);
|
||||
pos += toRead;
|
||||
it.rp()->move(toRead);
|
||||
}
|
||||
mProto->write(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION, buffer, bufferSize);
|
||||
for (const auto& bucket : counter.second) {
|
||||
long long bucketInfoToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_BUCKET_INFO);
|
||||
mProto->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
|
||||
(long long)bucket.mBucketStartNs);
|
||||
mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
|
||||
(long long)bucket.mBucketEndNs);
|
||||
mProto->write(FIELD_TYPE_INT64 | FIELD_ID_COUNT, (long long)bucket.mCount);
|
||||
mProto->end(bucketInfoToken);
|
||||
VLOG("\t bucket [%lld - %lld] count: %lld", (long long)bucket.mBucketStartNs,
|
||||
(long long)bucket.mBucketEndNs, (long long)bucket.mCount);
|
||||
}
|
||||
|
||||
mProto->end(wrapperToken);
|
||||
}
|
||||
|
||||
@@ -169,8 +167,8 @@ StatsLogReport CountMetricProducer::onDumpReport() {
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
|
||||
size_t bufferSize = mProto->size();
|
||||
VLOG("metric %lld dump report now...", mMetric.metric_id());
|
||||
std::unique_ptr<uint8_t[]> buffer(new uint8_t[bufferSize]);
|
||||
|
||||
size_t pos = 0;
|
||||
auto it = mProto->data();
|
||||
while (it.readBuffer() != NULL) {
|
||||
@@ -181,7 +179,7 @@ StatsLogReport CountMetricProducer::onDumpReport() {
|
||||
}
|
||||
|
||||
startNewProtoOutputStream(endTime);
|
||||
mPastBucketProtos.clear();
|
||||
mPastBuckets.clear();
|
||||
mByteSize = 0;
|
||||
|
||||
// TODO: Once we migrate all MetricProducers to use ProtoOutputStream, we should return this:
|
||||
@@ -239,20 +237,16 @@ void CountMetricProducer::flushCounterIfNeeded(const uint64_t eventTimeNs) {
|
||||
// adjust the bucket start time
|
||||
int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
|
||||
|
||||
CountBucket info;
|
||||
info.mBucketStartNs = mCurrentBucketStartTimeNs;
|
||||
info.mBucketEndNs = mCurrentBucketStartTimeNs + mBucketSizeNs;
|
||||
for (const auto& counter : mCurrentSlicedCounter) {
|
||||
unique_ptr<ProtoOutputStream> proto = make_unique<ProtoOutputStream>();
|
||||
proto->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
proto->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
|
||||
(long long)mCurrentBucketStartTimeNs + mBucketSizeNs);
|
||||
proto->write(FIELD_TYPE_INT64 | FIELD_ID_COUNT, (long long)counter.second);
|
||||
|
||||
auto& bucketList = mPastBucketProtos[counter.first];
|
||||
mByteSize += proto->size();
|
||||
bucketList.push_back(std::move(proto));
|
||||
|
||||
info.mCount = counter.second;
|
||||
auto& bucketList = mPastBuckets[counter.first];
|
||||
bucketList.push_back(info);
|
||||
VLOG("metric %lld, dump key value: %s -> %d", mMetric.metric_id(), counter.first.c_str(),
|
||||
counter.second);
|
||||
mByteSize += sizeof(info);
|
||||
}
|
||||
|
||||
// TODO: Re-add anomaly detection (similar to):
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include <android/util/ProtoOutputStream.h>
|
||||
#include <gtest/gtest_prod.h>
|
||||
#include "../condition/ConditionTracker.h"
|
||||
#include "../matchers/matcher_util.h"
|
||||
#include "CountAnomalyTracker.h"
|
||||
@@ -34,11 +35,17 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
struct CountBucket {
|
||||
int64_t mBucketStartNs;
|
||||
int64_t mBucketEndNs;
|
||||
int64_t mCount;
|
||||
};
|
||||
|
||||
class CountMetricProducer : public MetricProducer {
|
||||
public:
|
||||
// TODO: Pass in the start time from MetricsManager, it should be consistent for all metrics.
|
||||
CountMetricProducer(const CountMetric& countMetric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard);
|
||||
const sp<ConditionWizard>& wizard, const uint64_t startTimeNs);
|
||||
|
||||
virtual ~CountMetricProducer();
|
||||
|
||||
@@ -66,8 +73,7 @@ protected:
|
||||
private:
|
||||
const CountMetric mMetric;
|
||||
|
||||
std::unordered_map<HashableDimensionKey,
|
||||
std::vector<unique_ptr<android::util::ProtoOutputStream>>> mPastBucketProtos;
|
||||
std::unordered_map<HashableDimensionKey, std::vector<CountBucket>> mPastBuckets;
|
||||
|
||||
size_t mByteSize;
|
||||
|
||||
@@ -83,6 +89,10 @@ private:
|
||||
long long mProtoToken;
|
||||
|
||||
void startNewProtoOutputStream(long long timestamp);
|
||||
|
||||
FRIEND_TEST(CountMetricProducerTest, TestNonDimensionalEvents);
|
||||
FRIEND_TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition);
|
||||
FRIEND_TEST(CountMetricProducerTest, TestEventsWithSlicedCondition);
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -35,9 +35,9 @@ DurationMetricProducer::DurationMetricProducer(const DurationMetric& metric,
|
||||
const int conditionIndex, const size_t startIndex,
|
||||
const size_t stopIndex, const size_t stopAllIndex,
|
||||
const sp<ConditionWizard>& wizard,
|
||||
const vector<KeyMatcher>& internalDimension)
|
||||
// TODO: Pass in the start time from MetricsManager, instead of calling time() here.
|
||||
: MetricProducer(time(nullptr) * NANO_SECONDS_IN_A_SECOND, conditionIndex, wizard),
|
||||
const vector<KeyMatcher>& internalDimension,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(startTimeNs, conditionIndex, wizard),
|
||||
mMetric(metric),
|
||||
mStartIndex(startIndex),
|
||||
mStopIndex(stopIndex),
|
||||
@@ -131,7 +131,7 @@ StatsLogReport DurationMetricProducer::onDumpReport() {
|
||||
// Dump current bucket if it's stale.
|
||||
// If current bucket is still on-going, don't force dump current bucket.
|
||||
// In finish(), We can force dump current bucket.
|
||||
flushIfNeeded(time(nullptr) * NANO_SECONDS_IN_A_SECOND);
|
||||
flushIfNeeded(time(nullptr) * NS_PER_SEC);
|
||||
report.set_end_report_nanos(mCurrentBucketStartTimeNs);
|
||||
|
||||
StatsLogReport_DurationMetricDataWrapper* wrapper = report.mutable_duration_metrics();
|
||||
@@ -195,10 +195,10 @@ void DurationMetricProducer::onMatchedLogEventInternal(
|
||||
}
|
||||
|
||||
size_t DurationMetricProducer::byteSize() {
|
||||
// TODO: return actual proto size when ProtoOutputStream is ready for use for
|
||||
// DurationMetricsProducer.
|
||||
// return mProto->size();
|
||||
return 0;
|
||||
// TODO: return actual proto size when ProtoOutputStream is ready for use for
|
||||
// DurationMetricsProducer.
|
||||
// return mProto->size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
DurationMetricProducer(const DurationMetric& durationMetric, const int conditionIndex,
|
||||
const size_t startIndex, const size_t stopIndex,
|
||||
const size_t stopAllIndex, const sp<ConditionWizard>& wizard,
|
||||
const vector<KeyMatcher>& internalDimension);
|
||||
const vector<KeyMatcher>& internalDimension, const uint64_t startTimeNs);
|
||||
|
||||
virtual ~DurationMetricProducer();
|
||||
|
||||
|
||||
@@ -46,10 +46,9 @@ const int FIELD_ID_TIMESTAMP_NANOS = 1;
|
||||
const int FIELD_ID_STATS_EVENTS = 2;
|
||||
|
||||
EventMetricProducer::EventMetricProducer(const EventMetric& metric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard)
|
||||
// TODO: Pass in the start time from MetricsManager, instead of calling time() here.
|
||||
: MetricProducer((time(nullptr) * NANO_SECONDS_IN_A_SECOND), conditionIndex, wizard),
|
||||
mMetric(metric) {
|
||||
const sp<ConditionWizard>& wizard,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(startTimeNs, conditionIndex, wizard), mMetric(metric) {
|
||||
if (metric.links().size() > 0) {
|
||||
mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
|
||||
metric.links().end());
|
||||
@@ -82,7 +81,7 @@ void EventMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
|
||||
}
|
||||
|
||||
StatsLogReport EventMetricProducer::onDumpReport() {
|
||||
long long endTime = time(nullptr) * NANO_SECONDS_IN_A_SECOND;
|
||||
long long endTime = time(nullptr) * NS_PER_SEC;
|
||||
mProto->end(mProtoToken);
|
||||
mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, endTime);
|
||||
|
||||
@@ -114,7 +113,6 @@ void EventMetricProducer::onMatchedLogEventInternal(
|
||||
const size_t matcherIndex, const HashableDimensionKey& eventKey,
|
||||
const std::map<std::string, HashableDimensionKey>& conditionKey, bool condition,
|
||||
const LogEvent& event, bool scheduledPull) {
|
||||
|
||||
if (!condition) {
|
||||
return;
|
||||
}
|
||||
@@ -128,7 +126,7 @@ void EventMetricProducer::onMatchedLogEventInternal(
|
||||
}
|
||||
|
||||
size_t EventMetricProducer::byteSize() {
|
||||
return mProto->size();
|
||||
return mProto->size();
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include <android/util/ProtoOutputStream.h>
|
||||
|
||||
#include "../condition/ConditionTracker.h"
|
||||
#include "../matchers/matcher_util.h"
|
||||
#include "MetricProducer.h"
|
||||
@@ -35,13 +36,14 @@ class EventMetricProducer : public MetricProducer {
|
||||
public:
|
||||
// TODO: Pass in the start time from MetricsManager, it should be consistent for all metrics.
|
||||
EventMetricProducer(const EventMetric& eventMetric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard);
|
||||
const sp<ConditionWizard>& wizard, const uint64_t startTimeNs);
|
||||
|
||||
virtual ~EventMetricProducer();
|
||||
|
||||
void onMatchedLogEventInternal(const size_t matcherIndex, const HashableDimensionKey& eventKey,
|
||||
const std::map<std::string, HashableDimensionKey>& conditionKey,
|
||||
bool condition, const LogEvent& event, bool scheduledPull) override;
|
||||
bool condition, const LogEvent& event,
|
||||
bool scheduledPull) override;
|
||||
|
||||
void onConditionChanged(const bool conditionMet, const uint64_t eventTime) override;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace statsd {
|
||||
|
||||
GaugeMetricProducer::GaugeMetricProducer(const GaugeMetric& metric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId)
|
||||
: MetricProducer((time(nullptr) * NANO_SECONDS_IN_A_SECOND), conditionIndex, wizard),
|
||||
: MetricProducer((time(nullptr) * NS_PER_SEC), conditionIndex, wizard),
|
||||
mMetric(metric),
|
||||
mPullTagId(pullTagId) {
|
||||
if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
|
||||
@@ -94,7 +94,7 @@ StatsLogReport GaugeMetricProducer::onDumpReport() {
|
||||
// Dump current bucket if it's stale.
|
||||
// If current bucket is still on-going, don't force dump current bucket.
|
||||
// In finish(), We can force dump current bucket.
|
||||
flushGaugeIfNeededLocked(time(nullptr) * NANO_SECONDS_IN_A_SECOND);
|
||||
flushGaugeIfNeededLocked(time(nullptr) * NS_PER_SEC);
|
||||
report.set_end_report_nanos(mCurrentBucketStartTimeNs);
|
||||
|
||||
StatsLogReport_GaugeMetricDataWrapper* wrapper = report.mutable_gauge_metrics();
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
: mStartTimeNs(startTimeNs),
|
||||
mCurrentBucketStartTimeNs(startTimeNs),
|
||||
mCondition(conditionIndex >= 0 ? false : true),
|
||||
mConditionSliced(false),
|
||||
mWizard(wizard),
|
||||
mConditionTrackerIndex(conditionIndex) {
|
||||
// reuse the same map for non-sliced metrics too. this way, we avoid too many if-else.
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
*/
|
||||
#define DEBUG true // STOPSHIP if true
|
||||
#include "Log.h"
|
||||
|
||||
#include "MetricsManager.h"
|
||||
#include <log/logprint.h>
|
||||
#include "../condition/CombinationConditionTracker.h"
|
||||
#include "../condition/SimpleConditionTracker.h"
|
||||
#include "../matchers/CombinationLogMatchingTracker.h"
|
||||
#include "../matchers/SimpleLogMatchingTracker.h"
|
||||
|
||||
#include "CountMetricProducer.h"
|
||||
#include "condition/CombinationConditionTracker.h"
|
||||
#include "condition/SimpleConditionTracker.h"
|
||||
#include "matchers/CombinationLogMatchingTracker.h"
|
||||
#include "matchers/SimpleLogMatchingTracker.h"
|
||||
#include "metrics_manager_util.h"
|
||||
#include "stats_util.h"
|
||||
|
||||
#include <log/logprint.h>
|
||||
using std::make_unique;
|
||||
using std::set;
|
||||
using std::string;
|
||||
|
||||
@@ -96,4 +96,3 @@ private:
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using std::map;
|
||||
using std::unordered_map;
|
||||
using std::list;
|
||||
using std::make_shared;
|
||||
using std::map;
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::unordered_map;
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
@@ -36,51 +36,50 @@ namespace statsd {
|
||||
|
||||
// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
|
||||
ValueMetricProducer::ValueMetricProducer(const ValueMetric& metric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId)
|
||||
: MetricProducer((time(nullptr) / 600 * 600 * NANO_SECONDS_IN_A_SECOND), conditionIndex,
|
||||
wizard),
|
||||
mMetric(metric),
|
||||
mPullTagId(pullTagId) {
|
||||
// TODO: valuemetric for pushed events may need unlimited bucket length
|
||||
mBucketSizeNs = mMetric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(startTimeNs, conditionIndex, wizard), mMetric(metric), mPullTagId(pullTagId) {
|
||||
// TODO: valuemetric for pushed events may need unlimited bucket length
|
||||
mBucketSizeNs = mMetric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
|
||||
mDimension.insert(mDimension.begin(), metric.dimension().begin(), metric.dimension().end());
|
||||
mDimension.insert(mDimension.begin(), metric.dimension().begin(), metric.dimension().end());
|
||||
|
||||
if (metric.links().size() > 0) {
|
||||
mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
|
||||
metric.links().end());
|
||||
mConditionSliced = true;
|
||||
}
|
||||
if (metric.links().size() > 0) {
|
||||
mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
|
||||
metric.links().end());
|
||||
mConditionSliced = true;
|
||||
}
|
||||
|
||||
if (!metric.has_condition() && mPullTagId != -1) {
|
||||
mStatsPullerManager.RegisterReceiver(mPullTagId, this, metric.bucket().bucket_size_millis());
|
||||
}
|
||||
if (!metric.has_condition() && mPullTagId != -1) {
|
||||
mStatsPullerManager.RegisterReceiver(mPullTagId, this,
|
||||
metric.bucket().bucket_size_millis());
|
||||
}
|
||||
|
||||
VLOG("value metric %lld created. bucket size %lld start_time: %lld", metric.metric_id(),
|
||||
(long long)mBucketSizeNs, (long long)mStartTimeNs);
|
||||
VLOG("value metric %lld created. bucket size %lld start_time: %lld", metric.metric_id(),
|
||||
(long long)mBucketSizeNs, (long long)mStartTimeNs);
|
||||
}
|
||||
|
||||
ValueMetricProducer::~ValueMetricProducer() {
|
||||
VLOG("~ValueMetricProducer() called");
|
||||
VLOG("~ValueMetricProducer() called");
|
||||
}
|
||||
|
||||
void ValueMetricProducer::finish() {
|
||||
// TODO: write the StatsLogReport to dropbox using
|
||||
// DropboxWriter.
|
||||
// TODO: write the StatsLogReport to dropbox using
|
||||
// DropboxWriter.
|
||||
}
|
||||
|
||||
static void addSlicedCounterToReport(StatsLogReport_ValueMetricDataWrapper& wrapper,
|
||||
const vector<KeyValuePair>& key,
|
||||
const vector<ValueBucketInfo>& buckets) {
|
||||
ValueMetricData* data = wrapper.add_data();
|
||||
for (const auto& kv : key) {
|
||||
data->add_dimension()->CopyFrom(kv);
|
||||
}
|
||||
for (const auto& bucket : buckets) {
|
||||
data->add_bucket_info()->CopyFrom(bucket);
|
||||
VLOG("\t bucket [%lld - %lld] value: %lld", bucket.start_bucket_nanos(),
|
||||
bucket.end_bucket_nanos(), bucket.value());
|
||||
}
|
||||
ValueMetricData* data = wrapper.add_data();
|
||||
for (const auto& kv : key) {
|
||||
data->add_dimension()->CopyFrom(kv);
|
||||
}
|
||||
for (const auto& bucket : buckets) {
|
||||
data->add_bucket_info()->CopyFrom(bucket);
|
||||
VLOG("\t bucket [%lld - %lld] value: %lld", bucket.start_bucket_nanos(),
|
||||
bucket.end_bucket_nanos(), bucket.value());
|
||||
}
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
|
||||
@@ -88,33 +87,28 @@ void ValueMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
|
||||
}
|
||||
|
||||
StatsLogReport ValueMetricProducer::onDumpReport() {
|
||||
VLOG("metric %lld dump report now...", mMetric.metric_id());
|
||||
VLOG("metric %lld dump report now...", mMetric.metric_id());
|
||||
|
||||
StatsLogReport report;
|
||||
report.set_metric_id(mMetric.metric_id());
|
||||
report.set_start_report_nanos(mStartTimeNs);
|
||||
StatsLogReport report;
|
||||
report.set_metric_id(mMetric.metric_id());
|
||||
report.set_start_report_nanos(mStartTimeNs);
|
||||
report.set_end_report_nanos(mCurrentBucketStartTimeNs);
|
||||
|
||||
// Dump current bucket if it's stale.
|
||||
// If current bucket is still on-going, don't force dump current bucket.
|
||||
// In finish(), We can force dump current bucket.
|
||||
// flush_if_needed(time(nullptr) * NANO_SECONDS_IN_A_SECOND);
|
||||
report.set_end_report_nanos(mCurrentBucketStartTimeNs);
|
||||
StatsLogReport_ValueMetricDataWrapper* wrapper = report.mutable_value_metrics();
|
||||
|
||||
StatsLogReport_ValueMetricDataWrapper* wrapper = report.mutable_value_metrics();
|
||||
for (const auto& pair : mPastBuckets) {
|
||||
const HashableDimensionKey& hashableKey = pair.first;
|
||||
auto it = mDimensionKeyMap.find(hashableKey);
|
||||
if (it == mDimensionKeyMap.end()) {
|
||||
ALOGE("Dimension key %s not found?!?! skip...", hashableKey.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& pair : mPastBuckets) {
|
||||
const HashableDimensionKey& hashableKey = pair.first;
|
||||
auto it = mDimensionKeyMap.find(hashableKey);
|
||||
if (it == mDimensionKeyMap.end()) {
|
||||
ALOGE("Dimension key %s not found?!?! skip...", hashableKey.c_str());
|
||||
continue;
|
||||
VLOG(" dimension key %s", hashableKey.c_str());
|
||||
addSlicedCounterToReport(*wrapper, it->second, pair.second);
|
||||
}
|
||||
|
||||
VLOG(" dimension key %s", hashableKey.c_str());
|
||||
addSlicedCounterToReport(*wrapper, it->second, pair.second);
|
||||
}
|
||||
return report;
|
||||
// TODO: Clear mPastBuckets, mDimensionKeyMap once the report is dumped.
|
||||
return report;
|
||||
// TODO: Clear mPastBuckets, mDimensionKeyMap once the report is dumped.
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onConditionChanged(const bool condition, const uint64_t eventTime) {
|
||||
@@ -158,50 +152,50 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onMatchedLogEventInternal(
|
||||
const size_t matcherIndex, const HashableDimensionKey& eventKey,
|
||||
const map<string, HashableDimensionKey>& conditionKey, bool condition,
|
||||
const LogEvent& event, bool scheduledPull) {
|
||||
uint64_t eventTimeNs = event.GetTimestampNs();
|
||||
if (eventTimeNs < mCurrentBucketStartTimeNs) {
|
||||
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
return;
|
||||
}
|
||||
|
||||
Interval& interval = mCurrentSlicedBucket[eventKey];
|
||||
|
||||
long value = get_value(event);
|
||||
|
||||
if (scheduledPull) {
|
||||
if (interval.raw.size() > 0) {
|
||||
interval.raw.back().second = value;
|
||||
} else {
|
||||
interval.raw.push_back(std::make_pair(value, value));
|
||||
const size_t matcherIndex, const HashableDimensionKey& eventKey,
|
||||
const map<string, HashableDimensionKey>& conditionKey, bool condition,
|
||||
const LogEvent& event, bool scheduledPull) {
|
||||
uint64_t eventTimeNs = event.GetTimestampNs();
|
||||
if (eventTimeNs < mCurrentBucketStartTimeNs) {
|
||||
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
return;
|
||||
}
|
||||
mNextSlicedBucket[eventKey].raw[0].first = value;
|
||||
} else {
|
||||
if (mCondition == ConditionState::kTrue) {
|
||||
interval.raw.push_back(std::make_pair(value, 0));
|
||||
|
||||
Interval& interval = mCurrentSlicedBucket[eventKey];
|
||||
|
||||
long value = get_value(event);
|
||||
|
||||
if (scheduledPull) {
|
||||
if (interval.raw.size() > 0) {
|
||||
interval.raw.back().second = value;
|
||||
} else {
|
||||
interval.raw.push_back(std::make_pair(value, value));
|
||||
}
|
||||
mNextSlicedBucket[eventKey].raw[0].first = value;
|
||||
} else {
|
||||
if (interval.raw.size() != 0) {
|
||||
interval.raw.back().second = value;
|
||||
}
|
||||
if (mCondition == ConditionState::kTrue) {
|
||||
interval.raw.push_back(std::make_pair(value, 0));
|
||||
} else {
|
||||
if (interval.raw.size() != 0) {
|
||||
interval.raw.back().second = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mPullTagId == -1) {
|
||||
flush_if_needed(eventTimeNs);
|
||||
}
|
||||
}
|
||||
if (mPullTagId == -1) {
|
||||
flush_if_needed(eventTimeNs);
|
||||
}
|
||||
}
|
||||
|
||||
long ValueMetricProducer::get_value(const LogEvent& event) {
|
||||
status_t err = NO_ERROR;
|
||||
long val = event.GetLong(mMetric.value_field(), &err);
|
||||
if (err == NO_ERROR) {
|
||||
return val;
|
||||
} else {
|
||||
VLOG("Can't find value in message.");
|
||||
return 0;
|
||||
}
|
||||
status_t err = NO_ERROR;
|
||||
long val = event.GetLong(mMetric.value_field(), &err);
|
||||
if (err == NO_ERROR) {
|
||||
return val;
|
||||
} else {
|
||||
VLOG("Can't find value in message.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ValueMetricProducer::flush_if_needed(const uint64_t eventTimeNs) {
|
||||
@@ -218,22 +212,22 @@ void ValueMetricProducer::flush_if_needed(const uint64_t eventTimeNs) {
|
||||
info.set_end_bucket_nanos(mCurrentBucketStartTimeNs + mBucketSizeNs);
|
||||
|
||||
for (const auto& slice : mCurrentSlicedBucket) {
|
||||
long value = 0;
|
||||
for (const auto& pair : slice.second.raw) {
|
||||
value += pair.second - pair.first;
|
||||
}
|
||||
info.set_value(value);
|
||||
VLOG(" %s, %ld", slice.first.c_str(), value);
|
||||
// it will auto create new vector of ValuebucketInfo if the key is not found.
|
||||
auto& bucketList = mPastBuckets[slice.first];
|
||||
bucketList.push_back(info);
|
||||
long value = 0;
|
||||
for (const auto& pair : slice.second.raw) {
|
||||
value += pair.second - pair.first;
|
||||
}
|
||||
info.set_value(value);
|
||||
VLOG(" %s, %ld", slice.first.c_str(), value);
|
||||
// it will auto create new vector of ValuebucketInfo if the key is not found.
|
||||
auto& bucketList = mPastBuckets[slice.first];
|
||||
bucketList.push_back(info);
|
||||
}
|
||||
|
||||
// Reset counters
|
||||
mCurrentSlicedBucket.swap(mNextSlicedBucket);
|
||||
mNextSlicedBucket.clear();
|
||||
int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
|
||||
if (numBucketsForward >1) {
|
||||
if (numBucketsForward > 1) {
|
||||
VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
|
||||
}
|
||||
mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
|
||||
@@ -243,4 +237,4 @@ void ValueMetricProducer::flush_if_needed(const uint64_t eventTimeNs) {
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
} // namespace android
|
||||
|
||||
@@ -33,7 +33,8 @@ namespace statsd {
|
||||
class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
|
||||
public:
|
||||
ValueMetricProducer(const ValueMetric& valueMetric, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId);
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const uint64_t startTimeNs);
|
||||
|
||||
virtual ~ValueMetricProducer();
|
||||
|
||||
@@ -47,7 +48,9 @@ public:
|
||||
|
||||
void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data) override;
|
||||
// TODO: Implement this later.
|
||||
size_t byteSize() override{return 0;};
|
||||
size_t byteSize() override {
|
||||
return 0;
|
||||
};
|
||||
|
||||
// TODO: Implement this later.
|
||||
virtual void notifyAppUpgrade(const string& apk, const int uid, const int version) override{};
|
||||
|
||||
@@ -192,10 +192,11 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
|
||||
unordered_map<int, std::vector<int>>& conditionToMetricMap,
|
||||
unordered_map<int, std::vector<int>>& trackerToMetricMap) {
|
||||
sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
|
||||
const int allMetricsCount =
|
||||
config.count_metric_size() + config.duration_metric_size() + config.event_metric_size() + config.value_metric_size();
|
||||
const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
|
||||
config.event_metric_size() + config.value_metric_size();
|
||||
allMetricProducers.reserve(allMetricsCount);
|
||||
StatsPullerManager& statsPullerManager = StatsPullerManager::GetInstance();
|
||||
uint64_t startTimeNs = time(nullptr) * NS_PER_SEC;
|
||||
|
||||
// Build MetricProducers for each metric defined in config.
|
||||
// build CountMetricProducer
|
||||
@@ -221,7 +222,8 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
|
||||
conditionToMetricMap);
|
||||
}
|
||||
|
||||
sp<MetricProducer> countProducer = new CountMetricProducer(metric, conditionIndex, wizard);
|
||||
sp<MetricProducer> countProducer =
|
||||
new CountMetricProducer(metric, conditionIndex, wizard, startTimeNs);
|
||||
allMetricProducers.push_back(countProducer);
|
||||
}
|
||||
|
||||
@@ -282,7 +284,7 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
|
||||
|
||||
sp<MetricProducer> durationMetric = new DurationMetricProducer(
|
||||
metric, conditionIndex, trackerIndices[0], trackerIndices[1], trackerIndices[2],
|
||||
wizard, internalDimension);
|
||||
wizard, internalDimension, startTimeNs);
|
||||
|
||||
allMetricProducers.push_back(durationMetric);
|
||||
}
|
||||
@@ -308,7 +310,9 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
|
||||
conditionToMetricMap);
|
||||
}
|
||||
|
||||
sp<MetricProducer> eventMetric = new EventMetricProducer(metric, conditionIndex, wizard);
|
||||
sp<MetricProducer> eventMetric =
|
||||
new EventMetricProducer(metric, conditionIndex, wizard, startTimeNs);
|
||||
|
||||
allMetricProducers.push_back(eventMetric);
|
||||
}
|
||||
|
||||
@@ -348,7 +352,7 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
|
||||
}
|
||||
|
||||
sp<MetricProducer> valueProducer =
|
||||
new ValueMetricProducer(metric, conditionIndex, wizard, pullTagId);
|
||||
new ValueMetricProducer(metric, conditionIndex, wizard, pullTagId, startTimeNs);
|
||||
allMetricProducers.push_back(valueProducer);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace statsd {
|
||||
|
||||
#define DEFAULT_DIMENSION_KEY ""
|
||||
#define MATCHER_NOT_FOUND -2
|
||||
#define NANO_SECONDS_IN_A_SECOND (1000 * 1000 * 1000)
|
||||
|
||||
typedef std::string HashableDimensionKey;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ TEST(LogEntryMatcherTest, TestSimpleMatcher) {
|
||||
auto simpleMatcher = matcher.mutable_simple_log_entry_matcher();
|
||||
simpleMatcher->set_tag(TAG_ID);
|
||||
|
||||
LogEvent event(TAG_ID);
|
||||
LogEvent event(TAG_ID, 0);
|
||||
|
||||
// Convert to a LogEvent
|
||||
event.init();
|
||||
@@ -62,7 +62,7 @@ TEST(LogEntryMatcherTest, TestBoolMatcher) {
|
||||
keyValue2->mutable_key_matcher()->set_key(FIELD_ID_2);
|
||||
|
||||
// Set up the event
|
||||
LogEvent event(TAG_ID);
|
||||
LogEvent event(TAG_ID, 0);
|
||||
auto list = event.GetAndroidLogEventList();
|
||||
*list << true;
|
||||
*list << false;
|
||||
@@ -98,7 +98,7 @@ TEST(LogEntryMatcherTest, TestStringMatcher) {
|
||||
keyValue->set_eq_string("some value");
|
||||
|
||||
// Set up the event
|
||||
LogEvent event(TAG_ID);
|
||||
LogEvent event(TAG_ID, 0);
|
||||
auto list = event.GetAndroidLogEventList();
|
||||
*list << "some value";
|
||||
|
||||
@@ -119,7 +119,7 @@ TEST(LogEntryMatcherTest, TestIntComparisonMatcher) {
|
||||
keyValue->mutable_key_matcher()->set_key(FIELD_ID_1);
|
||||
|
||||
// Set up the event
|
||||
LogEvent event(TAG_ID);
|
||||
LogEvent event(TAG_ID, 0);
|
||||
auto list = event.GetAndroidLogEventList();
|
||||
*list << 11;
|
||||
|
||||
|
||||
183
cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
Normal file
183
cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "metrics_test_helper.h"
|
||||
#include "src/metrics/CountMetricProducer.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace testing;
|
||||
using android::sp;
|
||||
using std::set;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
|
||||
int64_t bucketStartTimeNs = 10000000000;
|
||||
int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
|
||||
int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
|
||||
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
|
||||
int tagId = 1;
|
||||
|
||||
CountMetric metric;
|
||||
metric.set_metric_id(1);
|
||||
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
|
||||
|
||||
LogEvent event1(tagId, bucketStartTimeNs + 1);
|
||||
LogEvent event2(tagId, bucketStartTimeNs + 2);
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
|
||||
CountMetricProducer countProducer(metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
bucketStartTimeNs);
|
||||
|
||||
// 2 events in bucket 1.
|
||||
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1, false);
|
||||
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2, false);
|
||||
countProducer.flushCounterIfNeeded(bucketStartTimeNs + bucketSizeNs + 1);
|
||||
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
|
||||
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) !=
|
||||
countProducer.mPastBuckets.end());
|
||||
const auto& buckets = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY];
|
||||
EXPECT_EQ(1UL, buckets.size());
|
||||
const auto& bucketInfo = buckets[0];
|
||||
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
|
||||
EXPECT_EQ(2LL, bucketInfo.mCount);
|
||||
|
||||
// 1 matched event happens in bucket 2.
|
||||
LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
|
||||
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3, false);
|
||||
countProducer.flushCounterIfNeeded(bucketStartTimeNs + 2 * bucketSizeNs + 1);
|
||||
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
|
||||
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) !=
|
||||
countProducer.mPastBuckets.end());
|
||||
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY].size());
|
||||
const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY][1];
|
||||
EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
|
||||
EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
|
||||
EXPECT_EQ(1LL, bucketInfo2.mCount);
|
||||
|
||||
// nothing happens in bucket 3. we should not record anything for bucket 3.
|
||||
countProducer.flushCounterIfNeeded(bucketStartTimeNs + 3 * bucketSizeNs + 1);
|
||||
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
|
||||
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) !=
|
||||
countProducer.mPastBuckets.end());
|
||||
const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY];
|
||||
EXPECT_EQ(2UL, buckets3.size());
|
||||
}
|
||||
|
||||
TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
|
||||
int64_t bucketStartTimeNs = 10000000000;
|
||||
int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
|
||||
|
||||
CountMetric metric;
|
||||
metric.set_metric_id(1);
|
||||
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
|
||||
metric.set_condition("SCREEN_ON");
|
||||
|
||||
LogEvent event1(1, bucketStartTimeNs + 1);
|
||||
LogEvent event2(1, bucketStartTimeNs + 10);
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
|
||||
CountMetricProducer countProducer(metric, 1, wizard, bucketStartTimeNs);
|
||||
|
||||
countProducer.onConditionChanged(true, bucketStartTimeNs);
|
||||
countProducer.onMatchedLogEvent(1 /*matcher index*/, event1, false /*pulled*/);
|
||||
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
|
||||
|
||||
countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
|
||||
countProducer.onMatchedLogEvent(1 /*matcher index*/, event2, false /*pulled*/);
|
||||
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
|
||||
|
||||
countProducer.flushCounterIfNeeded(bucketStartTimeNs + bucketSizeNs + 1);
|
||||
|
||||
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
|
||||
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) !=
|
||||
countProducer.mPastBuckets.end());
|
||||
const auto& buckets = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY];
|
||||
EXPECT_EQ(1UL, buckets.size());
|
||||
const auto& bucketInfo = buckets[0];
|
||||
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
|
||||
EXPECT_EQ(1LL, bucketInfo.mCount);
|
||||
}
|
||||
|
||||
TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
|
||||
int64_t bucketStartTimeNs = 10000000000;
|
||||
int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
|
||||
|
||||
CountMetric metric;
|
||||
metric.set_metric_id(1);
|
||||
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
|
||||
metric.set_condition("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON");
|
||||
EventConditionLink* link = metric.add_links();
|
||||
link->set_condition("APP_IN_BACKGROUND_PER_UID");
|
||||
link->add_key_in_main()->set_key(1);
|
||||
link->add_key_in_condition()->set_key(2);
|
||||
|
||||
LogEvent event1(1, bucketStartTimeNs + 1);
|
||||
auto list = event1.GetAndroidLogEventList();
|
||||
*list << "111"; // uid
|
||||
event1.init();
|
||||
ConditionKey key1;
|
||||
key1["APP_IN_BACKGROUND_PER_UID"] = "2:111|";
|
||||
|
||||
LogEvent event2(1, bucketStartTimeNs + 10);
|
||||
auto list2 = event2.GetAndroidLogEventList();
|
||||
*list2 << "222"; // uid
|
||||
event2.init();
|
||||
ConditionKey key2;
|
||||
key2["APP_IN_BACKGROUND_PER_UID"] = "2:222|";
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
EXPECT_CALL(*wizard, query(_, key1)).WillOnce(Return(ConditionState::kFalse));
|
||||
|
||||
EXPECT_CALL(*wizard, query(_, key2)).WillOnce(Return(ConditionState::kTrue));
|
||||
|
||||
CountMetricProducer countProducer(metric, 1 /*condition tracker index*/, wizard,
|
||||
bucketStartTimeNs);
|
||||
|
||||
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1, false);
|
||||
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2, false);
|
||||
|
||||
countProducer.flushCounterIfNeeded(bucketStartTimeNs + bucketSizeNs + 1);
|
||||
|
||||
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
|
||||
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_DIMENSION_KEY) !=
|
||||
countProducer.mPastBuckets.end());
|
||||
const auto& buckets = countProducer.mPastBuckets[DEFAULT_DIMENSION_KEY];
|
||||
EXPECT_EQ(1UL, buckets.size());
|
||||
const auto& bucketInfo = buckets[0];
|
||||
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
|
||||
EXPECT_EQ(1LL, bucketInfo.mCount);
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
130
cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
Normal file
130
cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "metrics_test_helper.h"
|
||||
#include "src/metrics/EventMetricProducer.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace testing;
|
||||
using android::sp;
|
||||
using std::set;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
TEST(EventMetricProducerTest, TestNoCondition) {
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
|
||||
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
|
||||
|
||||
EventMetric metric;
|
||||
metric.set_metric_id(1);
|
||||
|
||||
LogEvent event1(1 /*tag id*/, bucketStartTimeNs + 1);
|
||||
LogEvent event2(1 /*tag id*/, bucketStartTimeNs + 2);
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
|
||||
EventMetricProducer eventProducer(metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
bucketStartTimeNs);
|
||||
|
||||
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1, false /*pulled*/);
|
||||
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2, false /*pulled*/);
|
||||
|
||||
// TODO: get the report and check the content after the ProtoOutputStream change is done.
|
||||
// eventProducer.onDumpReport();
|
||||
}
|
||||
|
||||
TEST(EventMetricProducerTest, TestEventsWithNonSlicedCondition) {
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
|
||||
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
|
||||
|
||||
EventMetric metric;
|
||||
metric.set_metric_id(1);
|
||||
metric.set_condition("SCREEN_ON");
|
||||
|
||||
LogEvent event1(1, bucketStartTimeNs + 1);
|
||||
LogEvent event2(1, bucketStartTimeNs + 10);
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
|
||||
EventMetricProducer eventProducer(metric, 1, wizard, bucketStartTimeNs);
|
||||
|
||||
eventProducer.onConditionChanged(true /*condition*/, bucketStartTimeNs);
|
||||
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1, false /*pulled*/);
|
||||
|
||||
eventProducer.onConditionChanged(false /*condition*/, bucketStartTimeNs + 2);
|
||||
|
||||
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2, false /*pulled*/);
|
||||
|
||||
// TODO: get the report and check the content after the ProtoOutputStream change is done.
|
||||
// eventProducer.onDumpReport();
|
||||
}
|
||||
|
||||
TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
|
||||
|
||||
EventMetric metric;
|
||||
metric.set_metric_id(1);
|
||||
metric.set_condition("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON");
|
||||
EventConditionLink* link = metric.add_links();
|
||||
link->set_condition("APP_IN_BACKGROUND_PER_UID");
|
||||
link->add_key_in_main()->set_key(1);
|
||||
link->add_key_in_condition()->set_key(2);
|
||||
|
||||
LogEvent event1(1, bucketStartTimeNs + 1);
|
||||
auto list = event1.GetAndroidLogEventList();
|
||||
*list << "111"; // uid
|
||||
event1.init();
|
||||
ConditionKey key1;
|
||||
key1["APP_IN_BACKGROUND_PER_UID"] = "2:111|";
|
||||
|
||||
LogEvent event2(1, bucketStartTimeNs + 10);
|
||||
auto list2 = event2.GetAndroidLogEventList();
|
||||
*list2 << "222"; // uid
|
||||
event2.init();
|
||||
ConditionKey key2;
|
||||
key2["APP_IN_BACKGROUND_PER_UID"] = "2:222|";
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
EXPECT_CALL(*wizard, query(_, key1)).WillOnce(Return(ConditionState::kFalse));
|
||||
|
||||
EXPECT_CALL(*wizard, query(_, key2)).WillOnce(Return(ConditionState::kTrue));
|
||||
|
||||
EventMetricProducer eventProducer(metric, 1, wizard, bucketStartTimeNs);
|
||||
|
||||
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1, false /*pulled*/);
|
||||
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2, false /*pulled*/);
|
||||
|
||||
// TODO: get the report and check the content after the ProtoOutputStream change is done.
|
||||
// eventProducer.onDumpReport();
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
@@ -12,12 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "metrics_test_helper.h"
|
||||
#include "src/condition/ConditionWizard.h"
|
||||
#include "src/metrics/duration_helper/MaxDurationTracker.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
@@ -32,13 +32,9 @@ using std::vector;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
class MockConditionWizard : public ConditionWizard {
|
||||
public:
|
||||
MOCK_METHOD2(
|
||||
query,
|
||||
ConditionState(const int conditionIndex,
|
||||
const std::map<std::string, HashableDimensionKey>& conditionParameters));
|
||||
};
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) {
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
@@ -110,6 +106,9 @@ TEST(MaxDurationTrackerTest, TestMaxDurationWithCondition) {
|
||||
EXPECT_EQ(5, buckets[0].duration_nanos());
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
@@ -12,18 +12,17 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "metrics_test_helper.h"
|
||||
#include "src/condition/ConditionWizard.h"
|
||||
#include "src/metrics/duration_helper/OringDurationTracker.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
using namespace android::os::statsd;
|
||||
using namespace testing;
|
||||
using android::sp;
|
||||
using std::set;
|
||||
@@ -31,14 +30,9 @@ using std::unordered_map;
|
||||
using std::vector;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
class MockConditionWizard : public ConditionWizard {
|
||||
public:
|
||||
MOCK_METHOD2(
|
||||
query,
|
||||
ConditionState(const int conditionIndex,
|
||||
const std::map<std::string, HashableDimensionKey>& conditionParameters));
|
||||
};
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
TEST(OringDurationTrackerTest, TestDurationOverlap) {
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
@@ -93,7 +87,9 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange) {
|
||||
EXPECT_EQ(1u, buckets.size());
|
||||
EXPECT_EQ(5, buckets[0].duration_nanos());
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
35
cmds/statsd/tests/metrics/metrics_test_helper.h
Normal file
35
cmds/statsd/tests/metrics/metrics_test_helper.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include "src/condition/ConditionWizard.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
class MockConditionWizard : public ConditionWizard {
|
||||
public:
|
||||
MOCK_METHOD2(
|
||||
query,
|
||||
ConditionState(const int conditionIndex,
|
||||
const std::map<std::string, HashableDimensionKey>& conditionParameters));
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
Reference in New Issue
Block a user