blob: a0addcccb7a1d12f418746a1e892df5a7f009679 [file] [log] [blame]
Chenjie Yu6736c892017-11-09 10:50:09 -08001// 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
Chenjie Yu6736c892017-11-09 10:50:09 -080015#include "src/metrics/ValueMetricProducer.h"
Yangster-macb8144812018-01-04 10:56:23 -080016#include "src/stats_log_util.h"
Yao Chenb3561512017-11-21 18:07:17 -080017#include "metrics_test_helper.h"
Yangster-mac94e197c2018-01-02 16:03:03 -080018#include "tests/statsd_test_util.h"
Chenjie Yu6736c892017-11-09 10:50:09 -080019
20#include <gmock/gmock.h>
21#include <gtest/gtest.h>
22#include <stdio.h>
23#include <vector>
24
25using namespace testing;
26using android::sp;
Yao Chenb3561512017-11-21 18:07:17 -080027using std::make_shared;
Chenjie Yu6736c892017-11-09 10:50:09 -080028using std::set;
Yao Chenb3561512017-11-21 18:07:17 -080029using std::shared_ptr;
Chenjie Yu6736c892017-11-09 10:50:09 -080030using std::unordered_map;
31using std::vector;
Chenjie Yu6736c892017-11-09 10:50:09 -080032
33#ifdef __ANDROID__
34
35namespace android {
36namespace os {
37namespace statsd {
38
Yangster-mac94e197c2018-01-02 16:03:03 -080039const ConfigKey kConfigKey(0, 12345);
Chenjie Yua7259ab2017-12-10 08:31:05 -080040const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080041const int64_t metricId = 123;
Chenjie Yua7259ab2017-12-10 08:31:05 -080042const int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080043const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Chenjie Yua7259ab2017-12-10 08:31:05 -080044const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
45const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
46const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
David Chen27785a82018-01-19 17:06:45 -080047const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
Chenjie Yua7259ab2017-12-10 08:31:05 -080048
Chenjie Yu6736c892017-11-09 10:50:09 -080049/*
50 * Tests pulled atoms with no conditions
51 */
52TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
Chenjie Yu6736c892017-11-09 10:50:09 -080053 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080054 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080055 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -080056 metric.mutable_value_field()->set_field(tagId);
57 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -080058
Chenjie Yu6736c892017-11-09 10:50:09 -080059 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
60 // TODO: pending refactor of StatsPullerManager
61 // For now we still need this so that it doesn't do real pulling.
Yao Chenb3561512017-11-21 18:07:17 -080062 shared_ptr<MockStatsPullerManager> pullerManager =
63 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -080064 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
65 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
66
Yao Chenb3561512017-11-21 18:07:17 -080067 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
68 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -080069 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yu6736c892017-11-09 10:50:09 -080070
71 vector<shared_ptr<LogEvent>> allData;
72 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080073 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
74 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -080075 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -080076 event->init();
77 allData.push_back(event);
78
79 valueProducer.onDataPulled(allData);
80 // has one slice
81 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
82 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
yro59cc24d2018-02-13 20:17:32 -080083 valueProducer.setBucketSize(60 * NS_PER_SEC);
84
Chenjie Yua7259ab2017-12-10 08:31:05 -080085 // startUpdated:true tainted:0 sum:0 start:11
86 EXPECT_EQ(true, curInterval.startUpdated);
87 EXPECT_EQ(0, curInterval.tainted);
88 EXPECT_EQ(0, curInterval.sum);
89 EXPECT_EQ(11, curInterval.start);
90 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
91 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -080092
93 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080094 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
95 event->write(tagId);
96 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -080097 event->init();
98 allData.push_back(event);
99 valueProducer.onDataPulled(allData);
100 // has one slice
101 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
102 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800103 // tartUpdated:false tainted:0 sum:12
104 EXPECT_EQ(true, curInterval.startUpdated);
105 EXPECT_EQ(0, curInterval.tainted);
106 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800107 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800108 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
109 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800110
111 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800112 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
113 event->write(tagId);
114 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800115 event->init();
116 allData.push_back(event);
117 valueProducer.onDataPulled(allData);
118 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
119 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800120 // startUpdated:false tainted:0 sum:12
121 EXPECT_EQ(true, curInterval.startUpdated);
122 EXPECT_EQ(0, curInterval.tainted);
123 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800124 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800125 EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
126 EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800127}
128
129/*
130 * Test pulled event with non sliced condition.
131 */
132TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800133 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800134 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800135 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800136 metric.mutable_value_field()->set_field(tagId);
137 metric.mutable_value_field()->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800138 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800139
Chenjie Yu6736c892017-11-09 10:50:09 -0800140 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800141 shared_ptr<MockStatsPullerManager> pullerManager =
142 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800143 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
144 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
145
Yao Chenb3561512017-11-21 18:07:17 -0800146 EXPECT_CALL(*pullerManager, Pull(tagId, _))
147 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800148 data->clear();
149 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800150 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800151 event->write(100);
152 event->init();
153 data->push_back(event);
154 return true;
155 }))
156 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800157 data->clear();
158 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800159 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800160 event->write(120);
161 event->init();
162 data->push_back(event);
163 return true;
164 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800165
Yao Chenb3561512017-11-21 18:07:17 -0800166 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
167 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800168 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800169 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800170
171 // has one slice
172 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
173 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800174 // startUpdated:false tainted:0 sum:0 start:100
175 EXPECT_EQ(100, curInterval.start);
176 EXPECT_EQ(true, curInterval.startUpdated);
177 EXPECT_EQ(0, curInterval.tainted);
178 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800179 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
180
181 vector<shared_ptr<LogEvent>> allData;
182 allData.clear();
183 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800184 event->write(1);
185 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800186 event->init();
187 allData.push_back(event);
188 valueProducer.onDataPulled(allData);
189
190 // has one slice
191 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
192 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800193 // startUpdated:false tainted:0 sum:0 start:110
194 EXPECT_EQ(110, curInterval.start);
Chenjie Yu6736c892017-11-09 10:50:09 -0800195 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
196 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
197 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
198
199 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
200
201 // has one slice
202 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
203 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800204 // startUpdated:false tainted:0 sum:0 start:110
205 EXPECT_EQ(10, curInterval.sum);
206 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yu6736c892017-11-09 10:50:09 -0800207}
208
David Chen27785a82018-01-19 17:06:45 -0800209TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
210 ValueMetric metric;
211 metric.set_id(metricId);
212 metric.set_bucket(ONE_MINUTE);
213 metric.mutable_value_field()->set_field(tagId);
214 metric.mutable_value_field()->add_child()->set_field(2);
215
216 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
217 shared_ptr<MockStatsPullerManager> pullerManager =
218 make_shared<StrictMock<MockStatsPullerManager>>();
219 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
220 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800221 valueProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800222
223 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
224 event1->write(1);
225 event1->write(10);
226 event1->init();
227 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
228 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
229
230 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
231 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
232 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
233
234 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
235 event2->write(1);
236 event2->write(10);
237 event2->init();
238 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
239 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
240 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
241
242 // Next value should create a new bucket.
243 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
244 event3->write(1);
245 event3->write(10);
246 event3->init();
247 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
248 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
249 EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
250}
251
252TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
253 ValueMetric metric;
254 metric.set_id(metricId);
255 metric.set_bucket(ONE_MINUTE);
256 metric.mutable_value_field()->set_field(tagId);
257 metric.mutable_value_field()->add_child()->set_field(2);
258
259 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
260 shared_ptr<MockStatsPullerManager> pullerManager =
261 make_shared<StrictMock<MockStatsPullerManager>>();
262 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
263 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
264 EXPECT_CALL(*pullerManager, Pull(tagId, _))
265 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
266 data->clear();
267 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
268 event->write(tagId);
269 event->write(120);
270 event->init();
271 data->push_back(event);
272 return true;
273 }));
274 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
275 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800276 valueProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800277
278 vector<shared_ptr<LogEvent>> allData;
279 allData.clear();
280 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
281 event->write(tagId);
282 event->write(100);
283 event->init();
284 allData.push_back(event);
285
286 valueProducer.onDataPulled(allData);
287 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
288
289 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
290 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
291 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
292 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
293
294 allData.clear();
295 event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
296 event->write(tagId);
297 event->write(150);
298 event->init();
299 allData.push_back(event);
300 valueProducer.onDataPulled(allData);
301 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
302 EXPECT_EQ((uint64_t)bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
303 EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
304}
305
Chenjie Yu6736c892017-11-09 10:50:09 -0800306TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800307 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800308 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800309 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800310 metric.mutable_value_field()->set_field(tagId);
311 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800312
Chenjie Yu6736c892017-11-09 10:50:09 -0800313 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800314 shared_ptr<MockStatsPullerManager> pullerManager =
315 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800316
Yao Chenb3561512017-11-21 18:07:17 -0800317 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
318 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800319 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yu6736c892017-11-09 10:50:09 -0800320
321 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800322 event1->write(1);
323 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800324 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800325 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800326 event2->write(1);
327 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800328 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800329 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800330 // has one slice
331 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
332 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800333 EXPECT_EQ(10, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800334
Chenjie Yua7259ab2017-12-10 08:31:05 -0800335 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800336
337 // has one slice
338 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
339 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800340 EXPECT_EQ(30, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800341
Yangsterf2bee6f2017-11-29 12:01:05 -0800342 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800343 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
344 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
345 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
346}
347
Bookatzde1b55622017-12-14 18:38:27 -0800348TEST(ValueMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800349 sp<AlarmMonitor> alarmMonitor;
Bookatzde1b55622017-12-14 18:38:27 -0800350 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800351 alert.set_id(101);
352 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800353 alert.set_trigger_if_sum_gt(130);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800354 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800355 const int32_t refPeriodSec = 3;
356 alert.set_refractory_period_secs(refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800357
358 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800359 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800360 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800361 metric.mutable_value_field()->set_field(tagId);
362 metric.mutable_value_field()->add_child()->set_field(2);
Bookatzde1b55622017-12-14 18:38:27 -0800363
364 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
365 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
366 -1 /*not pulled*/, bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800367 valueProducer.setBucketSize(60 * NS_PER_SEC);
368
Yangster-mac932ecec2018-02-01 10:23:52 -0800369 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
Bookatzde1b55622017-12-14 18:38:27 -0800370
371
372 shared_ptr<LogEvent> event1
373 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
374 event1->write(161);
375 event1->write(10); // value of interest
376 event1->init();
377 shared_ptr<LogEvent> event2
378 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
379 event2->write(162);
380 event2->write(20); // value of interest
381 event2->init();
382 shared_ptr<LogEvent> event3
383 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
384 event3->write(163);
385 event3->write(130); // value of interest
386 event3->init();
387 shared_ptr<LogEvent> event4
388 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
389 event4->write(35);
390 event4->write(1); // value of interest
391 event4->init();
392 shared_ptr<LogEvent> event5
393 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
394 event5->write(45);
395 event5->write(150); // value of interest
396 event5->init();
397 shared_ptr<LogEvent> event6
398 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
399 event6->write(25);
400 event6->write(160); // value of interest
401 event6->init();
402
403 // Two events in bucket #0.
404 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
405 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz1bf94382018-01-04 11:43:20 -0800406 // Value sum == 30 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800407 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800408
409 // One event in bucket #2. No alarm as bucket #0 is trashed out.
410 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz1bf94382018-01-04 11:43:20 -0800411 // Value sum == 130 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800412 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800413
414 // Three events in bucket #3.
415 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
416 // Anomaly at event 4 since Value sum == 131 > 130!
Yangster-mac93694462018-01-22 20:49:31 -0800417 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Yangster-mac330af582018-02-08 15:24:38 -0800418 event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800419 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
420 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Yangster-mac93694462018-01-22 20:49:31 -0800421 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Yangster-mac330af582018-02-08 15:24:38 -0800422 event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800423
424 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
425 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Yangster-mac93694462018-01-22 20:49:31 -0800426 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Yangster-mac330af582018-02-08 15:24:38 -0800427 event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800428}
429
Chenjie Yu6736c892017-11-09 10:50:09 -0800430} // namespace statsd
431} // namespace os
432} // namespace android
433#else
434GTEST_LOG_(INFO) << "This test does nothing.\n";
435#endif