blob: a8eb27037ebf0294a005a0ab39a12f6e98b87d2e [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>
Bookatz6bf98252018-03-14 10:44:24 -070022#include <math.h>
Chenjie Yu6736c892017-11-09 10:50:09 -080023#include <stdio.h>
24#include <vector>
25
26using namespace testing;
27using android::sp;
Yao Chenb3561512017-11-21 18:07:17 -080028using std::make_shared;
Chenjie Yu6736c892017-11-09 10:50:09 -080029using std::set;
Yao Chenb3561512017-11-21 18:07:17 -080030using std::shared_ptr;
Chenjie Yu6736c892017-11-09 10:50:09 -080031using std::unordered_map;
32using std::vector;
Chenjie Yu6736c892017-11-09 10:50:09 -080033
34#ifdef __ANDROID__
35
36namespace android {
37namespace os {
38namespace statsd {
39
Yangster-mac94e197c2018-01-02 16:03:03 -080040const ConfigKey kConfigKey(0, 12345);
Chenjie Yua7259ab2017-12-10 08:31:05 -080041const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080042const int64_t metricId = 123;
Chenjie Yua7259ab2017-12-10 08:31:05 -080043const int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080044const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Chenjie Yua7259ab2017-12-10 08:31:05 -080045const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
46const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
47const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
David Chen27785a82018-01-19 17:06:45 -080048const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
Chenjie Yua7259ab2017-12-10 08:31:05 -080049
Chenjie Yu6736c892017-11-09 10:50:09 -080050/*
51 * Tests pulled atoms with no conditions
52 */
53TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
Chenjie Yu6736c892017-11-09 10:50:09 -080054 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080055 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080056 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -080057 metric.mutable_value_field()->set_field(tagId);
58 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -080059
Chenjie Yu6736c892017-11-09 10:50:09 -080060 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
61 // TODO: pending refactor of StatsPullerManager
62 // For now we still need this so that it doesn't do real pulling.
Yao Chenb3561512017-11-21 18:07:17 -080063 shared_ptr<MockStatsPullerManager> pullerManager =
64 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -080065 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
66 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
67
Yao Chenb3561512017-11-21 18:07:17 -080068 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
69 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -080070 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yu6736c892017-11-09 10:50:09 -080071
72 vector<shared_ptr<LogEvent>> allData;
73 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080074 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
75 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -080076 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -080077 event->init();
78 allData.push_back(event);
79
80 valueProducer.onDataPulled(allData);
81 // has one slice
82 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
83 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
yro59cc24d2018-02-13 20:17:32 -080084 valueProducer.setBucketSize(60 * NS_PER_SEC);
85
Chenjie Yua7259ab2017-12-10 08:31:05 -080086 // startUpdated:true tainted:0 sum:0 start:11
87 EXPECT_EQ(true, curInterval.startUpdated);
88 EXPECT_EQ(0, curInterval.tainted);
89 EXPECT_EQ(0, curInterval.sum);
90 EXPECT_EQ(11, curInterval.start);
91 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
92 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -080093
94 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080095 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
96 event->write(tagId);
97 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -080098 event->init();
99 allData.push_back(event);
100 valueProducer.onDataPulled(allData);
101 // has one slice
102 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
103 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800104 // tartUpdated:false tainted:0 sum:12
105 EXPECT_EQ(true, curInterval.startUpdated);
106 EXPECT_EQ(0, curInterval.tainted);
107 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800108 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800109 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
110 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800111
112 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800113 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
114 event->write(tagId);
115 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800116 event->init();
117 allData.push_back(event);
118 valueProducer.onDataPulled(allData);
119 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
120 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800121 // startUpdated:false tainted:0 sum:12
122 EXPECT_EQ(true, curInterval.startUpdated);
123 EXPECT_EQ(0, curInterval.tainted);
124 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800125 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800126 EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
127 EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800128}
129
130/*
131 * Test pulled event with non sliced condition.
132 */
133TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800134 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800135 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800136 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800137 metric.mutable_value_field()->set_field(tagId);
138 metric.mutable_value_field()->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800139 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800140
Chenjie Yu6736c892017-11-09 10:50:09 -0800141 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800142 shared_ptr<MockStatsPullerManager> pullerManager =
143 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800144 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
145 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
146
Yao Chenb3561512017-11-21 18:07:17 -0800147 EXPECT_CALL(*pullerManager, Pull(tagId, _))
148 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800149 data->clear();
150 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800151 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800152 event->write(100);
153 event->init();
154 data->push_back(event);
155 return true;
156 }))
157 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800158 data->clear();
159 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800160 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800161 event->write(120);
162 event->init();
163 data->push_back(event);
164 return true;
165 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800166
Yao Chenb3561512017-11-21 18:07:17 -0800167 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
168 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800169 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800170 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800171
172 // has one slice
173 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
174 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800175 // startUpdated:false tainted:0 sum:0 start:100
176 EXPECT_EQ(100, curInterval.start);
177 EXPECT_EQ(true, curInterval.startUpdated);
178 EXPECT_EQ(0, curInterval.tainted);
179 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800180 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
181
182 vector<shared_ptr<LogEvent>> allData;
183 allData.clear();
184 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800185 event->write(1);
186 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800187 event->init();
188 allData.push_back(event);
189 valueProducer.onDataPulled(allData);
190
191 // has one slice
192 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
193 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800194 // startUpdated:false tainted:0 sum:0 start:110
195 EXPECT_EQ(110, curInterval.start);
Chenjie Yu6736c892017-11-09 10:50:09 -0800196 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
197 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
198 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
199
200 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
201
202 // has one slice
203 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
204 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800205 // startUpdated:false tainted:0 sum:0 start:110
206 EXPECT_EQ(10, curInterval.sum);
207 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yu6736c892017-11-09 10:50:09 -0800208}
209
David Chen27785a82018-01-19 17:06:45 -0800210TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
211 ValueMetric metric;
212 metric.set_id(metricId);
213 metric.set_bucket(ONE_MINUTE);
214 metric.mutable_value_field()->set_field(tagId);
215 metric.mutable_value_field()->add_child()->set_field(2);
216
217 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
218 shared_ptr<MockStatsPullerManager> pullerManager =
219 make_shared<StrictMock<MockStatsPullerManager>>();
220 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
221 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800222 valueProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800223
224 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
225 event1->write(1);
226 event1->write(10);
227 event1->init();
228 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
229 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
230
231 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
232 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
233 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
234
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 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
240 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
241 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
242
243 // Next value should create a new bucket.
244 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
245 event3->write(1);
246 event3->write(10);
247 event3->init();
248 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
249 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
250 EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
251}
252
253TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
254 ValueMetric metric;
255 metric.set_id(metricId);
256 metric.set_bucket(ONE_MINUTE);
257 metric.mutable_value_field()->set_field(tagId);
258 metric.mutable_value_field()->add_child()->set_field(2);
259
260 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
261 shared_ptr<MockStatsPullerManager> pullerManager =
262 make_shared<StrictMock<MockStatsPullerManager>>();
263 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
264 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
265 EXPECT_CALL(*pullerManager, Pull(tagId, _))
266 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
267 data->clear();
268 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
269 event->write(tagId);
270 event->write(120);
271 event->init();
272 data->push_back(event);
273 return true;
274 }));
275 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
276 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800277 valueProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800278
279 vector<shared_ptr<LogEvent>> allData;
280 allData.clear();
281 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
282 event->write(tagId);
283 event->write(100);
284 event->init();
285 allData.push_back(event);
286
287 valueProducer.onDataPulled(allData);
288 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
289
290 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
291 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
292 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
293 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
294
295 allData.clear();
296 event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
297 event->write(tagId);
298 event->write(150);
299 event->init();
300 allData.push_back(event);
301 valueProducer.onDataPulled(allData);
302 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
303 EXPECT_EQ((uint64_t)bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
304 EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
305}
306
Chenjie Yu6736c892017-11-09 10:50:09 -0800307TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800308 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800309 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800310 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800311 metric.mutable_value_field()->set_field(tagId);
312 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800313
Chenjie Yu6736c892017-11-09 10:50:09 -0800314 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800315 shared_ptr<MockStatsPullerManager> pullerManager =
316 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800317
Yao Chenb3561512017-11-21 18:07:17 -0800318 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
319 pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800320 valueProducer.setBucketSize(60 * NS_PER_SEC);
Chenjie Yu6736c892017-11-09 10:50:09 -0800321
322 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800323 event1->write(1);
324 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800325 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800326 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800327 event2->write(1);
328 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800329 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800330 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800331 // has one slice
332 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
333 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800334 EXPECT_EQ(10, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800335
Chenjie Yua7259ab2017-12-10 08:31:05 -0800336 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800337
338 // has one slice
339 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
340 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800341 EXPECT_EQ(30, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800342
Yangsterf2bee6f2017-11-29 12:01:05 -0800343 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800344 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
345 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
346 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
347}
348
Bookatzde1b55622017-12-14 18:38:27 -0800349TEST(ValueMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800350 sp<AlarmMonitor> alarmMonitor;
Bookatzde1b55622017-12-14 18:38:27 -0800351 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800352 alert.set_id(101);
353 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800354 alert.set_trigger_if_sum_gt(130);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800355 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800356 const int32_t refPeriodSec = 3;
357 alert.set_refractory_period_secs(refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800358
359 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800360 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800361 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800362 metric.mutable_value_field()->set_field(tagId);
363 metric.mutable_value_field()->add_child()->set_field(2);
Bookatzde1b55622017-12-14 18:38:27 -0800364
365 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
366 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
367 -1 /*not pulled*/, bucketStartTimeNs);
yro59cc24d2018-02-13 20:17:32 -0800368 valueProducer.setBucketSize(60 * NS_PER_SEC);
369
Yangster-mac932ecec2018-02-01 10:23:52 -0800370 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
Bookatzde1b55622017-12-14 18:38:27 -0800371
372
373 shared_ptr<LogEvent> event1
374 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
375 event1->write(161);
376 event1->write(10); // value of interest
377 event1->init();
378 shared_ptr<LogEvent> event2
379 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
380 event2->write(162);
381 event2->write(20); // value of interest
382 event2->init();
383 shared_ptr<LogEvent> event3
384 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
385 event3->write(163);
386 event3->write(130); // value of interest
387 event3->init();
388 shared_ptr<LogEvent> event4
389 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
390 event4->write(35);
391 event4->write(1); // value of interest
392 event4->init();
393 shared_ptr<LogEvent> event5
394 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
395 event5->write(45);
396 event5->write(150); // value of interest
397 event5->init();
398 shared_ptr<LogEvent> event6
399 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
400 event6->write(25);
401 event6->write(160); // value of interest
402 event6->init();
403
404 // Two events in bucket #0.
405 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
406 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz1bf94382018-01-04 11:43:20 -0800407 // Value sum == 30 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800408 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800409
410 // One event in bucket #2. No alarm as bucket #0 is trashed out.
411 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz1bf94382018-01-04 11:43:20 -0800412 // Value sum == 130 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800413 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800414
415 // Three events in bucket #3.
416 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
417 // Anomaly at event 4 since Value sum == 131 > 130!
Yangster-mac93694462018-01-22 20:49:31 -0800418 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700419 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800420 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
421 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Yangster-mac93694462018-01-22 20:49:31 -0800422 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700423 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800424
425 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
426 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Yangster-mac93694462018-01-22 20:49:31 -0800427 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700428 std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Bookatzde1b55622017-12-14 18:38:27 -0800429}
430
Chenjie Yu6736c892017-11-09 10:50:09 -0800431} // namespace statsd
432} // namespace os
433} // namespace android
434#else
435GTEST_LOG_(INFO) << "This test does nothing.\n";
436#endif