diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index f4db0af29cefe..6178a4bdf136d 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -235,9 +235,12 @@ private: FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm); + FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation); + FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition); FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition); diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h index 45f6b35681435..4ea1386bf78a5 100644 --- a/cmds/statsd/src/external/StatsPullerManager.h +++ b/cmds/statsd/src/external/StatsPullerManager.h @@ -120,8 +120,11 @@ private: FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm); + FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation); + FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); }; } // namespace statsd diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 2f9afa5d5c19e..49fe7ef31a302 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -141,9 +141,6 @@ GaugeMetricProducer::GaugeMetricProducer( // Adjust start for partial bucket mCurrentBucketStartTimeNs = startTimeNs; - if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) { - pullAndMatchEventsLocked(startTimeNs); - } VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d", (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs, @@ -315,6 +312,12 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, } } +void GaugeMetricProducer::prepareFistBucketLocked() { + if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) { + pullAndMatchEventsLocked(mCurrentBucketStartTimeNs); + } +} + void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) { bool triggerPuller = false; switch(mSamplingType) { diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index 9b99fb1fee99f..d3007c8a6778c 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -122,6 +122,8 @@ private: void flushCurrentBucketLocked(const int64_t& eventTimeNs, const int64_t& nextBucketStartTimeNs) override; + void prepareFistBucketLocked() override; + void pullAndMatchEventsLocked(const int64_t timestampNs); const int mWhatMatcherIndex; diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index 5ed95edc02992..e22b853700522 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -25,6 +25,9 @@ namespace statsd { using std::map; void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) { + if (!mIsActive) { + return; + } int64_t eventTimeNs = event.GetElapsedTimestampNs(); // this is old event, maybe statsd restarted? if (eventTimeNs < mTimeBaseNs) { diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h index 70fbd47623448..750566dd8e643 100644 --- a/cmds/statsd/src/metrics/MetricProducer.h +++ b/cmds/statsd/src/metrics/MetricProducer.h @@ -250,6 +250,11 @@ public: mActivationType = activationType; } + void prepareFistBucket() { + std::lock_guard lock(mMutex); + prepareFistBucketLocked(); + } + void flushIfExpire(int64_t elapsedTimestampNs); protected: @@ -281,6 +286,7 @@ protected: void setActiveLocked(int64_t currentTimeNs, int64_t remainingTtlNs); + virtual void prepareFistBucketLocked() {}; /** * Flushes the current bucket if the eventTime is after the current bucket's end time. This will also flush the current partial bucket in memory. diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 00ae3b7028d93..d05bb8b164e83 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -266,9 +266,12 @@ private: FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents); FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm); + FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation); + FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition); FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents); FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm); + FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation); 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 c44ea8aa8ed09..0bd6e624e25f8 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -144,6 +144,9 @@ ValueMetricProducer::ValueMetricProducer( mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) || HasPositionALL(metric.dimensions_in_condition()); + int64_t numBucketsForward = calcBucketsForwardCount(startTimeNs); + mCurrentBucketNum += numBucketsForward; + flushIfNeededLocked(startTimeNs); if (mIsPulled) { @@ -156,10 +159,6 @@ ValueMetricProducer::ValueMetricProducer( // Adjust start for partial bucket mCurrentBucketStartTimeNs = startTimeNs; mConditionTimer.newBucketStart(mCurrentBucketStartTimeNs); - // Kicks off the puller immediately if condition is true and diff based. - if (mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) { - pullAndMatchEventsLocked(startTimeNs, mCondition); - } VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs); } @@ -171,6 +170,13 @@ ValueMetricProducer::~ValueMetricProducer() { } } +void ValueMetricProducer::prepareFistBucketLocked() { + // Kicks off the puller immediately if condition is true and diff based. + if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) { + pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition); + } +} + void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) { VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 8c1999518ea6f..1821dea34975a 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -113,6 +113,8 @@ private: void flushCurrentBucketLocked(const int64_t& eventTimeNs, const int64_t& nextBucketStartTimeNs) override; + void prepareFistBucketLocked() override; + void dropDataLocked(const int64_t dropTimeNs) override; // Calculate previous bucket end time based on current time. diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index 082382cbdb0d7..31b424e8792ee 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -760,6 +760,12 @@ bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config, return true; } +void prepareFistBucket(const vector>& allMetricProducers) { + for (const auto& metric: allMetricProducers) { + metric->prepareFistBucket(); + } +} + bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap, const sp& pullerManager, const sp& anomalyAlarmMonitor, @@ -817,6 +823,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& return false; } + prepareFistBucket(allMetricProducers); + return true; } diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp index 946eccfc39434..f01ad0609295e 100644 --- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp @@ -28,7 +28,10 @@ namespace statsd { namespace { -StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type) { +const int64_t metricId = 123456; + +StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type, + bool useCondition = true) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. auto atomMatcher = CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE); @@ -40,9 +43,11 @@ StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type) { *config.add_predicate() = screenIsOffPredicate; auto gaugeMetric = config.add_gauge_metric(); - gaugeMetric->set_id(123456); + gaugeMetric->set_id(metricId); gaugeMetric->set_what(atomMatcher.id()); - gaugeMetric->set_condition(screenIsOffPredicate.id()); + if (useCondition) { + 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() = @@ -158,7 +163,7 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) { 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 + 1, data.bucket_info(1).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_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty()); @@ -400,6 +405,209 @@ TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) { EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0); } +TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) { + auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false); + + int64_t baseTimeNs = getElapsedRealtimeNs(); + int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000; + + auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher(); + *config.add_atom_matcher() = batterySaverStartMatcher; + const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets. + auto metric_activation = config.add_metric_activation(); + metric_activation->set_metric_id(metricId); + metric_activation->set_activation_type(MetricActivation::ACTIVATE_IMMEDIATELY); + auto event_activation = metric_activation->add_event_activation(); + event_activation->set_atom_matcher_id(batterySaverStartMatcher.id()); + event_activation->set_ttl_seconds(ttlNs / 1000000000); + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor( + baseTimeNs, configAddedTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + processor->mPullerManager->ForceClearPullerCache(); + + int startBucketNum = processor->mMetricsManagers.begin()->second-> + mAllMetricProducers[0]->getCurrentBucketNum(); + EXPECT_GT(startBucketNum, (int64_t)0); + EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + // When creating the config, the gauge metric producer should register the alarm at the + // end of the current bucket. + EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size()); + EXPECT_EQ(bucketSizeNs, + processor->mPullerManager->mReceivers.begin()->second.front().intervalNs); + int64_t& nextPullTimeNs = + processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs; + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs); + + // Pulling alarm arrives on time and reset the sequential pulling alarm. + // Event should not be kept. + processor->informPullAlarmFired(nextPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs); + EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis. + auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs); + processor->OnLogEvent(batterySaverOnEvent.get()); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + // This event should be kept. 1 total. + processor->informPullAlarmFired(nextPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, + nextPullTimeNs); + + // This event should be kept. 2 total. + processor->informPullAlarmFired(nextPullTimeNs + 2); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs); + + // Create random event to deactivate metric. + auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1); + processor->OnLogEvent(deactivationEvent.get()); + EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + // Event should not be kept. 2 total. + processor->informPullAlarmFired(nextPullTimeNs + 3); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs); + + processor->informPullAlarmFired(nextPullTimeNs + 2); + + ConfigMetricsReportList reports; + vector buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true, + ADB_DUMP, FAST, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + 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(), 0); + + auto data = gaugeMetrics.data(0); + EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field()); + EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); + EXPECT_EQ(1 /* subsystem 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(2, 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(baseTimeNs + 4 * bucketSizeNs + 1, data.bucket_info(0).elapsed_timestamp_nanos(0)); + EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); + EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty()); + EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0); + + EXPECT_EQ(1, data.bucket_info(1).atom_size()); + EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size()); + EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, data.bucket_info(1).elapsed_timestamp_nanos(0)); + EXPECT_EQ(0, data.bucket_info(1).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)), + data.bucket_info(1).start_bucket_elapsed_nanos()); + EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)), + data.bucket_info(1).end_bucket_elapsed_nanos()); + EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty()); + EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0); +} + +TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition) { + auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false); + + int64_t baseTimeNs = getElapsedRealtimeNs(); + 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()); + processor->mPullerManager->ForceClearPullerCache(); + + 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, processor->mPullerManager->mReceivers.size()); + EXPECT_EQ(bucketSizeNs, + processor->mPullerManager->mReceivers.begin()->second.front().intervalNs); + int64_t& nextPullTimeNs = + processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs; + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs); + + // Pulling alarm arrives on time and reset the sequential pulling alarm. + processor->informPullAlarmFired(nextPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs); + + processor->informPullAlarmFired(nextPullTimeNs + 4); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, + nextPullTimeNs); + + ConfigMetricsReportList reports; + vector buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true, + ADB_DUMP, FAST, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + 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(), 0); + + auto data = gaugeMetrics.data(0); + EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field()); + EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); + EXPECT_EQ(1 /* subsystem 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, data.bucket_info(0).elapsed_timestamp_nanos(0)); + EXPECT_EQ(0, 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_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty()); + EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0); + + EXPECT_EQ(1, data.bucket_info(1).atom_size()); + EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size()); + EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0)); + EXPECT_EQ(0, data.bucket_info(1).wall_clock_timestamp_nanos_size()); + 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).atom(0).subsystem_sleep_state().subsystem_name().empty()); + EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 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 + 4, data.bucket_info(2).elapsed_timestamp_nanos(0)); + EXPECT_EQ(0, data.bucket_info(2).wall_clock_timestamp_nanos_size()); + 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).atom(0).subsystem_sleep_state().subsystem_name().empty()); + EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0); +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp index b316562c5236e..e967eb34ab2e6 100644 --- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp @@ -28,7 +28,9 @@ namespace statsd { namespace { -StatsdConfig CreateStatsdConfig() { +const int64_t metricId = 123456; + +StatsdConfig CreateStatsdConfig(bool useCondition = true) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. auto pulledAtomMatcher = @@ -41,9 +43,11 @@ StatsdConfig CreateStatsdConfig() { *config.add_predicate() = screenIsOffPredicate; auto valueMetric = config.add_value_metric(); - valueMetric->set_id(123456); + valueMetric->set_id(metricId); valueMetric->set_what(pulledAtomMatcher.id()); - valueMetric->set_condition(screenIsOffPredicate.id()); + if (useCondition) { + valueMetric->set_condition(screenIsOffPredicate.id()); + } *valueMetric->mutable_value_field() = CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */}); *valueMetric->mutable_dimensions_in_what() = @@ -263,6 +267,99 @@ TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) { EXPECT_EQ(1, data.bucket_info(2).values_size()); } +TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) { + auto config = CreateStatsdConfig(false); + int64_t baseTimeNs = getElapsedRealtimeNs(); + int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000; + + auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher(); + *config.add_atom_matcher() = batterySaverStartMatcher; + const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets. + auto metric_activation = config.add_metric_activation(); + metric_activation->set_metric_id(metricId); + metric_activation->set_activation_type(MetricActivation::ACTIVATE_IMMEDIATELY); + auto event_activation = metric_activation->add_event_activation(); + event_activation->set_atom_matcher_id(batterySaverStartMatcher.id()); + event_activation->set_ttl_seconds(ttlNs / 1000000000); + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor( + baseTimeNs, configAddedTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + processor->mPullerManager->ForceClearPullerCache(); + + int startBucketNum = processor->mMetricsManagers.begin()->second-> + mAllMetricProducers[0]->getCurrentBucketNum(); + EXPECT_GT(startBucketNum, (int64_t)0); + EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + // When creating the config, the value metric producer should register the alarm at the + // end of the current bucket. + EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size()); + EXPECT_EQ(bucketSizeNs, + processor->mPullerManager->mReceivers.begin()->second.front().intervalNs); + int64_t& expectedPullTimeNs = + processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs; + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs); + + // Pulling alarm arrives on time and reset the sequential pulling alarm. + processor->informPullAlarmFired(expectedPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs); + + const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis. + auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs); + processor->OnLogEvent(batterySaverOnEvent.get()); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + processor->informPullAlarmFired(expectedPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs); + + processor->informPullAlarmFired(expectedPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs); + + // Create random event to deactivate metric. + auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1); + processor->OnLogEvent(deactivationEvent.get()); + EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive()); + + processor->informPullAlarmFired(expectedPullTimeNs + 1); + EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs); + + processor->informPullAlarmFired(expectedPullTimeNs + 1); + + ConfigMetricsReportList reports; + vector buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true, + ADB_DUMP, FAST, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + 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(), 0); + + auto data = valueMetrics.data(0); + EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field()); + EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); + EXPECT_EQ(1 /* subsystem 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()); + // We have 1 full bucket, the two surrounding the activation are dropped. + EXPECT_EQ(1, data.bucket_info_size()); + + EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); + EXPECT_EQ(1, data.bucket_info(0).values_size()); +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 62868232d8e78..b9a5867527123 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -79,6 +79,8 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) { logEventMatcherIndex, eventMatcherWizard, -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager); + gaugeProducer.prepareFistBucket(); + EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum); @@ -124,6 +126,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); + vector> allData; allData.clear(); shared_ptr event = make_shared(tagId, bucket2StartTimeNs + 1); @@ -207,6 +211,7 @@ TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) { logEventMatcherIndex, eventMatcherWizard, -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); sp anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor); EXPECT_TRUE(anomalyTracker != nullptr); @@ -298,6 +303,7 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) { GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); vector> allData; shared_ptr event = make_shared(tagId, bucketStartTimeNs + 1); @@ -364,6 +370,7 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) { logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); vector> allData; shared_ptr event = make_shared(tagId, bucketStartTimeNs + 1); @@ -424,6 +431,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8); EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); @@ -521,6 +529,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8); @@ -574,6 +583,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); Alert alert; alert.set_id(101); @@ -682,6 +692,7 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) { logEventMatcherIndex, eventMatcherWizard, tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); vector> allData; @@ -766,6 +777,7 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) { logEventMatcherIndex, eventMatcherWizard, tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + gaugeProducer.prepareFistBucket(); vector> allData; diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 43a3c7b0b2eae..148ed5ab259b3 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -105,6 +105,7 @@ class ValueMetricProducerTestHelper { kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer->prepareFistBucket(); return valueProducer; } @@ -124,6 +125,7 @@ class ValueMetricProducerTestHelper { new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer->prepareFistBucket(); valueProducer->mCondition = ConditionState::kFalse; return valueProducer; } @@ -167,6 +169,7 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) { ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase, 22, pullerManager); + valueProducer.prepareFistBucket(); EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10)); EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10)); @@ -196,6 +199,7 @@ TEST(ValueMetricProducerTest, TestFirstBucket) { ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, -1, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager); + valueProducer.prepareFistBucket(); EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(10, valueProducer.mCurrentBucketNum); @@ -377,6 +381,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer->prepareFistBucket(); vector> allData; allData.clear(); @@ -665,6 +670,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -722,6 +728,7 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); vector> allData; allData.clear(); @@ -772,6 +779,7 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); vector> allData; allData.clear(); @@ -846,6 +854,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -888,6 +897,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) { ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); valueProducer.mCondition = ConditionState::kFalse; shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); @@ -962,6 +972,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) { ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); sp anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor); @@ -1258,6 +1269,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -1302,6 +1314,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -1348,6 +1361,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -1398,6 +1412,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -1443,6 +1458,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -1516,6 +1532,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); shared_ptr event1 = make_shared(tagId, bucketStartTimeNs + 10); event1->write(1); @@ -2064,7 +2081,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucket2StartTimeNs, bucket2StartTimeNs, pullerManager); - + valueProducer.prepareFistBucket(); valueProducer.mCondition = ConditionState::kFalse; // Event should be skipped since it is from previous bucket. @@ -2845,6 +2862,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); ProtoOutputStream output; std::set strSet; @@ -2887,6 +2905,7 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); vector> allData; allData.clear(); @@ -2950,6 +2969,7 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) { ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); + valueProducer.prepareFistBucket(); ProtoOutputStream output; std::set strSet;