blob: acbfbbac25e10573f275e8f972c93b4af10df40c [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"
Yao Chenb3561512017-11-21 18:07:17 -080016#include "metrics_test_helper.h"
Yangster-mac94e197c2018-01-02 16:03:03 -080017#include "tests/statsd_test_util.h"
Chenjie Yu6736c892017-11-09 10:50:09 -080018
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21#include <stdio.h>
22#include <vector>
23
24using namespace testing;
25using android::sp;
Yao Chenb3561512017-11-21 18:07:17 -080026using std::make_shared;
Chenjie Yu6736c892017-11-09 10:50:09 -080027using std::set;
Yao Chenb3561512017-11-21 18:07:17 -080028using std::shared_ptr;
Chenjie Yu6736c892017-11-09 10:50:09 -080029using std::unordered_map;
30using std::vector;
Chenjie Yu6736c892017-11-09 10:50:09 -080031
32#ifdef __ANDROID__
33
34namespace android {
35namespace os {
36namespace statsd {
37
Yangster-mac94e197c2018-01-02 16:03:03 -080038const ConfigKey kConfigKey(0, 12345);
Chenjie Yua7259ab2017-12-10 08:31:05 -080039const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080040const int64_t metricId = 123;
Chenjie Yua7259ab2017-12-10 08:31:05 -080041const int64_t bucketStartTimeNs = 10000000000;
42const int64_t bucketSizeNs = 60 * 1000 * 1000 * 1000LL;
43const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
44const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
45const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
46
Chenjie Yu6736c892017-11-09 10:50:09 -080047/*
48 * Tests pulled atoms with no conditions
49 */
50TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
Chenjie Yu6736c892017-11-09 10:50:09 -080051 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080052 metric.set_id(metricId);
Chenjie Yu6736c892017-11-09 10:50:09 -080053 metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
54 metric.set_value_field(2);
55
Chenjie Yu6736c892017-11-09 10:50:09 -080056 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
57 // TODO: pending refactor of StatsPullerManager
58 // For now we still need this so that it doesn't do real pulling.
Yao Chenb3561512017-11-21 18:07:17 -080059 shared_ptr<MockStatsPullerManager> pullerManager =
60 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -080061 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
62 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
63
Yao Chenb3561512017-11-21 18:07:17 -080064 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
65 tagId, bucketStartTimeNs, pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -080066
67 vector<shared_ptr<LogEvent>> allData;
68 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080069 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
70 event->write(tagId);
Yao Chen80235402017-11-13 20:42:25 -080071 event->write(11);
Chenjie Yu6736c892017-11-09 10:50:09 -080072 event->init();
73 allData.push_back(event);
74
75 valueProducer.onDataPulled(allData);
76 // has one slice
77 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
78 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -080079 // startUpdated:true tainted:0 sum:0 start:11
80 EXPECT_EQ(true, curInterval.startUpdated);
81 EXPECT_EQ(0, curInterval.tainted);
82 EXPECT_EQ(0, curInterval.sum);
83 EXPECT_EQ(11, curInterval.start);
84 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
85 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -080086
87 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -080088 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
89 event->write(tagId);
90 event->write(23);
Chenjie Yu6736c892017-11-09 10:50:09 -080091 event->init();
92 allData.push_back(event);
93 valueProducer.onDataPulled(allData);
94 // has one slice
95 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
96 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -080097 // tartUpdated:false tainted:0 sum:12
98 EXPECT_EQ(true, curInterval.startUpdated);
99 EXPECT_EQ(0, curInterval.tainted);
100 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800101 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800102 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
103 EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800104
105 allData.clear();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800106 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
107 event->write(tagId);
108 event->write(36);
Chenjie Yu6736c892017-11-09 10:50:09 -0800109 event->init();
110 allData.push_back(event);
111 valueProducer.onDataPulled(allData);
112 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
113 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800114 // startUpdated:false tainted:0 sum:12
115 EXPECT_EQ(true, curInterval.startUpdated);
116 EXPECT_EQ(0, curInterval.tainted);
117 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800118 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
Chenjie Yua7259ab2017-12-10 08:31:05 -0800119 EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
120 EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValue);
Chenjie Yu6736c892017-11-09 10:50:09 -0800121}
122
123/*
124 * Test pulled event with non sliced condition.
125 */
126TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800127 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800128 metric.set_id(metricId);
Chenjie Yu6736c892017-11-09 10:50:09 -0800129 metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
130 metric.set_value_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800131 metric.set_condition(StringToId("SCREEN_ON"));
Chenjie Yu6736c892017-11-09 10:50:09 -0800132
Chenjie Yu6736c892017-11-09 10:50:09 -0800133 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800134 shared_ptr<MockStatsPullerManager> pullerManager =
135 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800136 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
137 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
138
Yao Chenb3561512017-11-21 18:07:17 -0800139 EXPECT_CALL(*pullerManager, Pull(tagId, _))
140 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800141 data->clear();
142 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800143 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800144 event->write(100);
145 event->init();
146 data->push_back(event);
147 return true;
148 }))
149 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
Yao Chenb3561512017-11-21 18:07:17 -0800150 data->clear();
151 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
Chenjie Yua7259ab2017-12-10 08:31:05 -0800152 event->write(tagId);
Yao Chenb3561512017-11-21 18:07:17 -0800153 event->write(120);
154 event->init();
155 data->push_back(event);
156 return true;
157 }));
Chenjie Yu6736c892017-11-09 10:50:09 -0800158
Yao Chenb3561512017-11-21 18:07:17 -0800159 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
160 pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800161
Chenjie Yua7259ab2017-12-10 08:31:05 -0800162 valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Chenjie Yu6736c892017-11-09 10:50:09 -0800163
164 // has one slice
165 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
166 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800167 // startUpdated:false tainted:0 sum:0 start:100
168 EXPECT_EQ(100, curInterval.start);
169 EXPECT_EQ(true, curInterval.startUpdated);
170 EXPECT_EQ(0, curInterval.tainted);
171 EXPECT_EQ(0, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800172 EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
173
174 vector<shared_ptr<LogEvent>> allData;
175 allData.clear();
176 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yao Chen80235402017-11-13 20:42:25 -0800177 event->write(1);
178 event->write(110);
Chenjie Yu6736c892017-11-09 10:50:09 -0800179 event->init();
180 allData.push_back(event);
181 valueProducer.onDataPulled(allData);
182
183 // has one slice
184 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
185 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800186 // startUpdated:false tainted:0 sum:0 start:110
187 EXPECT_EQ(110, curInterval.start);
Chenjie Yu6736c892017-11-09 10:50:09 -0800188 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
189 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
190 EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValue);
191
192 valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
193
194 // has one slice
195 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
196 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800197 // startUpdated:false tainted:0 sum:0 start:110
198 EXPECT_EQ(10, curInterval.sum);
199 EXPECT_EQ(false, curInterval.startUpdated);
Chenjie Yu6736c892017-11-09 10:50:09 -0800200}
201
202TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800203 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800204 metric.set_id(metricId);
Chenjie Yu6736c892017-11-09 10:50:09 -0800205 metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
206 metric.set_value_field(2);
207
Chenjie Yu6736c892017-11-09 10:50:09 -0800208 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
Yao Chenb3561512017-11-21 18:07:17 -0800209 shared_ptr<MockStatsPullerManager> pullerManager =
210 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu6736c892017-11-09 10:50:09 -0800211
Yao Chenb3561512017-11-21 18:07:17 -0800212 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
213 pullerManager);
Chenjie Yu6736c892017-11-09 10:50:09 -0800214
215 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yao Chen80235402017-11-13 20:42:25 -0800216 event1->write(1);
217 event1->write(10);
Chenjie Yu6736c892017-11-09 10:50:09 -0800218 event1->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800219 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
Yao Chen80235402017-11-13 20:42:25 -0800220 event2->write(1);
221 event2->write(20);
Chenjie Yu6736c892017-11-09 10:50:09 -0800222 event2->init();
Chenjie Yua7259ab2017-12-10 08:31:05 -0800223 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
Chenjie Yu6736c892017-11-09 10:50:09 -0800224 // has one slice
225 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
226 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800227 EXPECT_EQ(10, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800228
Chenjie Yua7259ab2017-12-10 08:31:05 -0800229 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Chenjie Yu6736c892017-11-09 10:50:09 -0800230
231 // has one slice
232 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
233 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800234 EXPECT_EQ(30, curInterval.sum);
Chenjie Yu6736c892017-11-09 10:50:09 -0800235
Yangsterf2bee6f2017-11-29 12:01:05 -0800236 valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
Chenjie Yu6736c892017-11-09 10:50:09 -0800237 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
238 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
239 EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValue);
240}
241
Bookatzde1b55622017-12-14 18:38:27 -0800242TEST(ValueMetricProducerTest, TestAnomalyDetection) {
243 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800244 alert.set_id(101);
245 alert.set_metric_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800246 alert.set_trigger_if_sum_gt(130);
247 alert.set_number_of_buckets(2);
248 alert.set_refractory_period_secs(3);
Bookatzde1b55622017-12-14 18:38:27 -0800249
250 ValueMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800251 metric.set_id(metricId);
Bookatzde1b55622017-12-14 18:38:27 -0800252 metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
253 metric.set_value_field(2);
254
255 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
256 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
257 -1 /*not pulled*/, bucketStartTimeNs);
Bookatz857aaa52017-12-19 15:29:06 -0800258 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert);
Bookatzde1b55622017-12-14 18:38:27 -0800259
260
261 shared_ptr<LogEvent> event1
262 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
263 event1->write(161);
264 event1->write(10); // value of interest
265 event1->init();
266 shared_ptr<LogEvent> event2
267 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
268 event2->write(162);
269 event2->write(20); // value of interest
270 event2->init();
271 shared_ptr<LogEvent> event3
272 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
273 event3->write(163);
274 event3->write(130); // value of interest
275 event3->init();
276 shared_ptr<LogEvent> event4
277 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
278 event4->write(35);
279 event4->write(1); // value of interest
280 event4->init();
281 shared_ptr<LogEvent> event5
282 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
283 event5->write(45);
284 event5->write(150); // value of interest
285 event5->init();
286 shared_ptr<LogEvent> event6
287 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
288 event6->write(25);
289 event6->write(160); // value of interest
290 event6->init();
291
292 // Two events in bucket #0.
293 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
294 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
Bookatz857aaa52017-12-19 15:29:06 -0800295 EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL); // Value sum == 30 <= 130.
Bookatzde1b55622017-12-14 18:38:27 -0800296
297 // One event in bucket #2. No alarm as bucket #0 is trashed out.
298 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
Bookatz857aaa52017-12-19 15:29:06 -0800299 EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL); // Value sum == 130 <= 130.
Bookatzde1b55622017-12-14 18:38:27 -0800300
301 // Three events in bucket #3.
302 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
303 // Anomaly at event 4 since Value sum == 131 > 130!
Bookatz857aaa52017-12-19 15:29:06 -0800304 EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event4->GetTimestampNs());
Bookatzde1b55622017-12-14 18:38:27 -0800305 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
306 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
Bookatz857aaa52017-12-19 15:29:06 -0800307 EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event4->GetTimestampNs());
Bookatzde1b55622017-12-14 18:38:27 -0800308
309 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
310 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
Bookatz857aaa52017-12-19 15:29:06 -0800311 EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event6->GetTimestampNs());
Bookatzde1b55622017-12-14 18:38:27 -0800312}
313
Chenjie Yu6736c892017-11-09 10:50:09 -0800314} // namespace statsd
315} // namespace os
316} // namespace android
317#else
318GTEST_LOG_(INFO) << "This test does nothing.\n";
319#endif