blob: 5ef84e6ac6ce90aa168417e20ce382c91650350c [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>
Bookatz6bf98252018-03-14 10:44:24 -070023#include <math.h>
Yangster-mace2cd6d52017-11-09 20:38:30 -080024#include <stdio.h>
25#include <vector>
26
27using namespace testing;
28using android::sp;
29using std::set;
30using std::unordered_map;
31using std::vector;
Chenjie Yud9dfda72017-12-11 17:41:20 -080032using std::make_shared;
Yangster-mace2cd6d52017-11-09 20:38:30 -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 Yud9dfda72017-12-11 17:41:20 -080041const int tagId = 1;
Yangster-mac94e197c2018-01-02 16:03:03 -080042const int64_t metricId = 123;
Chenjie Yud9dfda72017-12-11 17:41:20 -080043const int64_t bucketStartTimeNs = 10000000000;
Yangster-macb8144812018-01-04 10:56:23 -080044const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
Chenjie Yud9dfda72017-12-11 17:41:20 -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 uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
Bookatz8f2f3d82017-12-07 13:53:21 -080049
Chenjie Yud9dfda72017-12-11 17:41:20 -080050TEST(GaugeMetricProducerTest, TestNoCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -080051 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080052 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080053 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -080054 metric.mutable_gauge_fields_filter()->set_include_all(false);
55 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
56 gaugeFieldMatcher->set_field(tagId);
57 gaugeFieldMatcher->add_child()->set_field(1);
58 gaugeFieldMatcher->add_child()->set_field(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -080059
60 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
61
Chenjie Yud9dfda72017-12-11 17:41:20 -080062 // TODO: pending refactor of StatsPullerManager
63 // For now we still need this so that it doesn't do real pulling.
64 shared_ptr<MockStatsPullerManager> pullerManager =
65 make_shared<StrictMock<MockStatsPullerManager>>();
66 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
67 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Yangster-mace2cd6d52017-11-09 20:38:30 -080068
Chenjie Yud9dfda72017-12-11 17:41:20 -080069 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -080070 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -080071 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -080072
Chenjie Yud9dfda72017-12-11 17:41:20 -080073 vector<shared_ptr<LogEvent>> allData;
74 allData.clear();
75 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -080076 event->write(10);
77 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -080078 event->write(11);
79 event->init();
80 allData.push_back(event);
Yangster-mace2cd6d52017-11-09 20:38:30 -080081
82 gaugeProducer.onDataPulled(allData);
Chenjie Yud9dfda72017-12-11 17:41:20 -080083 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -080084 auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -080085 EXPECT_EQ(INT, it->mValue.getType());
86 EXPECT_EQ(10, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -080087 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -080088 EXPECT_EQ(11, it->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -080089 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
90
Chenjie Yud9dfda72017-12-11 17:41:20 -080091 allData.clear();
92 std::shared_ptr<LogEvent> event2 =
93 std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -080094 event2->write(24);
95 event2->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -080096 event2->write(25);
97 event2->init();
98 allData.push_back(event2);
Yangster-mace2cd6d52017-11-09 20:38:30 -080099 gaugeProducer.onDataPulled(allData);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800100 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800101 it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -0800102 EXPECT_EQ(INT, it->mValue.getType());
103 EXPECT_EQ(24, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -0800104 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800105 EXPECT_EQ(INT, it->mValue.getType());
106 EXPECT_EQ(25, it->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800107 // One dimension.
108 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
109 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800110 it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -0800111 EXPECT_EQ(INT, it->mValue.getType());
112 EXPECT_EQ(10L, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -0800113 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800114 EXPECT_EQ(INT, it->mValue.getType());
115 EXPECT_EQ(11L, it->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800116
117 gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
118 EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
119 // One dimension.
120 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
121 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800122 it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
Yao Chen8a8d16c2018-02-08 14:50:40 -0800123 EXPECT_EQ(INT, it->mValue.getType());
124 EXPECT_EQ(24L, it->mValue.int_value);
Yangster-mac20877162017-12-22 17:19:39 -0800125 it++;
Yao Chen8a8d16c2018-02-08 14:50:40 -0800126 EXPECT_EQ(INT, it->mValue.getType());
127 EXPECT_EQ(25L, it->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800128}
129
David Chen27785a82018-01-19 17:06:45 -0800130TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800131 sp<AlarmMonitor> alarmMonitor;
David Chen27785a82018-01-19 17:06:45 -0800132 GaugeMetric metric;
133 metric.set_id(metricId);
134 metric.set_bucket(ONE_MINUTE);
135 metric.mutable_gauge_fields_filter()->set_include_all(true);
136
137 Alert alert;
138 alert.set_id(101);
139 alert.set_metric_id(metricId);
140 alert.set_trigger_if_sum_gt(25);
141 alert.set_num_buckets(100);
142 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
143 shared_ptr<MockStatsPullerManager> pullerManager =
144 make_shared<StrictMock<MockStatsPullerManager>>();
145 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
146 -1 /* -1 means no pulling */, bucketStartTimeNs,
147 pullerManager);
Yangster-mac932ecec2018-02-01 10:23:52 -0800148
yro59cc24d2018-02-13 20:17:32 -0800149 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mac932ecec2018-02-01 10:23:52 -0800150 sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
David Chen27785a82018-01-19 17:06:45 -0800151 EXPECT_TRUE(anomalyTracker != nullptr);
152
153 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
154 event1->write(1);
155 event1->write(10);
156 event1->init();
157 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
158 EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
159
160 gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
161 EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
162 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
163 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
164 EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
165 // Partial buckets are not sent to anomaly tracker.
166 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
167
168 // Create an event in the same partial bucket.
169 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
170 event2->write(1);
171 event2->write(10);
172 event2->init();
173 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
174 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
175 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
176 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
177 // Partial buckets are not sent to anomaly tracker.
178 EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
179
180 // Next event should trigger creation of new bucket and send previous full bucket to anomaly
181 // tracker.
182 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
183 event3->write(1);
184 event3->write(10);
185 event3->init();
186 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
187 EXPECT_EQ(1UL, gaugeProducer.mCurrentBucketNum);
188 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
189 EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
190 EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
191
192 // Next event should trigger creation of new bucket.
193 shared_ptr<LogEvent> event4 =
194 make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
195 event4->write(1);
196 event4->write(10);
197 event4->init();
198 gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
199 EXPECT_EQ(2UL, gaugeProducer.mCurrentBucketNum);
200 EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
201 EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
202}
203
204TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
205 GaugeMetric metric;
206 metric.set_id(metricId);
207 metric.set_bucket(ONE_MINUTE);
208 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
209 gaugeFieldMatcher->set_field(tagId);
210 gaugeFieldMatcher->add_child()->set_field(2);
211
212 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
213
214 shared_ptr<MockStatsPullerManager> pullerManager =
215 make_shared<StrictMock<MockStatsPullerManager>>();
216 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
217 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
218 EXPECT_CALL(*pullerManager, Pull(tagId, _))
219 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
220 data->clear();
221 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
222 event->write("some value");
223 event->write(2);
224 event->init();
225 data->push_back(event);
226 return true;
227 }));
228
229 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
230 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800231 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800232
233 vector<shared_ptr<LogEvent>> allData;
234 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
235 event->write("some value");
236 event->write(1);
237 event->init();
238 allData.push_back(event);
239 gaugeProducer.onDataPulled(allData);
240 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
241 EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
242 ->second.front()
243 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800244 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800245
246 gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
247 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
248 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
249 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
250 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
251 EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
252 ->second.front()
253 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800254 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800255
256 allData.clear();
257 event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
258 event->write("some value");
259 event->write(3);
260 event->init();
261 allData.push_back(event);
262 gaugeProducer.onDataPulled(allData);
263 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
264 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
265 EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
266 ->second.front()
267 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800268 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800269}
270
Chenjie Yud9dfda72017-12-11 17:41:20 -0800271TEST(GaugeMetricProducerTest, TestWithCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800272 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800273 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800274 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800275 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
276 gaugeFieldMatcher->set_field(tagId);
277 gaugeFieldMatcher->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800278 metric.set_condition(StringToId("SCREEN_ON"));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800279
280 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
281
Chenjie Yud9dfda72017-12-11 17:41:20 -0800282 shared_ptr<MockStatsPullerManager> pullerManager =
283 make_shared<StrictMock<MockStatsPullerManager>>();
284 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
285 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
286 EXPECT_CALL(*pullerManager, Pull(tagId, _))
287 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
288 data->clear();
289 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -0800290 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800291 event->write(100);
292 event->init();
293 data->push_back(event);
294 return true;
295 }));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800296
Yangster-maca070b6a2018-01-04 13:28:38 -0800297 GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
Chenjie Yud9dfda72017-12-11 17:41:20 -0800298 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800299 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800300
Chenjie Yud9dfda72017-12-11 17:41:20 -0800301 gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800302 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800303 EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
304 ->second.front()
305 .mFields->begin()
306 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800307 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
308
309 vector<shared_ptr<LogEvent>> allData;
310 allData.clear();
311 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -0800312 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800313 event->write(110);
314 event->init();
315 allData.push_back(event);
316 gaugeProducer.onDataPulled(allData);
317
318 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800319 EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
320 ->second.front()
321 .mFields->begin()
322 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800323 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800324 EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
325 ->second.back()
326 .mGaugeAtoms.front()
327 .mFields->begin()
328 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800329
330 gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
331 gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
332 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800333 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800334 EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
335 ->second.back()
336 .mGaugeAtoms.front()
337 .mFields->begin()
338 ->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800339}
340
341TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800342 sp<AlarmMonitor> alarmMonitor;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800343 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
344
Chenjie Yud9dfda72017-12-11 17:41:20 -0800345 shared_ptr<MockStatsPullerManager> pullerManager =
346 make_shared<StrictMock<MockStatsPullerManager>>();
347 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
348 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
349
Yangster-mace2cd6d52017-11-09 20:38:30 -0800350 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800351 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800352 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800353 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
354 gaugeFieldMatcher->set_field(tagId);
355 gaugeFieldMatcher->add_child()->set_field(2);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800356 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -0800357 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800358 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800359
360 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800361 alert.set_id(101);
362 alert.set_metric_id(metricId);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800363 alert.set_trigger_if_sum_gt(25);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800364 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800365 const int32_t refPeriodSec = 60;
366 alert.set_refractory_period_secs(refPeriodSec);
Yangster-mac932ecec2018-02-01 10:23:52 -0800367 sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800368
Yangster-mac20877162017-12-22 17:19:39 -0800369 int tagId = 1;
370 std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
371 event1->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800372 event1->write(13);
373 event1->init();
374
375 gaugeProducer.onDataPulled({event1});
376 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800377 EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
378 ->second.front()
379 .mFields->begin()
380 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800381 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800382
383 std::shared_ptr<LogEvent> event2 =
Bookatz1bf94382018-01-04 11:43:20 -0800384 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
Yangster-mac20877162017-12-22 17:19:39 -0800385 event2->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800386 event2->write(15);
387 event2->init();
388
389 gaugeProducer.onDataPulled({event2});
390 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800391 EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
392 ->second.front()
393 .mFields->begin()
394 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800395 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700396 std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800397
398 std::shared_ptr<LogEvent> event3 =
Yangster-mac20877162017-12-22 17:19:39 -0800399 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
400 event3->write("some value");
Bookatz1bf94382018-01-04 11:43:20 -0800401 event3->write(26);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800402 event3->init();
403
404 gaugeProducer.onDataPulled({event3});
405 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800406 EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
407 ->second.front()
408 .mFields->begin()
409 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800410 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700411 std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800412
413 // The event4 does not have the gauge field. Thus the current bucket value is 0.
414 std::shared_ptr<LogEvent> event4 =
Yangster-mac20877162017-12-22 17:19:39 -0800415 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
416 event4->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800417 event4->init();
418 gaugeProducer.onDataPulled({event4});
Chenjie Yud9dfda72017-12-11 17:41:20 -0800419 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800420 EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800421}
422
423} // namespace statsd
424} // namespace os
425} // namespace android
426#else
427GTEST_LOG_(INFO) << "This test does nothing.\n";
428#endif