blob: 325a372d80562bdee1805fca562afd45535cddc8 [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);
Chenjie Yu6736c892017-11-09 10:50:09 -080069
70 vector<shared_ptr<LogEvent>> allData;
71 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080072 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
73 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -080074 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -080075 event->init();
76 allData.push_back(event);
77
78 valueProducer.onDataPulled(allData);
79 // has one slice
80 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
81 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -080082 // startUpdated:true tainted:0 sum:0 start:11
83 EXPECT_EQ(true, curInterval.startUpdated);
84 EXPECT_EQ(0, curInterval.tainted);
85 EXPECT_EQ(0, curInterval.sum);
86 EXPECT_EQ(11, curInterval.start);
87 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
88 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -080089
90 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080091 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
92 event->write(tagId);
93 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -080094 event->init();
95 allData.push_back(event);
96 valueProducer.onDataPulled(allData);
97 // has one slice
98 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
99 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800100 // tartUpdated:false tainted:0 sum:12
101 EXPECT_EQ(true, curInterval.startUpdated);
102 EXPECT_EQ(0, curInterval.tainted);
103 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800104 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800105 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
106 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800107
108 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800109 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
110 event->write(tagId);
111 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800112 event->init();
113 allData.push_back(event);
114 valueProducer.onDataPulled(allData);
115 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
116 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800117 // startUpdated:false tainted:0 sum:12
118 EXPECT_EQ(true, curInterval.startUpdated);
119 EXPECT_EQ(0, curInterval.tainted);
120 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800121 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800122 EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
123 EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800124}
125
126/*
127 * Test pulled event with non sliced condition.
128 */
129TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800130 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800131 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800132 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800133 metric.mutable_value_field()->set_field(tagId);
134 metric.mutable_value_field()->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800135 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800136
Chenjie Yu6736c892017-11-09 10:50:09 -0800137 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800138 shared_ptr<MockStatsPullerManager> pullerManager =
139 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800140 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
141 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
142
Yao Chenb3561512017-11-21 18:07:17 -0800143 EXPECT_CALL(*pullerManager, Pull(tagId, _))
144 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800145 data->clear();
146 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800147 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800148 event->write(100);
149 event->init();
150 data->push_back(event);
151 return true;
152 }))
153 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800154 data->clear();
155 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800156 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800157 event->write(120);
158 event->init();
159 data->push_back(event);
160 return true;
161 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800162
Yao Chenb3561512017-11-21 18:07:17 -0800163 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
164 pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800165
Chenjie Yua7259ab2017-12-10 08:31:05 -0800166 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800167
168 // has one slice
169 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
170 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800171 // startUpdated:false tainted:0 sum:0 start:100
172 EXPECT_EQ(100, curInterval.start);
173 EXPECT_EQ(true, curInterval.startUpdated);
174 EXPECT_EQ(0, curInterval.tainted);
175 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800176 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
177
178 vector<shared_ptr<LogEvent>> allData;
179 allData.clear();
180 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800181 event->write(1);
182 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800183 event->init();
184 allData.push_back(event);
185 valueProducer.onDataPulled(allData);
186
187 // has one slice
188 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
189 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800190 // startUpdated:false tainted:0 sum:0 start:110
191 EXPECT_EQ(110, curInterval.start);
Chenjie Yu6736c892017-11-09 10:50:09 -0800192 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
193 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
194 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
195
196 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
197
198 // has one slice
199 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
200 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800201 // startUpdated:false tainted:0 sum:0 start:110
202 EXPECT_EQ(10, curInterval.sum);
203 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yu6736c892017-11-09 10:50:09 -0800204}
205
David Chen27785a82018-01-19 17:06:45 -0800206TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
207 ValueMetric metric;
208 metric.set_id(metricId);
209 metric.set_bucket(ONE_MINUTE);
210 metric.mutable_value_field()->set_field(tagId);
211 metric.mutable_value_field()->add_child()->set_field(2);
212
213 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
214 shared_ptr<MockStatsPullerManager> pullerManager =
215 make_shared<StrictMock<MockStatsPullerManager>>();
216 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
217 pullerManager);
218
219 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
220 event1->write(1);
221 event1->write(10);
222 event1->init();
223 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
224 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
225
226 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
227 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
228 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
229
230 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
231 event2->write(1);
232 event2->write(10);
233 event2->init();
234 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
235 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
236 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
237
238 // Next value should create a new bucket.
239 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
240 event3->write(1);
241 event3->write(10);
242 event3->init();
243 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
244 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
245 EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
246}
247
248TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
249 ValueMetric metric;
250 metric.set_id(metricId);
251 metric.set_bucket(ONE_MINUTE);
252 metric.mutable_value_field()->set_field(tagId);
253 metric.mutable_value_field()->add_child()->set_field(2);
254
255 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
256 shared_ptr<MockStatsPullerManager> pullerManager =
257 make_shared<StrictMock<MockStatsPullerManager>>();
258 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
259 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
260 EXPECT_CALL(*pullerManager, Pull(tagId, _))
261 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
262 data->clear();
263 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
264 event->write(tagId);
265 event->write(120);
266 event->init();
267 data->push_back(event);
268 return true;
269 }));
270 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
271 pullerManager);
272
273 vector<shared_ptr<LogEvent>> allData;
274 allData.clear();
275 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
276 event->write(tagId);
277 event->write(100);
278 event->init();
279 allData.push_back(event);
280
281 valueProducer.onDataPulled(allData);
282 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
283
284 valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
285 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
286 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
287 EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
288
289 allData.clear();
290 event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
291 event->write(tagId);
292 event->write(150);
293 event->init();
294 allData.push_back(event);
295 valueProducer.onDataPulled(allData);
296 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
297 EXPECT_EQ((uint64_t)bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
298 EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
299}
300
Chenjie Yu6736c892017-11-09 10:50:09 -0800301TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800302 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800303 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800304 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800305 metric.mutable_value_field()->set_field(tagId);
306 metric.mutable_value_field()->add_child()->set_field(2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800307
Chenjie Yu6736c892017-11-09 10:50:09 -0800308 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800309 shared_ptr<MockStatsPullerManager> pullerManager =
310 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800311
Yao Chenb3561512017-11-21 18:07:17 -0800312 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
313 pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800314
315 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800316 event1->write(1);
317 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800318 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800319 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800320 event2->write(1);
321 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800322 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800323 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800324 // has one slice
325 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
326 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800327 EXPECT_EQ(10, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800328
Chenjie Yua7259ab2017-12-10 08:31:05 -0800329 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800330
331 // has one slice
332 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
333 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800334 EXPECT_EQ(30, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800335
Yangsterf2bee6f2017-11-29 12:01:05 -0800336 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800337 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
338 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
339 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
340}
341
Bookatzde1b55622017-12-14 18:38:27 -0800342TEST(ValueMetricProducerTest, TestAnomalyDetection) {
343 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800344 alert.set_id(101);
345 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800346 alert.set_trigger_if_sum_gt(130);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800347 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800348 const int32_t refPeriodSec = 3;
349 alert.set_refractory_period_secs(refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800350
351 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800352 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800353 metric.set_bucket(ONE_MINUTE);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800354 metric.mutable_value_field()->set_field(tagId);
355 metric.mutable_value_field()->add_child()->set_field(2);
Bookatzde1b55622017-12-14 18:38:27 -0800356
357 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
358 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
359 -1 /*not pulled*/, bucketStartTimeNs);
Bookatz857aaa52017-12-19 15:29:06 -0800360 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert);
Bookatzde1b55622017-12-14 18:38:27 -0800361
362
363 shared_ptr<LogEvent> event1
364 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
365 event1->write(161);
366 event1->write(10); // value of interest
367 event1->init();
368 shared_ptr<LogEvent> event2
369 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
370 event2->write(162);
371 event2->write(20); // value of interest
372 event2->init();
373 shared_ptr<LogEvent> event3
374 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
375 event3->write(163);
376 event3->write(130); // value of interest
377 event3->init();
378 shared_ptr<LogEvent> event4
379 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
380 event4->write(35);
381 event4->write(1); // value of interest
382 event4->init();
383 shared_ptr<LogEvent> event5
384 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
385 event5->write(45);
386 event5->write(150); // value of interest
387 event5->init();
388 shared_ptr<LogEvent> event6
389 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
390 event6->write(25);
391 event6->write(160); // value of interest
392 event6->init();
393
394 // Two events in bucket #0.
395 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
396 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz1bf94382018-01-04 11:43:20 -0800397 // Value sum == 30 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800398 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800399
400 // One event in bucket #2. No alarm as bucket #0 is trashed out.
401 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz1bf94382018-01-04 11:43:20 -0800402 // Value sum == 130 <= 130.
Yangster-mac93694462018-01-22 20:49:31 -0800403 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Bookatzde1b55622017-12-14 18:38:27 -0800404
405 // Three events in bucket #3.
406 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
407 // Anomaly at event 4 since Value sum == 131 > 130!
Yangster-mac93694462018-01-22 20:49:31 -0800408 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz1bf94382018-01-04 11:43:20 -0800409 event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800410 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
411 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Yangster-mac93694462018-01-22 20:49:31 -0800412 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz1bf94382018-01-04 11:43:20 -0800413 event4->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800414
415 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
416 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Yangster-mac93694462018-01-22 20:49:31 -0800417 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz1bf94382018-01-04 11:43:20 -0800418 event6->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
Bookatzde1b55622017-12-14 18:38:27 -0800419}
420
Chenjie Yu6736c892017-11-09 10:50:09 -0800421} // namespace statsd
422} // namespace os
423} // namespace android
424#else
425GTEST_LOG_(INFO) << "This test does nothing.\n";
426#endif