Home | History | Annotate | Download | only in metrics
      1 // Copyright (C) 2017 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "src/matchers/SimpleLogMatchingTracker.h"
     16 #include "src/metrics/GaugeMetricProducer.h"
     17 #include "src/stats_log_util.h"
     18 #include "logd/LogEvent.h"
     19 #include "metrics_test_helper.h"
     20 #include "tests/statsd_test_util.h"
     21 
     22 #include <gmock/gmock.h>
     23 #include <gtest/gtest.h>
     24 #include <math.h>
     25 #include <stdio.h>
     26 #include <vector>
     27 
     28 using namespace testing;
     29 using android::sp;
     30 using std::set;
     31 using std::unordered_map;
     32 using std::vector;
     33 using std::make_shared;
     34 
     35 #ifdef __ANDROID__
     36 
     37 namespace android {
     38 namespace os {
     39 namespace statsd {
     40 
     41 const ConfigKey kConfigKey(0, 12345);
     42 const int tagId = 1;
     43 const int64_t metricId = 123;
     44 const int64_t atomMatcherId = 678;
     45 const int logEventMatcherIndex = 0;
     46 const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
     47 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
     48 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
     49 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
     50 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
     51 const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
     52 
     53 /*
     54  * Tests that the first bucket works correctly
     55  */
     56 TEST(GaugeMetricProducerTest, TestFirstBucket) {
     57     GaugeMetric metric;
     58     metric.set_id(metricId);
     59     metric.set_bucket(ONE_MINUTE);
     60     metric.mutable_gauge_fields_filter()->set_include_all(false);
     61     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
     62     gaugeFieldMatcher->set_field(tagId);
     63     gaugeFieldMatcher->add_child()->set_field(1);
     64     gaugeFieldMatcher->add_child()->set_field(3);
     65 
     66     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     67 
     68     UidMap uidMap;
     69     SimpleAtomMatcher atomMatcher;
     70     atomMatcher.set_atom_id(tagId);
     71     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
     72         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     73 
     74     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     75 
     76     // statsd started long ago.
     77     // The metric starts in the middle of the bucket
     78     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
     79                                       logEventMatcherIndex, eventMatcherWizard,
     80                                       -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
     81                                       pullerManager);
     82     gaugeProducer.prepareFirstBucket();
     83 
     84 
     85     EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
     86     EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum);
     87     EXPECT_EQ(660000000005, gaugeProducer.getCurrentBucketEndTimeNs());
     88 }
     89 
     90 TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
     91     GaugeMetric metric;
     92     metric.set_id(metricId);
     93     metric.set_bucket(ONE_MINUTE);
     94     metric.mutable_gauge_fields_filter()->set_include_all(false);
     95     metric.set_max_pull_delay_sec(INT_MAX);
     96     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
     97     gaugeFieldMatcher->set_field(tagId);
     98     gaugeFieldMatcher->add_child()->set_field(1);
     99     gaugeFieldMatcher->add_child()->set_field(3);
    100 
    101     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    102 
    103     UidMap uidMap;
    104     SimpleAtomMatcher atomMatcher;
    105     atomMatcher.set_atom_id(tagId);
    106     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    107         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    108 
    109     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    110     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    111     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    112     EXPECT_CALL(*pullerManager, Pull(tagId, _))
    113             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    114                 data->clear();
    115                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    116                 event->write(3);
    117                 event->write("some value");
    118                 event->write(11);
    119                 event->init();
    120                 data->push_back(event);
    121                 return true;
    122             }));
    123 
    124     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    125                                       logEventMatcherIndex, eventMatcherWizard,
    126                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
    127                                       pullerManager);
    128 
    129     gaugeProducer.prepareFirstBucket();
    130 
    131     vector<shared_ptr<LogEvent>> allData;
    132     allData.clear();
    133     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    134     event->write(10);
    135     event->write("some value");
    136     event->write(11);
    137     event->init();
    138     allData.push_back(event);
    139 
    140     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
    141     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    142     auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
    143     EXPECT_EQ(INT, it->mValue.getType());
    144     EXPECT_EQ(10, it->mValue.int_value);
    145     it++;
    146     EXPECT_EQ(11, it->mValue.int_value);
    147     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    148     EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms
    149         .front().mFields->begin()->mValue.int_value);
    150 
    151     allData.clear();
    152     std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
    153     event2->write(24);
    154     event2->write("some value");
    155     event2->write(25);
    156     event2->init();
    157     allData.push_back(event2);
    158     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
    159     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    160     it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
    161     EXPECT_EQ(INT, it->mValue.getType());
    162     EXPECT_EQ(24, it->mValue.int_value);
    163     it++;
    164     EXPECT_EQ(INT, it->mValue.getType());
    165     EXPECT_EQ(25, it->mValue.int_value);
    166     // One dimension.
    167     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    168     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
    169     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
    170     EXPECT_EQ(INT, it->mValue.getType());
    171     EXPECT_EQ(10L, it->mValue.int_value);
    172     it++;
    173     EXPECT_EQ(INT, it->mValue.getType());
    174     EXPECT_EQ(11L, it->mValue.int_value);
    175 
    176     gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
    177     EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
    178     // One dimension.
    179     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    180     EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
    181     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
    182     EXPECT_EQ(INT, it->mValue.getType());
    183     EXPECT_EQ(24L, it->mValue.int_value);
    184     it++;
    185     EXPECT_EQ(INT, it->mValue.getType());
    186     EXPECT_EQ(25L, it->mValue.int_value);
    187 }
    188 
    189 TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
    190     sp<AlarmMonitor> alarmMonitor;
    191     GaugeMetric metric;
    192     metric.set_id(metricId);
    193     metric.set_bucket(ONE_MINUTE);
    194     metric.mutable_gauge_fields_filter()->set_include_all(true);
    195 
    196     Alert alert;
    197     alert.set_id(101);
    198     alert.set_metric_id(metricId);
    199     alert.set_trigger_if_sum_gt(25);
    200     alert.set_num_buckets(100);
    201     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    202     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    203 
    204     UidMap uidMap;
    205     SimpleAtomMatcher atomMatcher;
    206     atomMatcher.set_atom_id(tagId);
    207     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    208         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    209 
    210     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    211                                       logEventMatcherIndex, eventMatcherWizard,
    212                                       -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
    213                                       bucketStartTimeNs, pullerManager);
    214     gaugeProducer.prepareFirstBucket();
    215 
    216     sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
    217     EXPECT_TRUE(anomalyTracker != nullptr);
    218 
    219     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    220     event1->write(1);
    221     event1->write(10);
    222     event1->init();
    223     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
    224     EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
    225 
    226     gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
    227     EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
    228     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    229     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
    230     EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
    231     // Partial buckets are not sent to anomaly tracker.
    232     EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
    233 
    234     // Create an event in the same partial bucket.
    235     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
    236     event2->write(1);
    237     event2->write(10);
    238     event2->init();
    239     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
    240     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
    241     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    242     EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
    243     // Partial buckets are not sent to anomaly tracker.
    244     EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
    245 
    246     // Next event should trigger creation of new bucket and send previous full bucket to anomaly
    247     // tracker.
    248     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
    249     event3->write(1);
    250     event3->write(10);
    251     event3->init();
    252     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
    253     EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
    254     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    255     EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
    256     EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
    257 
    258     // Next event should trigger creation of new bucket.
    259     shared_ptr<LogEvent> event4 =
    260             make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
    261     event4->write(1);
    262     event4->write(10);
    263     event4->init();
    264     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
    265     EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
    266     EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    267     EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
    268 }
    269 
    270 TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
    271     GaugeMetric metric;
    272     metric.set_id(metricId);
    273     metric.set_bucket(ONE_MINUTE);
    274     metric.set_max_pull_delay_sec(INT_MAX);
    275     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
    276     gaugeFieldMatcher->set_field(tagId);
    277     gaugeFieldMatcher->add_child()->set_field(2);
    278 
    279     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    280 
    281     UidMap uidMap;
    282     SimpleAtomMatcher atomMatcher;
    283     atomMatcher.set_atom_id(tagId);
    284     sp<EventMatcherWizard> eventMatcherWizard =
    285             new EventMatcherWizard({new SimpleLogMatchingTracker(
    286                     atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    287 
    288     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    289     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    290     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    291     EXPECT_CALL(*pullerManager, Pull(tagId, _))
    292             .WillOnce(Return(false))
    293             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    294                 data->clear();
    295                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
    296                 event->write("some value");
    297                 event->write(2);
    298                 event->init();
    299                 data->push_back(event);
    300                 return true;
    301             }));
    302 
    303     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    304                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
    305                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
    306     gaugeProducer.prepareFirstBucket();
    307 
    308     vector<shared_ptr<LogEvent>> allData;
    309     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
    310     event->write("some value");
    311     event->write(1);
    312     event->init();
    313     allData.push_back(event);
    314     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
    315     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    316     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
    317                          ->second.front()
    318                          .mFields->begin()
    319                          ->mValue.int_value);
    320 
    321     gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
    322     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    323     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
    324     EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
    325     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    326     EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
    327                          ->second.front()
    328                          .mFields->begin()
    329                          ->mValue.int_value);
    330 
    331     allData.clear();
    332     event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
    333     event->write("some value");
    334     event->write(3);
    335     event->init();
    336     allData.push_back(event);
    337     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
    338     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    339     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    340     EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
    341                          ->second.front()
    342                          .mFields->begin()
    343                          ->mValue.int_value);
    344 }
    345 
    346 TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
    347     GaugeMetric metric;
    348     metric.set_id(metricId);
    349     metric.set_bucket(ONE_MINUTE);
    350     metric.set_max_pull_delay_sec(INT_MAX);
    351     metric.set_split_bucket_for_app_upgrade(false);
    352     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
    353     gaugeFieldMatcher->set_field(tagId);
    354     gaugeFieldMatcher->add_child()->set_field(2);
    355 
    356     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    357 
    358     UidMap uidMap;
    359     SimpleAtomMatcher atomMatcher;
    360     atomMatcher.set_atom_id(tagId);
    361     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    362         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    363 
    364     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    365     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    366     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    367     EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
    368 
    369     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    370                                       logEventMatcherIndex, eventMatcherWizard,
    371                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
    372                                       pullerManager);
    373     gaugeProducer.prepareFirstBucket();
    374 
    375     vector<shared_ptr<LogEvent>> allData;
    376     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
    377     event->write("some value");
    378     event->write(1);
    379     event->init();
    380     allData.push_back(event);
    381     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
    382     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    383     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
    384                          ->second.front()
    385                          .mFields->begin()
    386                          ->mValue.int_value);
    387 
    388     gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
    389     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
    390     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
    391     EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
    392     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    393     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
    394                          ->second.front()
    395                          .mFields->begin()
    396                          ->mValue.int_value);
    397 }
    398 
    399 TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
    400     GaugeMetric metric;
    401     metric.set_id(metricId);
    402     metric.set_bucket(ONE_MINUTE);
    403     metric.set_max_pull_delay_sec(INT_MAX);
    404     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
    405     gaugeFieldMatcher->set_field(tagId);
    406     gaugeFieldMatcher->add_child()->set_field(2);
    407     metric.set_condition(StringToId("SCREEN_ON"));
    408 
    409     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    410 
    411     UidMap uidMap;
    412     SimpleAtomMatcher atomMatcher;
    413     atomMatcher.set_atom_id(tagId);
    414     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    415         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    416 
    417     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    418     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    419     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    420     EXPECT_CALL(*pullerManager, Pull(tagId, _))
    421             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    422                 data->clear();
    423                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    424                 event->write("some value");
    425                 event->write(100);
    426                 event->init();
    427                 data->push_back(event);
    428                 return true;
    429             }));
    430 
    431     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
    432                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
    433                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
    434     gaugeProducer.prepareFirstBucket();
    435 
    436     gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
    437     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    438     EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
    439                            ->second.front()
    440                            .mFields->begin()
    441                            ->mValue.int_value);
    442     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
    443 
    444     vector<shared_ptr<LogEvent>> allData;
    445     allData.clear();
    446     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    447     event->write("some value");
    448     event->write(110);
    449     event->init();
    450     allData.push_back(event);
    451     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
    452 
    453     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    454     EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
    455                            ->second.front()
    456                            .mFields->begin()
    457                            ->mValue.int_value);
    458     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    459     EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
    460                            ->second.back()
    461                            .mGaugeAtoms.front()
    462                            .mFields->begin()
    463                            ->mValue.int_value);
    464 
    465     gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
    466     gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
    467     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    468     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
    469     EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
    470                             ->second.back()
    471                             .mGaugeAtoms.front()
    472                             .mFields->begin()
    473                             ->mValue.int_value);
    474 }
    475 
    476 TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
    477     const int conditionTag = 65;
    478     GaugeMetric metric;
    479     metric.set_id(1111111);
    480     metric.set_bucket(ONE_MINUTE);
    481     metric.mutable_gauge_fields_filter()->set_include_all(true);
    482     metric.set_condition(StringToId("APP_DIED"));
    483     metric.set_max_pull_delay_sec(INT_MAX);
    484     auto dim = metric.mutable_dimensions_in_what();
    485     dim->set_field(tagId);
    486     dim->add_child()->set_field(1);
    487 
    488     dim = metric.mutable_dimensions_in_condition();
    489     dim->set_field(conditionTag);
    490     dim->add_child()->set_field(1);
    491 
    492     UidMap uidMap;
    493     SimpleAtomMatcher atomMatcher;
    494     atomMatcher.set_atom_id(tagId);
    495     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    496         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    497 
    498     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    499     EXPECT_CALL(*wizard, query(_, _, _, _, _, _))
    500             .WillRepeatedly(
    501                     Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
    502                               const vector<Matcher>& dimensionFields, const bool isSubsetDim,
    503                               const bool isPartialLink,
    504                               std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
    505                         dimensionKeySet->clear();
    506                         int pos[] = {1, 0, 0};
    507                         Field f(conditionTag, pos, 0);
    508                         HashableDimensionKey key;
    509                         key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
    510                         dimensionKeySet->insert(key);
    511 
    512                         return ConditionState::kTrue;
    513                     }));
    514 
    515     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    516     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    517     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    518     EXPECT_CALL(*pullerManager, Pull(tagId, _))
    519             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    520                 data->clear();
    521                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    522                 event->write(1000);
    523                 event->write(100);
    524                 event->init();
    525                 data->push_back(event);
    526                 return true;
    527             }));
    528 
    529     GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
    530                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
    531                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
    532     gaugeProducer.prepareFirstBucket();
    533 
    534     gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
    535 
    536     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    537     const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
    538     EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
    539     EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
    540 
    541     EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size());
    542     EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value);
    543 
    544     EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
    545 
    546     vector<shared_ptr<LogEvent>> allData;
    547     allData.clear();
    548     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
    549     event->write(1000);
    550     event->write(110);
    551     event->init();
    552     allData.push_back(event);
    553     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
    554 
    555     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    556     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    557 }
    558 
    559 TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
    560     sp<AlarmMonitor> alarmMonitor;
    561     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    562 
    563     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    564     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
    565     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
    566     EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
    567 
    568     GaugeMetric metric;
    569     metric.set_id(metricId);
    570     metric.set_bucket(ONE_MINUTE);
    571     metric.set_max_pull_delay_sec(INT_MAX);
    572     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
    573     gaugeFieldMatcher->set_field(tagId);
    574     gaugeFieldMatcher->add_child()->set_field(2);
    575 
    576     UidMap uidMap;
    577     SimpleAtomMatcher atomMatcher;
    578     atomMatcher.set_atom_id(tagId);
    579     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    580         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    581 
    582     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    583                                       logEventMatcherIndex, eventMatcherWizard,
    584                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
    585                                       pullerManager);
    586     gaugeProducer.prepareFirstBucket();
    587 
    588     Alert alert;
    589     alert.set_id(101);
    590     alert.set_metric_id(metricId);
    591     alert.set_trigger_if_sum_gt(25);
    592     alert.set_num_buckets(2);
    593     const int32_t refPeriodSec = 60;
    594     alert.set_refractory_period_secs(refPeriodSec);
    595     sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
    596 
    597     int tagId = 1;
    598     std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
    599     event1->write("some value");
    600     event1->write(13);
    601     event1->init();
    602 
    603     gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
    604     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    605     EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
    606                            ->second.front()
    607                            .mFields->begin()
    608                            ->mValue.int_value);
    609     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
    610 
    611     std::shared_ptr<LogEvent> event2 =
    612             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
    613     event2->write("some value");
    614     event2->write(15);
    615     event2->init();
    616 
    617     gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
    618     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    619     EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
    620                            ->second.front()
    621                            .mFields->begin()
    622                            ->mValue.int_value);
    623     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
    624               std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
    625 
    626     std::shared_ptr<LogEvent> event3 =
    627             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
    628     event3->write("some value");
    629     event3->write(26);
    630     event3->init();
    631 
    632     gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
    633     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    634     EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
    635                            ->second.front()
    636                            .mFields->begin()
    637                            ->mValue.int_value);
    638     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
    639               std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
    640 
    641     // The event4 does not have the gauge field. Thus the current bucket value is 0.
    642     std::shared_ptr<LogEvent> event4 =
    643             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
    644     event4->write("some value");
    645     event4->init();
    646     gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
    647     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    648     EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
    649 }
    650 
    651 TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
    652     GaugeMetric metric;
    653     metric.set_id(metricId);
    654     metric.set_bucket(ONE_MINUTE);
    655     metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
    656     metric.mutable_gauge_fields_filter()->set_include_all(false);
    657     metric.set_max_pull_delay_sec(INT_MAX);
    658     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
    659     gaugeFieldMatcher->set_field(tagId);
    660     gaugeFieldMatcher->add_child()->set_field(1);
    661 
    662     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    663 
    664     UidMap uidMap;
    665     SimpleAtomMatcher atomMatcher;
    666     atomMatcher.set_atom_id(tagId);
    667     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    668         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    669 
    670     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    671     EXPECT_CALL(*pullerManager, Pull(tagId, _))
    672             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    673                 data->clear();
    674                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    675                 event->write(4);
    676                 event->init();
    677                 data->push_back(event);
    678                 return true;
    679             }))
    680             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    681                 data->clear();
    682                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
    683                 event->write(5);
    684                 event->init();
    685                 data->push_back(event);
    686                 return true;
    687             }))
    688             .WillOnce(Return(true));
    689 
    690     int triggerId = 5;
    691     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    692                                       logEventMatcherIndex, eventMatcherWizard,
    693                                       tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
    694                                       pullerManager);
    695     gaugeProducer.prepareFirstBucket();
    696 
    697     vector<shared_ptr<LogEvent>> allData;
    698 
    699     EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
    700     LogEvent trigger(triggerId, bucketStartTimeNs + 10);
    701     trigger.init();
    702     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    703     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
    704     trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
    705     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    706     EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
    707     trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
    708     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    709 
    710     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
    711     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
    712     EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
    713                          ->second.back()
    714                          .mGaugeAtoms[0]
    715                          .mFields->begin()
    716                          ->mValue.int_value);
    717     EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()
    718                          ->second.back()
    719                          .mGaugeAtoms[1]
    720                          .mFields->begin()
    721                          ->mValue.int_value);
    722 }
    723 
    724 TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
    725     GaugeMetric metric;
    726     metric.set_id(metricId);
    727     metric.set_bucket(ONE_MINUTE);
    728     metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
    729     metric.mutable_gauge_fields_filter()->set_include_all(true);
    730     metric.set_max_pull_delay_sec(INT_MAX);
    731     auto dimensionMatcher = metric.mutable_dimensions_in_what();
    732     // use field 1 as dimension.
    733     dimensionMatcher->set_field(tagId);
    734     dimensionMatcher->add_child()->set_field(1);
    735 
    736     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
    737 
    738     UidMap uidMap;
    739     SimpleAtomMatcher atomMatcher;
    740     atomMatcher.set_atom_id(tagId);
    741     sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
    742         new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
    743 
    744     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
    745     EXPECT_CALL(*pullerManager, Pull(tagId, _))
    746             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    747                 data->clear();
    748                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
    749                 event->write(3);
    750                 event->write(4);
    751                 event->init();
    752                 data->push_back(event);
    753                 return true;
    754             }))
    755             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    756                 data->clear();
    757                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
    758                 event->write(4);
    759                 event->write(5);
    760                 event->init();
    761                 data->push_back(event);
    762                 return true;
    763             }))
    764             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
    765                 data->clear();
    766                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
    767                 event->write(4);
    768                 event->write(6);
    769                 event->init();
    770                 data->push_back(event);
    771                 return true;
    772             }))
    773             .WillOnce(Return(true));
    774 
    775     int triggerId = 5;
    776     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
    777                                       logEventMatcherIndex, eventMatcherWizard,
    778                                       tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
    779                                       pullerManager);
    780     gaugeProducer.prepareFirstBucket();
    781 
    782     vector<shared_ptr<LogEvent>> allData;
    783 
    784     LogEvent trigger(triggerId, bucketStartTimeNs + 3);
    785     trigger.init();
    786     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    787     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
    788     trigger.setElapsedTimestampNs(bucketStartTimeNs + 10);
    789     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    790     EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
    791     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
    792     trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
    793     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    794     EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
    795     trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
    796     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
    797 
    798     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
    799     auto bucketIt = gaugeProducer.mPastBuckets.begin();
    800     EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
    801     EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
    802     EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
    803     bucketIt++;
    804     EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
    805     EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
    806     EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
    807     EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
    808 }
    809 
    810 }  // namespace statsd
    811 }  // namespace os
    812 }  // namespace android
    813 #else
    814 GTEST_LOG_(INFO) << "This test does nothing.\n";
    815 #endif
    816