Flush the bucket when creating the metric producer.
Use int64 for value field. E2e test for gauge/value metric. BUG: b/74445671 Test: statsd test. Change-Id: I823a0bade8f89834bdfb9cf48864852a47d7b63b
This commit is contained in:
@@ -205,6 +205,8 @@ LOCAL_SRC_FILES := \
|
||||
tests/e2e/Alarm_e2e_test.cpp \
|
||||
tests/e2e/Attribution_e2e_test.cpp \
|
||||
tests/e2e/GaugeMetric_e2e_push_test.cpp \
|
||||
tests/e2e/GaugeMetric_e2e_pull_test.cpp \
|
||||
tests/e2e/ValueMetric_pull_e2e_test.cpp \
|
||||
tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \
|
||||
tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \
|
||||
tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp \
|
||||
|
||||
@@ -365,7 +365,8 @@ sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const Stat
|
||||
sp<AlarmMonitor> anomalyAlarmMonitor;
|
||||
sp<AlarmMonitor> periodicAlarmMonitor;
|
||||
sp<StatsLogProcessor> processor = new StatsLogProcessor(
|
||||
uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, [](const ConfigKey&){});
|
||||
uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec * NS_PER_SEC,
|
||||
[](const ConfigKey&){});
|
||||
processor->OnConfigUpdated(timeBaseSec * NS_PER_SEC, key, config);
|
||||
return processor;
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6;
|
||||
StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
|
||||
const sp<AlarmMonitor>& anomalyAlarmMonitor,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor,
|
||||
const long timeBaseSec,
|
||||
const int64_t timeBaseNs,
|
||||
const std::function<void(const ConfigKey&)>& sendBroadcast)
|
||||
: mUidMap(uidMap),
|
||||
mAnomalyAlarmMonitor(anomalyAlarmMonitor),
|
||||
mPeriodicAlarmMonitor(periodicAlarmMonitor),
|
||||
mSendBroadcast(sendBroadcast),
|
||||
mTimeBaseSec(timeBaseSec),
|
||||
mTimeBaseNs(timeBaseNs),
|
||||
mLastLogTimestamp(0) {
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ void StatsLogProcessor::OnConfigUpdatedLocked(
|
||||
const int64_t timestampNs, const ConfigKey& key, const StatsdConfig& config) {
|
||||
VLOG("Updated configuration for key %s", key.ToString().c_str());
|
||||
sp<MetricsManager> newMetricsManager =
|
||||
new MetricsManager(key, config, mTimeBaseSec, (timestampNs - 1) / NS_PER_SEC + 1, mUidMap,
|
||||
new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap,
|
||||
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
|
||||
auto it = mMetricsManagers.find(key);
|
||||
if (it != mMetricsManagers.end()) {
|
||||
@@ -438,6 +438,10 @@ void StatsLogProcessor::WriteDataToDisk() {
|
||||
WriteDataToDiskLocked();
|
||||
}
|
||||
|
||||
void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) {
|
||||
mStatsPullerManager.OnAlarmFired(timestampNs);
|
||||
}
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
|
||||
@@ -36,7 +36,7 @@ class StatsLogProcessor : public ConfigListener {
|
||||
public:
|
||||
StatsLogProcessor(const sp<UidMap>& uidMap, const sp<AlarmMonitor>& anomalyAlarmMonitor,
|
||||
const sp<AlarmMonitor>& subscriberTriggerAlarmMonitor,
|
||||
const long timeBaseSec,
|
||||
const int64_t timeBaseNs,
|
||||
const std::function<void(const ConfigKey&)>& sendBroadcast);
|
||||
virtual ~StatsLogProcessor();
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
|
||||
void dumpStates(FILE* out, bool verbose);
|
||||
|
||||
void informPullAlarmFired(const int64_t timestampNs);
|
||||
|
||||
private:
|
||||
// For testing only.
|
||||
@@ -125,7 +126,7 @@ private:
|
||||
// to retrieve the stored data.
|
||||
std::function<void(const ConfigKey& key)> mSendBroadcast;
|
||||
|
||||
const long mTimeBaseSec;
|
||||
const int64_t mTimeBaseNs;
|
||||
|
||||
int64_t mLastLogTimestamp;
|
||||
|
||||
@@ -145,6 +146,12 @@ private:
|
||||
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
|
||||
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
|
||||
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
|
||||
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
|
||||
|
||||
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
|
||||
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
|
||||
FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
|
||||
|
||||
@@ -81,7 +81,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
|
||||
StatsPuller::SetUidMap(mUidMap);
|
||||
mConfigManager = new ConfigManager();
|
||||
mProcessor = new StatsLogProcessor(mUidMap, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
|
||||
getElapsedRealtimeSec(), [this](const ConfigKey& key) {
|
||||
getElapsedRealtimeNs(), [this](const ConfigKey& key) {
|
||||
sp<IStatsCompanionService> sc = getStatsCompanionService();
|
||||
auto receiver = mConfigManager->GetConfigReceiver(key);
|
||||
if (sc == nullptr) {
|
||||
@@ -745,7 +745,7 @@ Status StatsService::informPollAlarmFired() {
|
||||
"Only system uid can call informPollAlarmFired");
|
||||
}
|
||||
|
||||
mStatsPullerManager.OnAlarmFired();
|
||||
mProcessor->informPullAlarmFired(getElapsedRealtimeNs());
|
||||
|
||||
VLOG("StatsService::informPollAlarmFired succeeded");
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ class StatsPullerManager {
|
||||
return mPullerManager.PullerForMatcherExists(tagId);
|
||||
}
|
||||
|
||||
void OnAlarmFired() {
|
||||
mPullerManager.OnAlarmFired();
|
||||
void OnAlarmFired(const int64_t currentTimeNs) {
|
||||
mPullerManager.OnAlarmFired(currentTimeNs);
|
||||
}
|
||||
|
||||
virtual bool Pull(const int tagId, const int64_t timesNs,
|
||||
|
||||
@@ -275,11 +275,9 @@ void StatsPullerManagerImpl::UnRegisterReceiver(int tagId, wp<PullDataReceiver>
|
||||
}
|
||||
}
|
||||
|
||||
void StatsPullerManagerImpl::OnAlarmFired() {
|
||||
void StatsPullerManagerImpl::OnAlarmFired(const int64_t currentTimeNs) {
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
int64_t currentTimeNs = getElapsedRealtimeNs();
|
||||
|
||||
int64_t minNextPullTimeNs = LONG_MAX;
|
||||
|
||||
vector<pair<int, vector<ReceiverInfo*>>> needToPull =
|
||||
@@ -288,7 +286,7 @@ void StatsPullerManagerImpl::OnAlarmFired() {
|
||||
vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>();
|
||||
if (pair.second.size() != 0) {
|
||||
for (ReceiverInfo& receiverInfo : pair.second) {
|
||||
if (receiverInfo.nextPullTimeNs < currentTimeNs) {
|
||||
if (receiverInfo.nextPullTimeNs <= currentTimeNs) {
|
||||
receivers.push_back(&receiverInfo);
|
||||
} else {
|
||||
if (receiverInfo.nextPullTimeNs < minNextPullTimeNs) {
|
||||
@@ -311,10 +309,9 @@ void StatsPullerManagerImpl::OnAlarmFired() {
|
||||
receiverPtr->onDataPulled(data);
|
||||
// we may have just come out of a coma, compute next pull time
|
||||
receiverInfo->nextPullTimeNs =
|
||||
ceil((double_t)(currentTimeNs - receiverInfo->nextPullTimeNs) /
|
||||
receiverInfo->intervalNs) *
|
||||
receiverInfo->intervalNs +
|
||||
receiverInfo->nextPullTimeNs;
|
||||
(currentTimeNs - receiverInfo->nextPullTimeNs) /
|
||||
receiverInfo->intervalNs * receiverInfo->intervalNs +
|
||||
receiverInfo->intervalNs + receiverInfo->nextPullTimeNs;
|
||||
if (receiverInfo->nextPullTimeNs < minNextPullTimeNs) {
|
||||
minNextPullTimeNs = receiverInfo->nextPullTimeNs;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
// Verify if we know how to pull for this matcher
|
||||
bool PullerForMatcherExists(int tagId) const;
|
||||
|
||||
void OnAlarmFired();
|
||||
void OnAlarmFired(const int64_t timeNs);
|
||||
|
||||
bool Pull(const int tagId, const int64_t timeNs, vector<std::shared_ptr<LogEvent>>* data);
|
||||
|
||||
@@ -90,6 +90,11 @@ public:
|
||||
void updateAlarmLocked();
|
||||
|
||||
int64_t mNextPullTimeNs;
|
||||
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
|
||||
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
|
||||
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -395,6 +395,14 @@ void StatsdStats::resetInternalLocked() {
|
||||
}
|
||||
}
|
||||
|
||||
string buildTimeString(int64_t timeSec) {
|
||||
time_t t = timeSec;
|
||||
struct tm* tm = localtime(&t);
|
||||
char timeBuffer[80];
|
||||
strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
|
||||
return string(timeBuffer);
|
||||
}
|
||||
|
||||
void StatsdStats::dumpStats(FILE* out) const {
|
||||
lock_guard<std::mutex> lock(mLock);
|
||||
time_t t = mStartTimeSec;
|
||||
@@ -437,15 +445,19 @@ void StatsdStats::dumpStats(FILE* out) const {
|
||||
}
|
||||
|
||||
for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) {
|
||||
fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
|
||||
fprintf(out, "\tbroadcast time: %s(%lld)\n",
|
||||
buildTimeString(broadcastTime).c_str(), (long long)broadcastTime);
|
||||
}
|
||||
|
||||
for (const auto& dataDropTime : configStats->data_drop_time_sec) {
|
||||
fprintf(out, "\tdata drop time: %d\n", dataDropTime);
|
||||
fprintf(out, "\tdata drop time: %s(%lld)\n",
|
||||
buildTimeString(dataDropTime).c_str(), (long long)dataDropTime);
|
||||
}
|
||||
|
||||
for (const auto& dump : configStats->dump_report_stats) {
|
||||
fprintf(out, "\tdump report time: %d bytes: %lld\n", dump.first, (long long)dump.second);
|
||||
fprintf(out, "\tdump report time: %s(%lld) bytes: %lld\n",
|
||||
buildTimeString(dump.first).c_str(), (long long)dump.first,
|
||||
(long long)dump.second);
|
||||
}
|
||||
|
||||
for (const auto& stats : pair.second->matcher_stats) {
|
||||
|
||||
@@ -92,7 +92,7 @@ CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric
|
||||
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
|
||||
|
||||
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
|
||||
(long long)mBucketSizeNs, (long long)mStartTimeNs);
|
||||
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
|
||||
}
|
||||
|
||||
CountMetricProducer::~CountMetricProducer() {
|
||||
|
||||
@@ -122,7 +122,7 @@ DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const Durat
|
||||
}
|
||||
}
|
||||
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
|
||||
(long long)mBucketSizeNs, (long long)mStartTimeNs);
|
||||
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
|
||||
}
|
||||
|
||||
DurationMetricProducer::~DurationMetricProducer() {
|
||||
@@ -154,13 +154,13 @@ unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
|
||||
return make_unique<OringDurationTracker>(
|
||||
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
|
||||
mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
|
||||
mStartTimeNs, mBucketSizeNs, mConditionSliced,
|
||||
mTimeBaseNs, mBucketSizeNs, mConditionSliced,
|
||||
mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
|
||||
case DurationMetric_AggregationType_MAX_SPARSE:
|
||||
return make_unique<MaxDurationTracker>(
|
||||
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
|
||||
mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
|
||||
mStartTimeNs, mBucketSizeNs, mConditionSliced,
|
||||
mTimeBaseNs, mBucketSizeNs, mConditionSliced,
|
||||
mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
|
||||
}
|
||||
}
|
||||
@@ -650,7 +650,7 @@ void DurationMetricProducer::onMatchedLogEventInternalLocked(
|
||||
void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
|
||||
const LogEvent& event) {
|
||||
int64_t eventTimeNs = event.GetElapsedTimestampNs();
|
||||
if (eventTimeNs < mStartTimeNs) {
|
||||
if (eventTimeNs < mTimeBaseNs) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric
|
||||
}
|
||||
mProto = std::make_unique<ProtoOutputStream>();
|
||||
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
|
||||
(long long)mBucketSizeNs, (long long)mStartTimeNs);
|
||||
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
|
||||
}
|
||||
|
||||
EventMetricProducer::~EventMetricProducer() {
|
||||
|
||||
@@ -61,9 +61,9 @@ const int FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP = 5;
|
||||
GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const int64_t startTimeNs,
|
||||
const int64_t timeBaseNs, const int64_t startTimeNs,
|
||||
shared_ptr<StatsPullerManager> statsPullerManager)
|
||||
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
|
||||
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
|
||||
mStatsPullerManager(statsPullerManager),
|
||||
mPullTagId(pullTagId),
|
||||
mDimensionSoftLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
|
||||
@@ -110,14 +110,15 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric
|
||||
}
|
||||
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
|
||||
|
||||
flushIfNeededLocked(startTimeNs);
|
||||
// Kicks off the puller immediately.
|
||||
if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
|
||||
mStatsPullerManager->RegisterReceiver(
|
||||
mPullTagId, this, mCurrentBucketStartTimeNs + mBucketSizeNs, mBucketSizeNs);
|
||||
mPullTagId, this, getCurrentBucketEndTimeNs(), mBucketSizeNs);
|
||||
}
|
||||
|
||||
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
|
||||
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs,
|
||||
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
|
||||
mConditionSliced);
|
||||
}
|
||||
|
||||
@@ -125,14 +126,14 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric
|
||||
GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const int64_t startTimeNs)
|
||||
: GaugeMetricProducer(key, metric, conditionIndex, wizard, pullTagId, startTimeNs,
|
||||
const int64_t timeBaseNs, const int64_t startTimeNs)
|
||||
: GaugeMetricProducer(key, metric, conditionIndex, wizard, pullTagId, timeBaseNs, startTimeNs,
|
||||
make_shared<StatsPullerManager>()) {
|
||||
}
|
||||
|
||||
GaugeMetricProducer::~GaugeMetricProducer() {
|
||||
VLOG("~GaugeMetricProducer() called");
|
||||
if (mPullTagId != -1) {
|
||||
if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
|
||||
mStatsPullerManager->UnRegisterReceiver(mPullTagId, this);
|
||||
}
|
||||
}
|
||||
@@ -214,18 +215,20 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(
|
||||
mTagId) ==
|
||||
android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
|
||||
const int64_t wall_clock_ns = truncateTimestamp ?
|
||||
truncateTimestampNsToFiveMinutes(getWallClockNs()) : getWallClockNs();
|
||||
for (const auto& atom : bucket.mGaugeAtoms) {
|
||||
int64_t timestampNs = truncateTimestamp ?
|
||||
truncateTimestampNsToFiveMinutes(atom.mTimestamps) : atom.mTimestamps;
|
||||
const int64_t elapsedTimestampNs = truncateTimestamp ?
|
||||
truncateTimestampNsToFiveMinutes(atom.mElapsedTimestamps) :
|
||||
atom.mElapsedTimestamps;
|
||||
const int64_t wallClockNs = truncateTimestamp ?
|
||||
truncateTimestampNsToFiveMinutes(atom.mWallClockTimestampNs) :
|
||||
atom.mWallClockTimestampNs;
|
||||
protoOutput->write(
|
||||
FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
|
||||
(long long)timestampNs);
|
||||
(long long)elapsedTimestampNs);
|
||||
protoOutput->write(
|
||||
FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED |
|
||||
FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP,
|
||||
(long long)wall_clock_ns);
|
||||
(long long)wallClockNs);
|
||||
}
|
||||
}
|
||||
protoOutput->end(bucketInfoToken);
|
||||
@@ -241,7 +244,7 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
// TODO: Clear mDimensionKeyMap once the report is dumped.
|
||||
}
|
||||
|
||||
void GaugeMetricProducer::pullLocked() {
|
||||
void GaugeMetricProducer::pullLocked(const int64_t timestampNs) {
|
||||
bool triggerPuller = false;
|
||||
switch(mSamplingType) {
|
||||
// When the metric wants to do random sampling and there is already one gauge atom for the
|
||||
@@ -262,7 +265,7 @@ void GaugeMetricProducer::pullLocked() {
|
||||
}
|
||||
|
||||
vector<std::shared_ptr<LogEvent>> allData;
|
||||
if (!mStatsPullerManager->Pull(mPullTagId, getElapsedRealtimeNs(), &allData)) {
|
||||
if (!mStatsPullerManager->Pull(mPullTagId, timestampNs, &allData)) {
|
||||
ALOGE("Gauge Stats puller failed for tag: %d", mPullTagId);
|
||||
return;
|
||||
}
|
||||
@@ -273,26 +276,26 @@ void GaugeMetricProducer::pullLocked() {
|
||||
}
|
||||
|
||||
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
|
||||
const int64_t eventTime) {
|
||||
const int64_t eventTimeNs) {
|
||||
VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
|
||||
flushIfNeededLocked(eventTime);
|
||||
flushIfNeededLocked(eventTimeNs);
|
||||
mCondition = conditionMet;
|
||||
|
||||
if (mPullTagId != -1) {
|
||||
pullLocked();
|
||||
if (mPullTagId != -1 && mCondition) {
|
||||
pullLocked(eventTimeNs);
|
||||
} // else: Push mode. No need to proactively pull the gauge data.
|
||||
}
|
||||
|
||||
void GaugeMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
|
||||
const int64_t eventTime) {
|
||||
const int64_t eventTimeNs) {
|
||||
VLOG("GaugeMetric %lld onSlicedConditionMayChange overall condition %d", (long long)mMetricId,
|
||||
overallCondition);
|
||||
flushIfNeededLocked(eventTime);
|
||||
flushIfNeededLocked(eventTimeNs);
|
||||
// If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
|
||||
// pull for every dimension.
|
||||
mCondition = overallCondition;
|
||||
if (mPullTagId != -1) {
|
||||
pullLocked();
|
||||
pullLocked(eventTimeNs);
|
||||
} // else: Push mode. No need to proactively pull the gauge data.
|
||||
}
|
||||
|
||||
@@ -360,7 +363,7 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked(
|
||||
if (hitGuardRailLocked(eventKey)) {
|
||||
return;
|
||||
}
|
||||
GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs);
|
||||
GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs, getWallClockNs());
|
||||
(*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom);
|
||||
// Anomaly detection on gauge metric only works when there is one numeric
|
||||
// field specified.
|
||||
|
||||
@@ -33,11 +33,12 @@ namespace os {
|
||||
namespace statsd {
|
||||
|
||||
struct GaugeAtom {
|
||||
GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t timeNs)
|
||||
: mFields(fields), mTimestamps(timeNs) {
|
||||
GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int wallClockNs)
|
||||
: mFields(fields), mElapsedTimestamps(elapsedTimeNs), mWallClockTimestampNs(wallClockNs) {
|
||||
}
|
||||
std::shared_ptr<vector<FieldValue>> mFields;
|
||||
int64_t mTimestamps;
|
||||
int64_t mElapsedTimestamps;
|
||||
int64_t mWallClockTimestampNs;
|
||||
};
|
||||
|
||||
struct GaugeBucket {
|
||||
@@ -57,7 +58,7 @@ class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDa
|
||||
public:
|
||||
GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
|
||||
const int conditionIndex, const sp<ConditionWizard>& wizard,
|
||||
const int pullTagId, const int64_t startTimeNs);
|
||||
const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs);
|
||||
|
||||
virtual ~GaugeMetricProducer();
|
||||
|
||||
@@ -76,7 +77,7 @@ public:
|
||||
flushCurrentBucketLocked(eventTimeNs);
|
||||
mCurrentBucketStartTimeNs = eventTimeNs;
|
||||
if (mPullTagId != -1) {
|
||||
pullLocked();
|
||||
pullLocked(eventTimeNs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,7 +95,8 @@ private:
|
||||
// for testing
|
||||
GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
|
||||
const int conditionIndex, const sp<ConditionWizard>& wizard,
|
||||
const int pullTagId, const int64_t startTimeNs,
|
||||
const int pullTagId,
|
||||
const int64_t timeBaseNs, const int64_t startTimeNs,
|
||||
std::shared_ptr<StatsPullerManager> statsPullerManager);
|
||||
|
||||
// Internal interface to handle condition change.
|
||||
@@ -115,7 +117,7 @@ private:
|
||||
|
||||
void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
|
||||
|
||||
void pullLocked();
|
||||
void pullLocked(const int64_t timestampNs);
|
||||
|
||||
int mTagId;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ using std::map;
|
||||
void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
|
||||
int64_t eventTimeNs = event.GetElapsedTimestampNs();
|
||||
// this is old event, maybe statsd restarted?
|
||||
if (eventTimeNs < mStartTimeNs) {
|
||||
if (eventTimeNs < mTimeBaseNs) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +40,12 @@ namespace statsd {
|
||||
// be a no-op.
|
||||
class MetricProducer : public virtual PackageInfoListener {
|
||||
public:
|
||||
MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t startTimeNs,
|
||||
MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
|
||||
const int conditionIndex, const sp<ConditionWizard>& wizard)
|
||||
: mMetricId(metricId),
|
||||
mConfigKey(key),
|
||||
mStartTimeNs(startTimeNs),
|
||||
mCurrentBucketStartTimeNs(startTimeNs),
|
||||
mTimeBaseNs(timeBaseNs),
|
||||
mCurrentBucketStartTimeNs(timeBaseNs),
|
||||
mCurrentBucketNum(0),
|
||||
mCondition(conditionIndex >= 0 ? false : true),
|
||||
mConditionSliced(false),
|
||||
@@ -165,6 +165,11 @@ public:
|
||||
dropDataLocked(dropTimeNs);
|
||||
}
|
||||
|
||||
// For test only.
|
||||
inline int64_t getCurrentBucketNum() const {
|
||||
return mCurrentBucketNum;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0;
|
||||
virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
|
||||
@@ -204,7 +209,7 @@ protected:
|
||||
// Convenience to compute the current bucket's end time, which is always aligned with the
|
||||
// start time of the metric.
|
||||
int64_t getCurrentBucketEndTimeNs() const {
|
||||
return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
|
||||
return mTimeBaseNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
|
||||
}
|
||||
|
||||
virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
|
||||
@@ -215,7 +220,7 @@ protected:
|
||||
|
||||
// The time when this metric producer was first created. The end time for the current bucket
|
||||
// can be computed from this based on mCurrentBucketNum.
|
||||
int64_t mStartTimeNs;
|
||||
int64_t mTimeBaseNs;
|
||||
|
||||
// Start time may not be aligned with the start of statsd if there is an app upgrade in the
|
||||
// middle of a bucket.
|
||||
|
||||
@@ -54,21 +54,21 @@ const int FIELD_ID_ANNOTATIONS_INT64 = 1;
|
||||
const int FIELD_ID_ANNOTATIONS_INT32 = 2;
|
||||
|
||||
MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
|
||||
const long timeBaseSec, const long currentTimeSec,
|
||||
const int64_t timeBaseNs, const int64_t currentTimeNs,
|
||||
const sp<UidMap> &uidMap,
|
||||
const sp<AlarmMonitor>& anomalyAlarmMonitor,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor)
|
||||
: mConfigKey(key), mUidMap(uidMap),
|
||||
mTtlNs(config.has_ttl_in_seconds() ? config.ttl_in_seconds() * NS_PER_SEC : -1),
|
||||
mTtlEndNs(-1),
|
||||
mLastReportTimeNs(timeBaseSec * NS_PER_SEC),
|
||||
mLastReportTimeNs(timeBaseNs),
|
||||
mLastReportWallClockNs(getWallClockNs()) {
|
||||
// Init the ttl end timestamp.
|
||||
refreshTtl(timeBaseSec * NS_PER_SEC);
|
||||
refreshTtl(timeBaseNs);
|
||||
|
||||
mConfigValid =
|
||||
initStatsdConfig(key, config, *uidMap, anomalyAlarmMonitor, periodicAlarmMonitor,
|
||||
timeBaseSec, currentTimeSec, mTagIds, mAllAtomMatchers,
|
||||
timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers,
|
||||
mAllConditionTrackers, mAllMetricProducers, mAllAnomalyTrackers,
|
||||
mAllPeriodicAlarmTrackers, mConditionToMetricMap, mTrackerToMetricMap,
|
||||
mTrackerToConditionMap, mNoReportMetricIds);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace statsd {
|
||||
class MetricsManager : public PackageInfoListener {
|
||||
public:
|
||||
MetricsManager(const ConfigKey& configKey, const StatsdConfig& config,
|
||||
const long timeBaseSec, const long currentTimeSec,
|
||||
const int64_t timeBaseNs, const int64_t currentTimeNs,
|
||||
const sp<UidMap>& uidMap, const sp<AlarmMonitor>& anomalyAlarmMonitor,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor);
|
||||
|
||||
@@ -187,6 +187,11 @@ private:
|
||||
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
|
||||
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
|
||||
FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
|
||||
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
|
||||
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
|
||||
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
|
||||
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
|
||||
FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
|
||||
|
||||
@@ -63,9 +63,9 @@ const int FIELD_ID_VALUE = 3;
|
||||
ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const int64_t startTimeNs,
|
||||
const int64_t timeBaseNs, const int64_t startTimestampNs,
|
||||
shared_ptr<StatsPullerManager> statsPullerManager)
|
||||
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
|
||||
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
|
||||
mValueField(metric.value_field()),
|
||||
mStatsPullerManager(statsPullerManager),
|
||||
mPullTagId(pullTagId),
|
||||
@@ -105,27 +105,28 @@ ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric
|
||||
}
|
||||
}
|
||||
|
||||
if (mValueField.child_size()) {
|
||||
if (mValueField.child_size() > 0) {
|
||||
mField = mValueField.child(0).field();
|
||||
}
|
||||
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
|
||||
|
||||
// Kicks off the puller immediately.
|
||||
flushIfNeededLocked(startTimestampNs);
|
||||
if (mPullTagId != -1) {
|
||||
mStatsPullerManager->RegisterReceiver(
|
||||
mPullTagId, this, mCurrentBucketStartTimeNs + mBucketSizeNs, mBucketSizeNs);
|
||||
}
|
||||
|
||||
VLOG("value metric %lld created. bucket size %lld start_time: %lld",
|
||||
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs);
|
||||
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs);
|
||||
}
|
||||
|
||||
// for testing
|
||||
ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const int64_t startTimeNs)
|
||||
: ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId, startTimeNs,
|
||||
const int64_t timeBaseNs, const int64_t startTimeNs)
|
||||
: ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId, timeBaseNs, startTimeNs,
|
||||
make_shared<StatsPullerManager>()) {
|
||||
}
|
||||
|
||||
@@ -198,7 +199,6 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
|
||||
|
||||
VLOG("metric %lld dump report now...", (long long)mMetricId);
|
||||
mPastBuckets.clear();
|
||||
// TODO: Clear mDimensionKeyMap once the report is dumped.
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onConditionChangedLocked(const bool condition,
|
||||
@@ -237,8 +237,8 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
|
||||
// For scheduled pulled data, the effective event time is snap to the nearest
|
||||
// bucket boundary to make bucket finalize.
|
||||
int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
|
||||
int64_t eventTime = mStartTimeNs +
|
||||
((realEventTime - mStartTimeNs) / mBucketSizeNs) * mBucketSizeNs;
|
||||
int64_t eventTime = mTimeBaseNs +
|
||||
((realEventTime - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
|
||||
|
||||
mCondition = false;
|
||||
for (const auto& data : allData) {
|
||||
@@ -310,7 +310,7 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
|
||||
Interval& interval = mCurrentSlicedBucket[eventKey];
|
||||
|
||||
int error = 0;
|
||||
const long value = event.GetLong(mField, &error);
|
||||
const int64_t value = event.GetLong(mField, &error);
|
||||
if (error < 0) {
|
||||
return;
|
||||
}
|
||||
@@ -337,7 +337,7 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
|
||||
interval.hasValue = true;
|
||||
interval.startUpdated = false;
|
||||
} else {
|
||||
VLOG("No start for matching end %ld", value);
|
||||
VLOG("No start for matching end %lld", (long long)value);
|
||||
interval.tainted += 1;
|
||||
}
|
||||
}
|
||||
@@ -359,7 +359,7 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
|
||||
void ValueMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
|
||||
int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
|
||||
|
||||
if (currentBucketEndTimeNs > eventTimeNs) {
|
||||
if (eventTimeNs < currentBucketEndTimeNs) {
|
||||
VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
|
||||
(long long)(currentBucketEndTimeNs));
|
||||
return;
|
||||
|
||||
@@ -40,7 +40,7 @@ class ValueMetricProducer : public virtual MetricProducer, public virtual PullDa
|
||||
public:
|
||||
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
|
||||
const int conditionIndex, const sp<ConditionWizard>& wizard,
|
||||
const int pullTagId, const int64_t startTimeNs);
|
||||
const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs);
|
||||
|
||||
virtual ~ValueMetricProducer();
|
||||
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
// for testing
|
||||
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
|
||||
const int conditionIndex, const sp<ConditionWizard>& wizard,
|
||||
const int pullTagId, const int64_t startTimeNs,
|
||||
const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
|
||||
std::shared_ptr<StatsPullerManager> statsPullerManager);
|
||||
|
||||
// tagId for pulled data. -1 if this is not pulled
|
||||
@@ -127,14 +127,14 @@ private:
|
||||
typedef struct {
|
||||
// Pulled data always come in pair of <start, end>. This holds the value
|
||||
// for start. The diff (end - start) is added to sum.
|
||||
long start;
|
||||
int64_t start;
|
||||
// Whether the start data point is updated
|
||||
bool startUpdated;
|
||||
// If end data point comes before the start, record this pair as tainted
|
||||
// and the value is not added to the running sum.
|
||||
int tainted;
|
||||
// Running sum of known pairs in this bucket
|
||||
long sum;
|
||||
int64_t sum;
|
||||
// If this dimension has any non-tainted value. If not, don't report the
|
||||
// dimension.
|
||||
bool hasValue;
|
||||
@@ -142,7 +142,7 @@ private:
|
||||
|
||||
std::unordered_map<MetricDimensionKey, Interval> mCurrentSlicedBucket;
|
||||
|
||||
std::unordered_map<MetricDimensionKey, long> mCurrentFullBucket;
|
||||
std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
|
||||
|
||||
// Save the past buckets and we can clear when the StatsLogReport is dumped.
|
||||
// TODO: Add a lock to mPastBuckets.
|
||||
|
||||
@@ -262,7 +262,8 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec,
|
||||
bool initMetrics(const ConfigKey& key, const StatsdConfig& config,
|
||||
const int64_t timeBaseTimeNs, const int64_t currentTimeNs,
|
||||
UidMap& uidMap, const unordered_map<int64_t, int>& logTrackerMap,
|
||||
const unordered_map<int64_t, int>& conditionTrackerMap,
|
||||
const vector<sp<LogMatchingTracker>>& allAtomMatchers,
|
||||
@@ -277,8 +278,6 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long ti
|
||||
allMetricProducers.reserve(allMetricsCount);
|
||||
StatsPullerManager statsPullerManager;
|
||||
|
||||
uint64_t startTimeNs = timeBaseSec * NS_PER_SEC;
|
||||
|
||||
// Build MetricProducers for each metric defined in config.
|
||||
// build CountMetricProducer
|
||||
for (int i = 0; i < config.count_metric_size(); i++) {
|
||||
@@ -314,7 +313,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long ti
|
||||
}
|
||||
|
||||
sp<MetricProducer> countProducer =
|
||||
new CountMetricProducer(key, metric, conditionIndex, wizard, startTimeNs);
|
||||
new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
|
||||
allMetricProducers.push_back(countProducer);
|
||||
}
|
||||
|
||||
@@ -384,7 +383,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long ti
|
||||
|
||||
sp<MetricProducer> durationMetric = new DurationMetricProducer(
|
||||
key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
|
||||
trackerIndices[2], nesting, wizard, internalDimensions, startTimeNs);
|
||||
trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs);
|
||||
|
||||
allMetricProducers.push_back(durationMetric);
|
||||
}
|
||||
@@ -420,7 +419,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long ti
|
||||
}
|
||||
|
||||
sp<MetricProducer> eventMetric =
|
||||
new EventMetricProducer(key, metric, conditionIndex, wizard, startTimeNs);
|
||||
new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
|
||||
|
||||
allMetricProducers.push_back(eventMetric);
|
||||
}
|
||||
@@ -467,7 +466,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long ti
|
||||
}
|
||||
|
||||
sp<MetricProducer> valueProducer = new ValueMetricProducer(key, metric, conditionIndex,
|
||||
wizard, pullTagId, startTimeNs);
|
||||
wizard, pullTagId,
|
||||
timeBaseTimeNs, currentTimeNs);
|
||||
allMetricProducers.push_back(valueProducer);
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long ti
|
||||
}
|
||||
|
||||
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
|
||||
key, metric, conditionIndex, wizard, pullTagId, startTimeNs);
|
||||
key, metric, conditionIndex, wizard, pullTagId, timeBaseTimeNs, currentTimeNs);
|
||||
allMetricProducers.push_back(gaugeProducer);
|
||||
}
|
||||
for (int i = 0; i < config.no_report_metric_size(); ++i) {
|
||||
@@ -601,11 +601,11 @@ bool initAlerts(const StatsdConfig& config,
|
||||
|
||||
bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor,
|
||||
const long timeBaseSec, const long currentTimeSec,
|
||||
const int64_t timeBaseNs, const int64_t currentTimeNs,
|
||||
vector<sp<AlarmTracker>>& allAlarmTrackers) {
|
||||
unordered_map<int64_t, int> alarmTrackerMap;
|
||||
uint64_t startMillis = (uint64_t)timeBaseSec * MS_PER_SEC;
|
||||
uint64_t currentTimeMillis = (uint64_t)currentTimeSec * MS_PER_SEC;
|
||||
int64_t startMillis = timeBaseNs / 1000 / 1000;
|
||||
int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
|
||||
for (int i = 0; i < config.alarm_size(); i++) {
|
||||
const Alarm& alarm = config.alarm(i);
|
||||
if (alarm.offset_millis() <= 0) {
|
||||
@@ -646,8 +646,9 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
|
||||
|
||||
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
|
||||
const sp<AlarmMonitor>& anomalyAlarmMonitor,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor, const long timeBaseSec,
|
||||
const long currentTimeSec, set<int>& allTagIds,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor,
|
||||
const int64_t timeBaseNs, const int64_t currentTimeNs,
|
||||
set<int>& allTagIds,
|
||||
vector<sp<LogMatchingTracker>>& allAtomMatchers,
|
||||
vector<sp<ConditionTracker>>& allConditionTrackers,
|
||||
vector<sp<MetricProducer>>& allMetricProducers,
|
||||
@@ -673,7 +674,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!initMetrics(key, config, timeBaseSec, uidMap, logTrackerMap, conditionTrackerMap,
|
||||
if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap,
|
||||
logTrackerMap, conditionTrackerMap,
|
||||
allAtomMatchers, allConditionTrackers, allMetricProducers,
|
||||
conditionToMetricMap, trackerToMetricMap, metricProducerMap,
|
||||
noReportMetricIds)) {
|
||||
@@ -686,7 +688,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
|
||||
return false;
|
||||
}
|
||||
if (!initAlarms(config, key, periodicAlarmMonitor,
|
||||
timeBaseSec, currentTimeSec, allPeriodicAlarmTrackers)) {
|
||||
timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
|
||||
ALOGE("initAlarms failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,9 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
|
||||
// the list of MetricProducer index
|
||||
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
|
||||
bool initMetrics(
|
||||
const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec, UidMap& uidMap,
|
||||
const ConfigKey& key, const StatsdConfig& config,
|
||||
const int64_t timeBaseTimeNs, const int64_t currentTimeNs,
|
||||
UidMap& uidMap,
|
||||
const std::unordered_map<int64_t, int>& logTrackerMap,
|
||||
const std::unordered_map<int64_t, int>& conditionTrackerMap,
|
||||
const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
|
||||
@@ -96,8 +98,9 @@ bool initMetrics(
|
||||
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
|
||||
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
|
||||
const sp<AlarmMonitor>& anomalyAlarmMonitor,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor, const long timeBaseSec,
|
||||
const long currentTimeSec, std::set<int>& allTagIds,
|
||||
const sp<AlarmMonitor>& periodicAlarmMonitor,
|
||||
const int64_t timeBaseNs, const int64_t currentTimeNs,
|
||||
std::set<int>& allTagIds,
|
||||
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
|
||||
std::vector<sp<ConditionTracker>>& allConditionTrackers,
|
||||
std::vector<sp<MetricProducer>>& allMetricProducers,
|
||||
|
||||
@@ -97,9 +97,9 @@ message ValueMetricData {
|
||||
}
|
||||
|
||||
message GaugeBucketInfo {
|
||||
optional int64 start_bucket_nanos = 1;
|
||||
optional int64 start_bucket_elapsed_nanos = 1;
|
||||
|
||||
optional int64 end_bucket_nanos = 2;
|
||||
optional int64 end_bucket_elapsed_nanos = 2;
|
||||
|
||||
repeated Atom atom = 3;
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ TEST(AlarmE2eTest, TestMultipleAlarms) {
|
||||
int64_t bucketStartTimeNs = 10000000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
EXPECT_EQ(2u, processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers.size());
|
||||
|
||||
@@ -65,7 +65,7 @@ TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||
@@ -168,7 +168,7 @@ TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||
|
||||
@@ -101,7 +101,7 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||
@@ -278,7 +278,7 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||
@@ -391,7 +391,7 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
|
||||
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||
|
||||
@@ -62,7 +62,7 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -204,7 +204,7 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ TEST(ConfigTtlE2eTest, TestCountMetric) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondi
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -404,7 +404,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationConditi
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -648,7 +648,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_Combination
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCon
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -283,7 +283,7 @@ TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondi
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
|
||||
@@ -465,7 +465,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondit
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -666,7 +667,8 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationConditio
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition) {
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -363,7 +363,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition) {
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -582,7 +582,7 @@ TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
|
||||
396
cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
Normal file
396
cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
Normal file
@@ -0,0 +1,396 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "src/StatsLogProcessor.h"
|
||||
#include "src/stats_log_util.h"
|
||||
#include "tests/statsd_test_util.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
namespace {
|
||||
|
||||
StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type) {
|
||||
StatsdConfig config;
|
||||
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
|
||||
auto temperatureAtomMatcher = CreateTemperatureAtomMatcher();
|
||||
*config.add_atom_matcher() = temperatureAtomMatcher;
|
||||
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
|
||||
*config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
|
||||
|
||||
auto screenIsOffPredicate = CreateScreenIsOffPredicate();
|
||||
*config.add_predicate() = screenIsOffPredicate;
|
||||
|
||||
auto gaugeMetric = config.add_gauge_metric();
|
||||
gaugeMetric->set_id(123456);
|
||||
gaugeMetric->set_what(temperatureAtomMatcher.id());
|
||||
gaugeMetric->set_condition(screenIsOffPredicate.id());
|
||||
gaugeMetric->set_sampling_type(sampling_type);
|
||||
gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true);
|
||||
*gaugeMetric->mutable_dimensions_in_what() =
|
||||
CreateDimensions(android::util::TEMPERATURE, {2/* sensor name field */ });
|
||||
gaugeMetric->set_bucket(FIVE_MINUTES);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
|
||||
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
|
||||
int64_t baseTimeNs = 10 * NS_PER_SEC;
|
||||
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
baseTimeNs, configAddedTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
int startBucketNum = processor->mMetricsManagers.begin()->second->
|
||||
mAllMetricProducers[0]->getCurrentBucketNum();
|
||||
EXPECT_GT(startBucketNum, (int64_t)0);
|
||||
|
||||
// When creating the config, the gauge metric producer should register the alarm at the
|
||||
// end of the current bucket.
|
||||
EXPECT_EQ((size_t)1, StatsPullerManagerImpl::GetInstance().mReceivers.size());
|
||||
EXPECT_EQ(bucketSizeNs,
|
||||
StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().intervalNs);
|
||||
int64_t& nextPullTimeNs = StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().nextPullTimeNs;
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 55);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
// Pulling alarm arrives on time and reset the sequential pulling alarm.
|
||||
processor->informPullAlarmFired(nextPullTimeNs + 1);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + bucketSizeNs + 10);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + bucketSizeNs + 100);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
processor->informPullAlarmFired(nextPullTimeNs + 1);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
|
||||
nextPullTimeNs);
|
||||
|
||||
processor->informPullAlarmFired(nextPullTimeNs + 1);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 3 * bucketSizeNs + 2);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
processor->informPullAlarmFired(nextPullTimeNs + 3);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 5 * bucketSizeNs + 1);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
processor->informPullAlarmFired(nextPullTimeNs + 2);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
processor->informPullAlarmFired(nextPullTimeNs + 2);
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(1, reports.reports_size());
|
||||
EXPECT_EQ(1, reports.reports(0).metrics_size());
|
||||
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
|
||||
sortMetricDataByDimensionsValue(
|
||||
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
|
||||
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
|
||||
|
||||
auto data = gaugeMetrics.data(0);
|
||||
EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field());
|
||||
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
|
||||
EXPECT_EQ(2 /* sensor name field */,
|
||||
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
|
||||
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
|
||||
EXPECT_EQ(6, data.bucket_info_size());
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(0).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(1).atom_size());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
|
||||
data.bucket_info(1).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(2).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
|
||||
data.bucket_info(2).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(3).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
|
||||
data.bucket_info(3).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(3).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(3).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(4).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
|
||||
data.bucket_info(4).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(4).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(4).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(5).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
|
||||
data.bucket_info(5).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(5).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_dc(), 0);
|
||||
}
|
||||
|
||||
TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) {
|
||||
auto config = CreateStatsdConfig(GaugeMetric::ALL_CONDITION_CHANGES);
|
||||
int64_t baseTimeNs = 10 * NS_PER_SEC;
|
||||
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
baseTimeNs, configAddedTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
int startBucketNum = processor->mMetricsManagers.begin()->second->
|
||||
mAllMetricProducers[0]->getCurrentBucketNum();
|
||||
EXPECT_GT(startBucketNum, (int64_t)0);
|
||||
|
||||
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 55);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + bucketSizeNs + 10);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + bucketSizeNs + 100);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 3 * bucketSizeNs + 2);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 5 * bucketSizeNs + 1);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 5 * bucketSizeNs + 3);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 5 * bucketSizeNs + 10);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(1, reports.reports_size());
|
||||
EXPECT_EQ(1, reports.reports(0).metrics_size());
|
||||
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
|
||||
sortMetricDataByDimensionsValue(
|
||||
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
|
||||
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
|
||||
|
||||
auto data = gaugeMetrics.data(0);
|
||||
EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field());
|
||||
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
|
||||
EXPECT_EQ(2 /* sensor name field */,
|
||||
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
|
||||
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
|
||||
EXPECT_EQ(3, data.bucket_info_size());
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(0).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(1).atom_size());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
|
||||
data.bucket_info(1).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(2, data.bucket_info(2).atom_size());
|
||||
EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
|
||||
data.bucket_info(2).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
|
||||
data.bucket_info(2).elapsed_timestamp_nanos(1));
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
|
||||
EXPECT_FALSE(data.bucket_info(2).atom(1).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(2).atom(1).temperature().temperature_dc(), 0);
|
||||
}
|
||||
|
||||
|
||||
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
|
||||
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
|
||||
int64_t baseTimeNs = 10 * NS_PER_SEC;
|
||||
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
baseTimeNs, configAddedTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
int startBucketNum = processor->mMetricsManagers.begin()->second->
|
||||
mAllMetricProducers[0]->getCurrentBucketNum();
|
||||
EXPECT_GT(startBucketNum, (int64_t)0);
|
||||
|
||||
// When creating the config, the gauge metric producer should register the alarm at the
|
||||
// end of the current bucket.
|
||||
EXPECT_EQ((size_t)1, StatsPullerManagerImpl::GetInstance().mReceivers.size());
|
||||
EXPECT_EQ(bucketSizeNs,
|
||||
StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().intervalNs);
|
||||
int64_t& nextPullTimeNs = StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().nextPullTimeNs;
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 55);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + bucketSizeNs + 10);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
// Pulling alarm arrives one bucket size late.
|
||||
processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 3 * bucketSizeNs + 11);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
// Pulling alarm arrives more than one bucket size late.
|
||||
processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(1, reports.reports_size());
|
||||
EXPECT_EQ(1, reports.reports(0).metrics_size());
|
||||
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
|
||||
sortMetricDataByDimensionsValue(
|
||||
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
|
||||
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
|
||||
|
||||
auto data = gaugeMetrics.data(0);
|
||||
EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field());
|
||||
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
|
||||
EXPECT_EQ(2 /* sensor name field */,
|
||||
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
|
||||
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
|
||||
EXPECT_EQ(3, data.bucket_info_size());
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(0).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(1).atom_size());
|
||||
EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
|
||||
data.bucket_info(1).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
EXPECT_EQ(1, data.bucket_info(2).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
|
||||
data.bucket_info(2).elapsed_timestamp_nanos(0));
|
||||
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_FALSE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
|
||||
EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
@@ -96,7 +96,8 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -169,9 +170,11 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(2, data.bucket_info(0).atom_size());
|
||||
EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(2, data.bucket_info(0).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::HOT, data.bucket_info(0).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
|
||||
data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::HOT,
|
||||
data.bucket_info(0).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name2",
|
||||
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
|
||||
EXPECT_EQ(102L,
|
||||
@@ -186,8 +189,10 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(1, data.bucket_info(1).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(1).start_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(1).end_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
|
||||
data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
|
||||
data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::WARM,
|
||||
data.bucket_info(1).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name4",
|
||||
@@ -199,9 +204,9 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(2, data.bucket_info(2).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
|
||||
data.bucket_info(2).start_bucket_nanos());
|
||||
data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
|
||||
data.bucket_info(2).end_bucket_nanos());
|
||||
data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::COLD,
|
||||
data.bucket_info(2).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name5",
|
||||
@@ -218,9 +223,11 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(1, data.bucket_info(0).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::HOT, data.bucket_info(0).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
|
||||
data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::HOT,
|
||||
data.bucket_info(0).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name2",
|
||||
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
|
||||
EXPECT_EQ(102L,
|
||||
@@ -229,8 +236,10 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(1, data.bucket_info(1).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(1).start_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(1).end_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
|
||||
data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
|
||||
data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::WARM,
|
||||
data.bucket_info(1).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name4",
|
||||
@@ -242,9 +251,9 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(1, data.bucket_info(2).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
|
||||
data.bucket_info(2).start_bucket_nanos());
|
||||
data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
|
||||
data.bucket_info(2).end_bucket_nanos());
|
||||
data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::COLD,
|
||||
data.bucket_info(2).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name5",
|
||||
@@ -264,8 +273,10 @@ TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
|
||||
EXPECT_EQ(1, data.bucket_info(0).atom_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
|
||||
EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
|
||||
data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
|
||||
data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
|
||||
EXPECT_EQ("activity_name7",
|
||||
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
|
||||
|
||||
@@ -107,7 +107,7 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
@@ -224,7 +224,8 @@ TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
|
||||
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
|
||||
260
cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
Normal file
260
cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include "src/StatsLogProcessor.h"
|
||||
#include "src/stats_log_util.h"
|
||||
#include "tests/statsd_test_util.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
namespace {
|
||||
|
||||
StatsdConfig CreateStatsdConfig() {
|
||||
StatsdConfig config;
|
||||
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
|
||||
auto temperatureAtomMatcher = CreateTemperatureAtomMatcher();
|
||||
*config.add_atom_matcher() = temperatureAtomMatcher;
|
||||
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
|
||||
*config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
|
||||
|
||||
auto screenIsOffPredicate = CreateScreenIsOffPredicate();
|
||||
*config.add_predicate() = screenIsOffPredicate;
|
||||
|
||||
auto valueMetric = config.add_value_metric();
|
||||
valueMetric->set_id(123456);
|
||||
valueMetric->set_what(temperatureAtomMatcher.id());
|
||||
valueMetric->set_condition(screenIsOffPredicate.id());
|
||||
*valueMetric->mutable_value_field() =
|
||||
CreateDimensions(android::util::TEMPERATURE, {3/* temperature degree field */ });
|
||||
*valueMetric->mutable_dimensions_in_what() =
|
||||
CreateDimensions(android::util::TEMPERATURE, {2/* sensor name field */ });
|
||||
valueMetric->set_bucket(FIVE_MINUTES);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(ValueMetricE2eTest, TestPulledEvents) {
|
||||
auto config = CreateStatsdConfig();
|
||||
int64_t baseTimeNs = 10 * NS_PER_SEC;
|
||||
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
baseTimeNs, configAddedTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
int startBucketNum = processor->mMetricsManagers.begin()->second->
|
||||
mAllMetricProducers[0]->getCurrentBucketNum();
|
||||
EXPECT_GT(startBucketNum, (int64_t)0);
|
||||
|
||||
// When creating the config, the gauge metric producer should register the alarm at the
|
||||
// end of the current bucket.
|
||||
EXPECT_EQ((size_t)1, StatsPullerManagerImpl::GetInstance().mReceivers.size());
|
||||
EXPECT_EQ(bucketSizeNs,
|
||||
StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().intervalNs);
|
||||
int64_t& expectedPullTimeNs = StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().nextPullTimeNs;
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 55);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 65);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 75);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
// Pulling alarm arrives on time and reset the sequential pulling alarm.
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
|
||||
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 2 * bucketSizeNs + 15);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 4 * bucketSizeNs + 11);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(1, reports.reports_size());
|
||||
EXPECT_EQ(1, reports.reports(0).metrics_size());
|
||||
StatsLogReport::ValueMetricDataWrapper valueMetrics;
|
||||
sortMetricDataByDimensionsValue(
|
||||
reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
|
||||
EXPECT_GT((int)valueMetrics.data_size(), 1);
|
||||
|
||||
auto data = valueMetrics.data(0);
|
||||
EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field());
|
||||
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
|
||||
EXPECT_EQ(2 /* sensor name field */,
|
||||
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
|
||||
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
|
||||
EXPECT_EQ(5, data.bucket_info_size());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(0).has_value());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(1).has_value());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(2).has_value());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(3).has_value());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(4).has_value());
|
||||
}
|
||||
|
||||
TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
|
||||
auto config = CreateStatsdConfig();
|
||||
int64_t baseTimeNs = 10 * NS_PER_SEC;
|
||||
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
|
||||
int64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
|
||||
|
||||
ConfigKey cfgKey;
|
||||
auto processor = CreateStatsLogProcessor(
|
||||
baseTimeNs, configAddedTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
|
||||
int startBucketNum = processor->mMetricsManagers.begin()->second->
|
||||
mAllMetricProducers[0]->getCurrentBucketNum();
|
||||
EXPECT_GT(startBucketNum, (int64_t)0);
|
||||
|
||||
// When creating the config, the gauge metric producer should register the alarm at the
|
||||
// end of the current bucket.
|
||||
EXPECT_EQ((size_t)1, StatsPullerManagerImpl::GetInstance().mReceivers.size());
|
||||
EXPECT_EQ(bucketSizeNs,
|
||||
StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().intervalNs);
|
||||
int64_t& expectedPullTimeNs = StatsPullerManagerImpl::GetInstance().mReceivers.begin()->
|
||||
second.front().nextPullTimeNs;
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
// Screen off/on/off events.
|
||||
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 55);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 65);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 75);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
// Pulling alarm arrives late by 2 buckets and 1 ns.
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
|
||||
configAddedTimeNs + 4 * bucketSizeNs + 65);
|
||||
processor->OnLogEvent(screenOnEvent.get());
|
||||
|
||||
// Pulling alarm arrives late by one bucket size + 21ns.
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
|
||||
configAddedTimeNs + 6 * bucketSizeNs + 31);
|
||||
processor->OnLogEvent(screenOffEvent.get());
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
processor->informPullAlarmFired(expectedPullTimeNs + 1);
|
||||
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
|
||||
|
||||
ConfigMetricsReportList reports;
|
||||
vector<uint8_t> buffer;
|
||||
processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, &buffer);
|
||||
EXPECT_TRUE(buffer.size() > 0);
|
||||
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
|
||||
EXPECT_EQ(1, reports.reports_size());
|
||||
EXPECT_EQ(1, reports.reports(0).metrics_size());
|
||||
StatsLogReport::ValueMetricDataWrapper valueMetrics;
|
||||
sortMetricDataByDimensionsValue(
|
||||
reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
|
||||
EXPECT_GT((int)valueMetrics.data_size(), 1);
|
||||
|
||||
auto data = valueMetrics.data(0);
|
||||
EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field());
|
||||
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
|
||||
EXPECT_EQ(2 /* sensor name field */,
|
||||
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
|
||||
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
|
||||
EXPECT_EQ(3, data.bucket_info_size());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(0).has_value());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(1).has_value());
|
||||
|
||||
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
|
||||
EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
|
||||
EXPECT_TRUE(data.bucket_info(2).has_value());
|
||||
}
|
||||
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
@@ -121,7 +121,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1)
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
FeedEvents(config, processor);
|
||||
@@ -154,7 +154,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2)
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
FeedEvents(config, processor);
|
||||
@@ -188,7 +188,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3)
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
FeedEvents(config, processor);
|
||||
@@ -231,7 +231,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1)
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
FeedEvents(config, processor);
|
||||
@@ -256,7 +256,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2)
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
FeedEvents(config, processor);
|
||||
@@ -284,7 +284,7 @@ TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3)
|
||||
uint64_t bucketStartTimeNs = 10000000000;
|
||||
uint64_t bucketSizeNs =
|
||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
|
||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
||||
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||
FeedEvents(config, processor);
|
||||
|
||||
@@ -67,7 +67,7 @@ TEST(GaugeMetricProducerTest, TestNoCondition) {
|
||||
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
|
||||
|
||||
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
tagId, bucketStartTimeNs, pullerManager);
|
||||
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
|
||||
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
vector<shared_ptr<LogEvent>> allData;
|
||||
@@ -144,7 +144,7 @@ TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
|
||||
make_shared<StrictMock<MockStatsPullerManager>>();
|
||||
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
-1 /* -1 means no pulling */, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
|
||||
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
|
||||
@@ -228,7 +228,7 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
|
||||
}));
|
||||
|
||||
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
tagId, bucketStartTimeNs, pullerManager);
|
||||
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
|
||||
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
vector<shared_ptr<LogEvent>> allData;
|
||||
@@ -297,7 +297,7 @@ TEST(GaugeMetricProducerTest, TestWithCondition) {
|
||||
}));
|
||||
|
||||
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
|
||||
bucketStartTimeNs, pullerManager);
|
||||
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
|
||||
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
|
||||
@@ -389,7 +389,7 @@ TEST(GaugeMetricProducerTest, TestWithSlicedCondition) {
|
||||
}));
|
||||
|
||||
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
|
||||
@@ -433,7 +433,7 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
|
||||
gaugeFieldMatcher->set_field(tagId);
|
||||
gaugeFieldMatcher->add_child()->set_field(2);
|
||||
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
tagId, bucketStartTimeNs, pullerManager);
|
||||
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
|
||||
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
Alert alert;
|
||||
|
||||
@@ -68,7 +68,7 @@ TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
|
||||
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
tagId, bucketStartTimeNs, pullerManager);
|
||||
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
vector<shared_ptr<LogEvent>> allData;
|
||||
@@ -168,7 +168,7 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
|
||||
}));
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
|
||||
|
||||
@@ -221,7 +221,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
|
||||
shared_ptr<MockStatsPullerManager> pullerManager =
|
||||
make_shared<StrictMock<MockStatsPullerManager>>();
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
|
||||
@@ -277,7 +277,7 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
|
||||
return true;
|
||||
}));
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
vector<shared_ptr<LogEvent>> allData;
|
||||
@@ -320,7 +320,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
|
||||
make_shared<StrictMock<MockStatsPullerManager>>();
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
|
||||
@@ -368,7 +368,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
|
||||
|
||||
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
-1 /*not pulled*/, bucketStartTimeNs);
|
||||
-1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
|
||||
@@ -447,7 +447,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
|
||||
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
|
||||
tagId, bucketStartTimeNs, pullerManager);
|
||||
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
|
||||
vector<shared_ptr<LogEvent>> allData;
|
||||
@@ -556,7 +556,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
|
||||
}));
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
|
||||
|
||||
@@ -650,7 +650,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
|
||||
}));
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
|
||||
|
||||
@@ -742,7 +742,7 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3) {
|
||||
}));
|
||||
|
||||
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
|
||||
pullerManager);
|
||||
bucketStartTimeNs, pullerManager);
|
||||
valueProducer.setBucketSize(60 * NS_PER_SEC);
|
||||
valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
|
||||
AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) {
|
||||
AtomMatcher atom_matcher;
|
||||
atom_matcher.set_id(StringToId(name));
|
||||
@@ -26,6 +27,10 @@ AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) {
|
||||
return atom_matcher;
|
||||
}
|
||||
|
||||
AtomMatcher CreateTemperatureAtomMatcher() {
|
||||
return CreateSimpleAtomMatcher("TemperatureMatcher", android::util::TEMPERATURE);
|
||||
}
|
||||
|
||||
AtomMatcher CreateScheduledJobStateChangedAtomMatcher(const string& name,
|
||||
ScheduledJobStateChanged::State state) {
|
||||
AtomMatcher atom_matcher;
|
||||
@@ -444,8 +449,8 @@ std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
|
||||
return logEvent;
|
||||
}
|
||||
|
||||
sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,
|
||||
const ConfigKey& key) {
|
||||
sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
|
||||
const StatsdConfig& config, const ConfigKey& key) {
|
||||
sp<UidMap> uidMap = new UidMap();
|
||||
sp<AlarmMonitor> anomalyAlarmMonitor =
|
||||
new AlarmMonitor(1, [](const sp<IStatsCompanionService>&, int64_t){},
|
||||
@@ -454,8 +459,8 @@ sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const Stat
|
||||
new AlarmMonitor(1, [](const sp<IStatsCompanionService>&, int64_t){},
|
||||
[](const sp<IStatsCompanionService>&){});
|
||||
sp<StatsLogProcessor> processor = new StatsLogProcessor(
|
||||
uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, [](const ConfigKey&){});
|
||||
processor->OnConfigUpdated(timeBaseSec * NS_PER_SEC, key, config);
|
||||
uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseNs, [](const ConfigKey&){});
|
||||
processor->OnConfigUpdated(currentTimeNs, key, config);
|
||||
return processor;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ namespace statsd {
|
||||
// Create AtomMatcher proto to simply match a specific atom type.
|
||||
AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId);
|
||||
|
||||
// Create AtomMatcher proto for temperature atom.
|
||||
AtomMatcher CreateTemperatureAtomMatcher();
|
||||
|
||||
// Create AtomMatcher proto for scheduled job state changed.
|
||||
AtomMatcher CreateScheduledJobStateChangedAtomMatcher();
|
||||
|
||||
@@ -172,8 +175,9 @@ std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
|
||||
AttributionNodeInternal CreateAttribution(const int& uid, const string& tag);
|
||||
|
||||
// Create a statsd log event processor upon the start time in seconds, config and key.
|
||||
sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config,
|
||||
const ConfigKey& key);
|
||||
sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs,
|
||||
const int64_t currentTimeNs,
|
||||
const StatsdConfig& config, const ConfigKey& key);
|
||||
|
||||
// Util function to sort the log events by timestamp.
|
||||
void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
|
||||
|
||||
Reference in New Issue
Block a user