blob: c0cc0b6ad218e603bd6669bf0e8ee117997154f8 [file] [log] [blame]
Yangster-mace2cd6d52017-11-09 20:38:30 -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
Yao Chend5aa01b32017-12-19 16:46:36 -080015#include "src/metrics/GaugeMetricProducer.h"
Yangster-macb8144812018-01-04 10:56:23 -080016#include "src/stats_log_util.h"
Yangster-mace2cd6d52017-11-09 20:38:30 -080017#include "logd/LogEvent.h"
18#include "metrics_test_helper.h"
Yangster-mac94e197c2018-01-02 16:03:03 -080019#include "tests/statsd_test_util.h"
Yangster-mace2cd6d52017-11-09 20:38:30 -080020
21#include <gmock/gmock.h>
22#include <gtest/gtest.h>
23#include <stdio.h>
24#include <vector>
25
26using namespace testing;
27using android::sp;
28using std::set;
29using std::unordered_map;
30using std::vector;
Chenjie Yud9dfda72017-12-11 17:41:20 -080031using std::make_shared;
Yangster-mace2cd6d52017-11-09 20:38:30 -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 Yud9dfda72017-12-11 17:41:20 -080040const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080041const int64_t metricId = 123;
Chenjie Yud9dfda72017-12-11 17:41:20 -080042const int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080043const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Chenjie Yud9dfda72017-12-11 17:41:20 -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 uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
Bookatz8f2f3d82017-12-07 13:53:21 -080048
Chenjie Yud9dfda72017-12-11 17:41:20 -080049TEST(GaugeMetricProducerTest, TestNoCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -080050 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080051 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080052 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -080053 metric.mutable_gauge_fields_filter()->set_include_all(false);
54 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
55 gaugeFieldMatcher->set_field(tagId);
56 gaugeFieldMatcher->add_child()->set_field(1);
57 gaugeFieldMatcher->add_child()->set_field(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -080058
59 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
60
Chenjie Yud9dfda72017-12-11 17:41:20 -080061 // TODO: pending refactor of StatsPullerManager
62 // For now we still need this so that it doesn't do real pulling.
63 shared_ptr<MockStatsPullerManager> pullerManager =
64 make_shared<StrictMock<MockStatsPullerManager>>();
65 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
66 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Yangster-mace2cd6d52017-11-09 20:38:30 -080067
Chenjie Yud9dfda72017-12-11 17:41:20 -080068 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -080069 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -080070 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -080071
Chenjie Yud9dfda72017-12-11 17:41:20 -080072 vector<shared_ptr<LogEvent>> allData;
73 allData.clear();
74 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -080075 event->write(10);
76 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -080077 event->write(11);
78 event->init();
79 allData.push_back(event);
Yangster-mace2cd6d52017-11-09 20:38:30 -080080
81 gaugeProducer.onDataPulled(allData);
Chenjie Yud9dfda72017-12-11 17:41:20 -080082 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -080083 auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -080084 EXPECT_EQ(INT, it->mValue.getType());
85 EXPECT_EQ(10, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -080086 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -080087 EXPECT_EQ(11, it->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -080088 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
89
Chenjie Yud9dfda72017-12-11 17:41:20 -080090 allData.clear();
91 std::shared_ptr<LogEvent> event2 =
92 std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -080093 event2->write(24);
94 event2->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -080095 event2->write(25);
96 event2->init();
97 allData.push_back(event2);
Yangster-mace2cd6d52017-11-09 20:38:30 -080098 gaugeProducer.onDataPulled(allData);
Yangster-mace2cd6d52017-11-09 20:38:30 -080099 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800100 it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -0800101 EXPECT_EQ(INT, it->mValue.getType());
102 EXPECT_EQ(24, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -0800103 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800104 EXPECT_EQ(INT, it->mValue.getType());
105 EXPECT_EQ(25, it->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800106 // One dimension.
107 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
108 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800109 it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -0800110 EXPECT_EQ(INT, it->mValue.getType());
111 EXPECT_EQ(10L, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -0800112 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800113 EXPECT_EQ(INT, it->mValue.getType());
114 EXPECT_EQ(11L, it->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800115
116 gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
117 EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
118 // One dimension.
119 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
120 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800121 it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -0800122 EXPECT_EQ(INT, it->mValue.getType());
123 EXPECT_EQ(24L, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -0800124 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800125 EXPECT_EQ(INT, it->mValue.getType());
126 EXPECT_EQ(25L, it->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800127}
128
David Chen27785a82018-01-19 17:06:45 -0800129TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800130 sp<AlarmMonitor> alarmMonitor;
David Chen27785a82018-01-19 17:06:45 -0800131 GaugeMetric metric;
132 metric.set_id(metricId);
133 metric.set_bucket(ONE_MINUTE);
134 metric.mutable_gauge_fields_filter()->set_include_all(true);
135
136 Alert alert;
137 alert.set_id(101);
138 alert.set_metric_id(metricId);
139 alert.set_trigger_if_sum_gt(25);
140 alert.set_num_buckets(100);
141 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
142 shared_ptr<MockStatsPullerManager> pullerManager =
143 make_shared<StrictMock<MockStatsPullerManager>>();
144 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
145 -1 /* -1 means no pulling */, bucketStartTimeNs,
146 pullerManager);
Yangster-mac932ecec2018-02-01 10:23:52 -0800147
yro59cc24d2018-02-13 20:17:32 -0800148 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mac932ecec2018-02-01 10:23:52 -0800149 sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
David Chen27785a82018-01-19 17:06:45 -0800150 EXPECT_TRUE(anomalyTracker != nullptr);
151
152 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
153 event1->write(1);
154 event1->write(10);
155 event1->init();
156 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
157 EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
158
159 gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
160 EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
161 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
162 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
163 EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
164 // Partial buckets are not sent to anomaly tracker.
165 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
166
167 // Create an event in the same partial bucket.
168 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
169 event2->write(1);
170 event2->write(10);
171 event2->init();
172 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
173 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
174 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
175 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
176 // Partial buckets are not sent to anomaly tracker.
177 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
178
179 // Next event should trigger creation of new bucket and send previous full bucket to anomaly
180 // tracker.
181 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
182 event3->write(1);
183 event3->write(10);
184 event3->init();
185 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
186 EXPECT_EQ(1UL, gaugeProducer.mCurrentBucketNum);
187 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
188 EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
189 EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
190
191 // Next event should trigger creation of new bucket.
192 shared_ptr<LogEvent> event4 =
193 make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
194 event4->write(1);
195 event4->write(10);
196 event4->init();
197 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
198 EXPECT_EQ(2UL, gaugeProducer.mCurrentBucketNum);
199 EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
200 EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
201}
202
203TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
204 GaugeMetric metric;
205 metric.set_id(metricId);
206 metric.set_bucket(ONE_MINUTE);
207 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
208 gaugeFieldMatcher->set_field(tagId);
209 gaugeFieldMatcher->add_child()->set_field(2);
210
211 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
212
213 shared_ptr<MockStatsPullerManager> pullerManager =
214 make_shared<StrictMock<MockStatsPullerManager>>();
215 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
216 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
217 EXPECT_CALL(*pullerManager, Pull(tagId, _))
218 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
219 data->clear();
220 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
221 event->write("some value");
222 event->write(2);
223 event->init();
224 data->push_back(event);
225 return true;
226 }));
227
228 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
229 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800230 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800231
232 vector<shared_ptr<LogEvent>> allData;
233 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
234 event->write("some value");
235 event->write(1);
236 event->init();
237 allData.push_back(event);
238 gaugeProducer.onDataPulled(allData);
239 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
240 EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
241 ->second.front()
242 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800243 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800244
245 gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
246 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
247 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
248 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
249 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
250 EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
251 ->second.front()
252 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800253 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800254
255 allData.clear();
256 event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
257 event->write("some value");
258 event->write(3);
259 event->init();
260 allData.push_back(event);
261 gaugeProducer.onDataPulled(allData);
262 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
263 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
264 EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
265 ->second.front()
266 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800267 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800268}
269
Chenjie Yud9dfda72017-12-11 17:41:20 -0800270TEST(GaugeMetricProducerTest, TestWithCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800271 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800272 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800273 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800274 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
275 gaugeFieldMatcher->set_field(tagId);
276 gaugeFieldMatcher->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800277 metric.set_condition(StringToId("SCREEN_ON"));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800278
279 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
280
Chenjie Yud9dfda72017-12-11 17:41:20 -0800281 shared_ptr<MockStatsPullerManager> pullerManager =
282 make_shared<StrictMock<MockStatsPullerManager>>();
283 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
284 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
285 EXPECT_CALL(*pullerManager, Pull(tagId, _))
286 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
287 data->clear();
288 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -0800289 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800290 event->write(100);
291 event->init();
292 data->push_back(event);
293 return true;
294 }));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800295
Yangster-maca070b6a2018-01-04 13:28:38 -0800296 GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
Chenjie Yud9dfda72017-12-11 17:41:20 -0800297 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800298 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800299
Chenjie Yud9dfda72017-12-11 17:41:20 -0800300 gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800301 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800302 EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
303 ->second.front()
304 .mFields->begin()
305 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800306 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
307
308 vector<shared_ptr<LogEvent>> allData;
309 allData.clear();
310 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -0800311 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800312 event->write(110);
313 event->init();
314 allData.push_back(event);
315 gaugeProducer.onDataPulled(allData);
316
317 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800318 EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
319 ->second.front()
320 .mFields->begin()
321 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800322 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800323 EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
324 ->second.back()
325 .mGaugeAtoms.front()
326 .mFields->begin()
327 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800328
329 gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
330 gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
331 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800332 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800333 EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
334 ->second.back()
335 .mGaugeAtoms.front()
336 .mFields->begin()
337 ->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800338}
339
340TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800341 sp<AlarmMonitor> alarmMonitor;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800342 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
343
Chenjie Yud9dfda72017-12-11 17:41:20 -0800344 shared_ptr<MockStatsPullerManager> pullerManager =
345 make_shared<StrictMock<MockStatsPullerManager>>();
346 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
347 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
348
Yangster-mace2cd6d52017-11-09 20:38:30 -0800349 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800350 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800351 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800352 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
353 gaugeFieldMatcher->set_field(tagId);
354 gaugeFieldMatcher->add_child()->set_field(2);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800355 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -0800356 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800357 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800358
359 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800360 alert.set_id(101);
361 alert.set_metric_id(metricId);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800362 alert.set_trigger_if_sum_gt(25);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800363 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800364 const int32_t refPeriodSec = 60;
365 alert.set_refractory_period_secs(refPeriodSec);
Yangster-mac932ecec2018-02-01 10:23:52 -0800366 sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800367
Yangster-mac20877162017-12-22 17:19:39 -0800368 int tagId = 1;
369 std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
370 event1->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800371 event1->write(13);
372 event1->init();
373
374 gaugeProducer.onDataPulled({event1});
375 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800376 EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
377 ->second.front()
378 .mFields->begin()
379 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800380 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800381
382 std::shared_ptr<LogEvent> event2 =
Bookatz1bf94382018-01-04 11:43:20 -0800383 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
Yangster-mac20877162017-12-22 17:19:39 -0800384 event2->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800385 event2->write(15);
386 event2->init();
387
388 gaugeProducer.onDataPulled({event2});
389 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800390 EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
391 ->second.front()
392 .mFields->begin()
393 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800394 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Yangster-mac330af582018-02-08 15:24:38 -0800395 event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800396
397 std::shared_ptr<LogEvent> event3 =
Yangster-mac20877162017-12-22 17:19:39 -0800398 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
399 event3->write("some value");
Bookatz1bf94382018-01-04 11:43:20 -0800400 event3->write(26);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800401 event3->init();
402
403 gaugeProducer.onDataPulled({event3});
404 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800405 EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
406 ->second.front()
407 .mFields->begin()
408 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800409 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Yangster-mac330af582018-02-08 15:24:38 -0800410 event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800411
412 // The event4 does not have the gauge field. Thus the current bucket value is 0.
413 std::shared_ptr<LogEvent> event4 =
Yangster-mac20877162017-12-22 17:19:39 -0800414 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
415 event4->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800416 event4->init();
417 gaugeProducer.onDataPulled({event4});
Chenjie Yud9dfda72017-12-11 17:41:20 -0800418 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800419 EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800420}
421
422} // namespace statsd
423} // namespace os
424} // namespace android
425#else
426GTEST_LOG_(INFO) << "This test does nothing.\n";
427#endif