diff options
40 files changed, 899 insertions, 172 deletions
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 8e46714abbd0..e0222d9f036d 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -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 \ diff --git a/cmds/statsd/benchmark/metric_util.cpp b/cmds/statsd/benchmark/metric_util.cpp index 7d6c47b00100..e6272edf7dcc 100644 --- a/cmds/statsd/benchmark/metric_util.cpp +++ b/cmds/statsd/benchmark/metric_util.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; } diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 90ce73576e90..efcb1fe4827c 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -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 diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 1e82b1e48ebf..0e1d4ba55189 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -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); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index d3cda63e2f86..86a3a787a903 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -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"); diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 83d59c0a5830..50ffe17549c6 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -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, diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp index 2f0e88595d45..610faad85d94 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp @@ -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; } diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.h b/cmds/statsd/src/external/StatsPullerManagerImpl.h index 8c771f31fdc5..56d04b41c5d5 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.h +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.h @@ -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 diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index b589d0dc70be..c342aa5f77ae 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -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) { diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index c77e07b7698c..e21392cb8ce6 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -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() { diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 3125fa7bb63b..3661b31d9ee4 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -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; } diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index 33ab9aa9b184..2f2679efab65 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -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() { diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 3c77aaecfd72..6886f7c2e87a 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -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. diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index 04b7df96a41f..08765c28dbc3 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -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; diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index bcf0e6212cde..5ff8082c9a9d 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -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; } diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index f931e573eb98..532ecbf36d72 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -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. diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index b7f1bd530d5e..47a1a86f861f 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -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); diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 6aa260a0fa7b..3d2c5956df40 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -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); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 89efae35b6f7..844c72801ea6 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -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; diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index b19adbef6bad..9c5a56c7b40e 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -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. diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index 566d34e0df0d..811a00e47ae5 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -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; } diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h index 0ebdcf9d08ee..d749bf43c9be 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.h +++ b/cmds/statsd/src/metrics/metrics_manager_util.h @@ -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, diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index 36b24c8e89da..4f7581d38e43 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -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; diff --git a/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp b/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp index 73c4e7b859de..9ea0b8109209 100644 --- a/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp index 93ecde50955b..c78d99e768f7 100644 --- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp index e924b0303946..50da9e2d48b1 100644 --- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp index 4dd0da8a67d2..4f035be70162 100644 --- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp index bb3ad64b5d63..b98dc60086ac 100644 --- a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp index eb57d47050df..0758fd0d830c 100644 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp index 9729a2e8d965..e74be1e5288c 100644 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp index 4e2c36e12440..c32048bc6885 100644 --- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp +++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp new file mode 100644 index 000000000000..9561fcf4da3f --- /dev/null +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp @@ -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 diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp index 18a048520dd2..d79cb336a20b 100644 --- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp index 1952a6faa4ad..4ace38282f7f 100644 --- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp @@ -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()); diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp new file mode 100644 index 000000000000..62b6fcc7f3a0 --- /dev/null +++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp @@ -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 diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp index f2d47c7ab770..55bf4be41a9c 100644 --- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp @@ -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); diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index a1f865d7e355..698ce727e688 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -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; diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 7b52265bf55c..81d889241b73 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -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); diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index 649c399af179..12649093059b 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -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; } diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index 1ac630ccff96..6ecca46862da 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -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); |