diff options
Diffstat (limited to 'cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp')
-rw-r--r-- | cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp | 664 |
1 files changed, 357 insertions, 307 deletions
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index b9553a8fded8..5997bedcdf2d 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -12,19 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "src/matchers/SimpleLogMatchingTracker.h" #include "src/metrics/GaugeMetricProducer.h" -#include "src/stats_log_util.h" -#include "logd/LogEvent.h" -#include "metrics_test_helper.h" -#include "tests/statsd_test_util.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <math.h> #include <stdio.h> + #include <vector> +#include "logd/LogEvent.h" +#include "metrics_test_helper.h" +#include "src/matchers/SimpleLogMatchingTracker.h" +#include "src/metrics/MetricProducer.h" +#include "src/stats_log_util.h" +#include "stats_event.h" +#include "tests/statsd_test_util.h" + using namespace testing; using android::sp; using std::set; @@ -38,6 +42,8 @@ namespace android { namespace os { namespace statsd { +namespace { + const ConfigKey kConfigKey(0, 12345); const int tagId = 1; const int64_t metricId = 123; @@ -48,7 +54,30 @@ const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000L const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs; const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs; const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs; -const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC; +const int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC; + +shared_ptr<LogEvent> makeLogEvent(int32_t atomId, int64_t timestampNs, int32_t value1, string str1, + int32_t value2) { + AStatsEvent* statsEvent = AStatsEvent_obtain(); + AStatsEvent_setAtomId(statsEvent, atomId); + AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); + + AStatsEvent_writeInt32(statsEvent, value1); + AStatsEvent_writeString(statsEvent, str1.c_str()); + AStatsEvent_writeInt32(statsEvent, value2); + + shared_ptr<LogEvent> logEvent = std::make_shared<LogEvent>(/*uid=*/0, /*pid=*/0); + parseStatsEventToLogEvent(statsEvent, logEvent.get()); + return logEvent; +} +} // anonymous namespace + +// Setup for parameterized tests. +class GaugeMetricProducerTest_PartialBucket : public TestWithParam<BucketSplitEvent> {}; + +INSTANTIATE_TEST_SUITE_P(GaugeMetricProducerTest_PartialBucket, + GaugeMetricProducerTest_PartialBucket, + testing::Values(APP_UPGRADE, BOOT_COMPLETE)); /* * Tests that the first bucket works correctly @@ -75,13 +104,11 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) { // statsd started long ago. // The metric starts in the middle of the bucket - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, - pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, -1, -1, + tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager); gaugeProducer.prepareFirstBucket(); - EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum); EXPECT_EQ(660000000005, gaugeProducer.getCurrentBucketEndTimeNs()); @@ -103,60 +130,49 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, _)) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); - event->write(3); - event->write("some value"); - event->write(11); - event->init(); - data->push_back(event); + data->push_back(makeLogEvent(tagId, eventTimeNs + 10, 3, "some value", 11)); return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, - pullerManager); - + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); vector<shared_ptr<LogEvent>> allData; allData.clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); - event->write(10); - event->write("some value"); - event->write(11); - event->init(); - allData.push_back(event); + allData.push_back(makeLogEvent(tagId, bucket2StartTimeNs + 1, 10, "some value", 11)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin(); EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(10, it->mValue.int_value); it++; EXPECT_EQ(11, it->mValue.int_value); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); - EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms - .front().mFields->begin()->mValue.int_value); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin() + ->second.back() + .mGaugeAtoms.front() + .mFields->begin() + ->mValue.int_value); allData.clear(); - std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10); - event2->write(24); - event2->write("some value"); - event2->write(25); - event2->init(); - allData.push_back(event2); + allData.push_back(makeLogEvent(tagId, bucket3StartTimeNs + 10, 24, "some value", 25)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin(); EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(24, it->mValue.int_value); @@ -164,8 +180,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(25, it->mValue.int_value); // One dimension. - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin(); EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(10L, it->mValue.int_value); @@ -174,10 +190,10 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(11L, it->mValue.int_value); gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs); - EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size()); // One dimension. - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); - EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size()); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size()); it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin(); EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(24L, it->mValue.int_value); @@ -186,7 +202,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) { EXPECT_EQ(25L, it->mValue.int_value); } -TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) { +TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) { sp<AlarmMonitor> alarmMonitor; GaugeMetric metric; metric.set_id(metricId); @@ -204,11 +220,12 @@ TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); @@ -216,58 +233,64 @@ TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) { sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor); EXPECT_TRUE(anomalyTracker != nullptr); - shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); - event1->write(1); - event1->write(10); - event1->init(); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); + LogEvent event1(/*uid=*/0, /*pid=*/0); + CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event1); EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY)); - gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1); + switch (GetParam()) { + case APP_UPGRADE: + gaugeProducer.notifyAppUpgrade(partialBucketSplitTimeNs); + break; + case BOOT_COMPLETE: + gaugeProducer.onStatsdInitCompleted(partialBucketSplitTimeNs); + break; + } EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY)); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(bucketStartTimeNs, + gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs); + EXPECT_EQ(partialBucketSplitTimeNs, + gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs); EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum); - EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); + EXPECT_EQ(partialBucketSplitTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); // Partial buckets are not sent to anomaly tracker. EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY)); // Create an event in the same partial bucket. - shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC); - event2->write(1); - event2->write(10); - event2->init(); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); + LogEvent event2(/*uid=*/0, /*pid=*/0); + CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 59 * NS_PER_SEC, 1, 10); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event2); EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); - EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(bucketStartTimeNs, + gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs); + EXPECT_EQ(partialBucketSplitTimeNs, + gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs); + EXPECT_EQ((int64_t)partialBucketSplitTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); // Partial buckets are not sent to anomaly tracker. EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY)); // Next event should trigger creation of new bucket and send previous full bucket to anomaly // tracker. - shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC); - event3->write(1); - event3->write(10); - event3->init(); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); + LogEvent event3(/*uid=*/0, /*pid=*/0); + CreateTwoValueLogEvent(&event3, tagId, bucketStartTimeNs + 65 * NS_PER_SEC, 1, 10); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event3); EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum); - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + ASSERT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs); EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY)); // Next event should trigger creation of new bucket. - shared_ptr<LogEvent> event4 = - make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC); - event4->write(1); - event4->write(10); - event4->init(); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); + LogEvent event4(/*uid=*/0, /*pid=*/0); + CreateTwoValueLogEvent(&event4, tagId, bucketStartTimeNs + 125 * NS_PER_SEC, 1, 10); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event4); EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum); - EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + ASSERT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY)); } -TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) { +TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) { GaugeMetric metric; metric.set_id(metricId); metric.set_bucket(ONE_MINUTE); @@ -284,59 +307,59 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) { sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({new SimpleLogMatchingTracker( atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, _)) + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) .WillOnce(Return(false)) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs); - event->write("some value"); - event->write(2); - event->init(); - data->push_back(event); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 2)); return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); vector<shared_ptr<LogEvent>> allData; - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); - event->write("some value"); - event->write(1); - event->init(); - allData.push_back(event); + allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() ->mValue.int_value); - gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + switch (GetParam()) { + case APP_UPGRADE: + gaugeProducer.notifyAppUpgrade(partialBucketSplitTimeNs); + break; + case BOOT_COMPLETE: + gaugeProducer.onStatsdInitCompleted(partialBucketSplitTimeNs); + break; + } + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(bucketStartTimeNs, + gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs); + EXPECT_EQ(partialBucketSplitTimeNs, + gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs); EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum); - EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + EXPECT_EQ(partialBucketSplitTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() ->mValue.int_value); allData.clear(); - event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1); - event->write("some value"); - event->write(3); - event->init(); - allData.push_back(event); + allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + bucketSizeNs + 1, 3)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() @@ -358,38 +381,35 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false)); - - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, - pullerManager); + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(false)); + + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); vector<shared_ptr<LogEvent>> allData; - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); - event->write("some value"); - event->write(1); - event->init(); - allData.push_back(event); + allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() ->mValue.int_value); - gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1); - EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + gaugeProducer.notifyAppUpgrade(partialBucketSplitTimeNs); + ASSERT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum); EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() @@ -411,51 +431,48 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + + int64_t conditionChangeNs = bucketStartTimeNs + 8; sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, _)) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, conditionChangeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); - event->write("some value"); - event->write(100); - event->init(); - data->push_back(event); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs + 10, 100)); return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/, + {ConditionState::kUnknown}, wizard, logEventMatcherIndex, + eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, + bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); - gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + gaugeProducer.onConditionChanged(true, conditionChangeNs); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() ->mValue.int_value); - EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(0UL, gaugeProducer.mPastBuckets.size()); vector<shared_ptr<LogEvent>> allData; allData.clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); - event->write("some value"); - event->write(110); - event->init(); - allData.push_back(event); + allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() ->mValue.int_value); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin() ->second.back() .mGaugeAtoms.front() @@ -464,8 +481,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10); gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size()); EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin() ->second.back() .mGaugeAtoms.front() @@ -485,75 +502,61 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) { dim->set_field(tagId); dim->add_child()->set_field(1); - dim = metric.mutable_dimensions_in_condition(); - dim->set_field(conditionTag); - dim->add_child()->set_field(1); - UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); - EXPECT_CALL(*wizard, query(_, _, _, _, _, _)) + EXPECT_CALL(*wizard, query(_, _, _)) .WillRepeatedly( Invoke([](const int conditionIndex, const ConditionKey& conditionParameters, - const vector<Matcher>& dimensionFields, const bool isSubsetDim, - const bool isPartialLink, - std::unordered_set<HashableDimensionKey>* dimensionKeySet) { - dimensionKeySet->clear(); + const bool isPartialLink) { int pos[] = {1, 0, 0}; Field f(conditionTag, pos, 0); HashableDimensionKey key; key.mutableValues()->emplace_back(f, Value((int32_t)1000000)); - dimensionKeySet->insert(key); return ConditionState::kTrue; })); + int64_t sliceConditionChangeNs = bucketStartTimeNs + 8; + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, _)) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, sliceConditionChangeNs, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); - event->write(1000); - event->write(100); - event->init(); - data->push_back(event); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs + 10, 1000, 100)); return true; })); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, - logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, - bucketStartTimeNs, bucketStartTimeNs, pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/, + {ConditionState::kUnknown}, wizard, logEventMatcherIndex, + eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs, + bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); - gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8); + gaugeProducer.onSlicedConditionMayChange(true, sliceConditionChangeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first; - EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size()); + ASSERT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size()); EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value); - EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size()); - EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value); - - EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(0UL, gaugeProducer.mPastBuckets.size()); vector<shared_ptr<LogEvent>> allData; allData.clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); - event->write(1000); - event->write(110); - event->init(); - allData.push_back(event); + allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1000, 110)); gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); } TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { @@ -561,9 +564,10 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); - EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false)); + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _)) + .WillOnce(Return(false)); GaugeMetric metric; metric.set_id(metricId); @@ -576,13 +580,13 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, - pullerManager); + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1, + tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); Alert alert; @@ -595,13 +599,11 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor); int tagId = 1; - std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); - event1->write("some value"); - event1->write(13); - event1->init(); - - gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + vector<shared_ptr<LogEvent>> allData; + allData.clear(); + allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 13)); + gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() @@ -609,13 +611,12 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); std::shared_ptr<LogEvent> event2 = - std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20); - event2->write("some value"); - event2->write(15); - event2->init(); + CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + bucketSizeNs + 20, 15); - gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + allData.clear(); + allData.push_back(event2); + gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() @@ -623,14 +624,11 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec); - std::shared_ptr<LogEvent> event3 = - std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10); - event3->write("some value"); - event3->write(26); - event3->init(); - - gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + allData.clear(); + allData.push_back( + CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10, 26)); + gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin() ->second.front() .mFields->begin() @@ -638,13 +636,11 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) { EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec)); - // The event4 does not have the gauge field. Thus the current bucket value is 0. - std::shared_ptr<LogEvent> event4 = - std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10); - event4->write("some value"); - event4->init(); - gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + // This event does not have the gauge field. Thus the current bucket value is 0. + allData.clear(); + allData.push_back(CreateNoValuesLogEvent(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10)); + gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty()); } @@ -664,51 +660,49 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, _)) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); - event->write(4); - event->init(); - data->push_back(event); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 4)); return true; })) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); - event->write(5); - event->init(); - data->push_back(event); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 5)); return true; })) .WillOnce(Return(true)); int triggerId = 5; - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); - vector<shared_ptr<LogEvent>> allData; + ASSERT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size()); - EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size()); - LogEvent trigger(triggerId, bucketStartTimeNs + 10); - trigger.init(); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); - trigger.setElapsedTimestampNs(bucketStartTimeNs + 20); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); - trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size()); - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size()); + LogEvent triggerEvent(/*uid=*/0, /*pid=*/0); + CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 10); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); + triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 20); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + ASSERT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); + triggerEvent.setElapsedTimestampNs(bucket2StartTimeNs + 1); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + + ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size()); + ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size()); EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin() ->second.back() .mGaugeAtoms[0] @@ -738,75 +732,131 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); - EXPECT_CALL(*pullerManager, Pull(tagId, _)) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _)) + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3); - event->write(3); - event->write(4); - event->init(); - data->push_back(event); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 3, 4)); return true; })) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); - event->write(4); - event->write(5); - event->init(); - data->push_back(event); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 5)); return true; })) - .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20); data->clear(); - shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); - event->write(4); - event->write(6); - event->init(); - data->push_back(event); + data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 6)); return true; })) .WillOnce(Return(true)); int triggerId = 5; - GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager); gaugeProducer.prepareFirstBucket(); - vector<shared_ptr<LogEvent>> allData; - - LogEvent trigger(triggerId, bucketStartTimeNs + 3); - trigger.init(); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); - trigger.setElapsedTimestampNs(bucketStartTimeNs + 10); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size()); - EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); - trigger.setElapsedTimestampNs(bucketStartTimeNs + 20); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); - trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1); - gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger); - - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size()); + LogEvent triggerEvent(/*uid=*/0, /*pid=*/0); + CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 10); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + ASSERT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size()); + ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); + triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 20); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + ASSERT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size()); + triggerEvent.setElapsedTimestampNs(bucket2StartTimeNs + 1); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + + ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.size()); auto bucketIt = gaugeProducer.mPastBuckets.begin(); - EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size()); + ASSERT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size()); EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value); EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value); bucketIt++; - EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size()); + ASSERT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size()); EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value); EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value); EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value); } +/* + * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size + * is smaller than the "min_bucket_size_nanos" specified in the metric config. + */ +TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) { + GaugeMetric metric; + metric.set_id(metricId); + metric.set_bucket(FIVE_MINUTES); + metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES); + metric.set_min_bucket_size_nanos(10000000000); // 10 seconds + + sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); + + UidMap uidMap; + SimpleAtomMatcher atomMatcher; + atomMatcher.set_atom_id(tagId); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); + EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _, _)) + // Bucket start. + .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs, + vector<std::shared_ptr<LogEvent>>* data, bool) { + data->clear(); + data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 10)); + return true; + })); + + int triggerId = 5; + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, + wizard, logEventMatcherIndex, eventMatcherWizard, tagId, + triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs, + pullerManager); + gaugeProducer.prepareFirstBucket(); + + LogEvent triggerEvent(/*uid=*/0, /*pid=*/0); + CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3); + gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent); + + // Check dump report. + ProtoOutputStream output; + std::set<string> strSet; + gaugeProducer.onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */, true, + FAST /* dump_latency */, &strSet, &output); + + StatsLogReport report = outputStreamToProto(&output); + EXPECT_TRUE(report.has_gauge_metrics()); + ASSERT_EQ(0, report.gauge_metrics().data_size()); + ASSERT_EQ(1, report.gauge_metrics().skipped_size()); + + EXPECT_EQ(NanoToMillis(bucketStartTimeNs), + report.gauge_metrics().skipped(0).start_bucket_elapsed_millis()); + EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), + report.gauge_metrics().skipped(0).end_bucket_elapsed_millis()); + ASSERT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size()); + + auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0); + EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason()); + EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis()); +} + } // namespace statsd } // namespace os } // namespace android |