blob: 7ca66fd361c204cb700240abf3a731f78e3eee62 [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;
Yangster-macbe10ddf2018-03-13 15:39:51 -070043const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
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>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -070066 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yud9dfda72017-12-11 17:41:20 -080067 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>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700216 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
David Chen27785a82018-01-19 17:06:45 -0800217 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700218 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
219 .WillOnce(Invoke([](int tagId, int64_t timeNs,
220 vector<std::shared_ptr<LogEvent>>* data) {
David Chen27785a82018-01-19 17:06:45 -0800221 data->clear();
222 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
223 event->write("some value");
224 event->write(2);
225 event->init();
226 data->push_back(event);
227 return true;
228 }));
229
230 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
231 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800232 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
David Chen27785a82018-01-19 17:06:45 -0800233
234 vector<shared_ptr<LogEvent>> allData;
235 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
236 event->write("some value");
237 event->write(1);
238 event->init();
239 allData.push_back(event);
240 gaugeProducer.onDataPulled(allData);
241 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
242 EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
243 ->second.front()
244 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800245 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800246
247 gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
248 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
249 EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
250 EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
251 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
252 EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
253 ->second.front()
254 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800255 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800256
257 allData.clear();
258 event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
259 event->write("some value");
260 event->write(3);
261 event->init();
262 allData.push_back(event);
263 gaugeProducer.onDataPulled(allData);
264 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
265 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
266 EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
267 ->second.front()
268 .mFields->begin()
Yao Chen8a8d16c2018-02-08 14:50:40 -0800269 ->mValue.int_value);
David Chen27785a82018-01-19 17:06:45 -0800270}
271
Chenjie Yud9dfda72017-12-11 17:41:20 -0800272TEST(GaugeMetricProducerTest, TestWithCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800273 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800274 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800275 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800276 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
277 gaugeFieldMatcher->set_field(tagId);
278 gaugeFieldMatcher->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800279 metric.set_condition(StringToId("SCREEN_ON"));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800280
281 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
282
Chenjie Yud9dfda72017-12-11 17:41:20 -0800283 shared_ptr<MockStatsPullerManager> pullerManager =
284 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700285 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800286 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700287 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
288 .WillOnce(Invoke([](int tagId, int64_t timeNs,
289 vector<std::shared_ptr<LogEvent>>* data) {
Chenjie Yud9dfda72017-12-11 17:41:20 -0800290 data->clear();
291 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -0800292 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800293 event->write(100);
294 event->init();
295 data->push_back(event);
296 return true;
297 }));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800298
Yangster-maca070b6a2018-01-04 13:28:38 -0800299 GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
Chenjie Yud9dfda72017-12-11 17:41:20 -0800300 bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800301 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800302
Chenjie Yud9dfda72017-12-11 17:41:20 -0800303 gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800304 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800305 EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
306 ->second.front()
307 .mFields->begin()
308 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800309 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
310
311 vector<shared_ptr<LogEvent>> allData;
312 allData.clear();
313 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -0800314 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800315 event->write(110);
316 event->init();
317 allData.push_back(event);
318 gaugeProducer.onDataPulled(allData);
319
320 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800321 EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
322 ->second.front()
323 .mFields->begin()
324 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800325 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800326 EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
327 ->second.back()
328 .mGaugeAtoms.front()
329 .mFields->begin()
330 ->mValue.int_value);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800331
332 gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
333 gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
334 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800335 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800336 EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
337 ->second.back()
338 .mGaugeAtoms.front()
339 .mFields->begin()
340 ->mValue.int_value);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800341}
342
Yao Chen427d3722018-03-22 15:21:52 -0700343TEST(GaugeMetricProducerTest, TestWithSlicedCondition) {
344 const int conditionTag = 65;
345 GaugeMetric metric;
346 metric.set_id(1111111);
347 metric.set_bucket(ONE_MINUTE);
348 metric.mutable_gauge_fields_filter()->set_include_all(true);
349 metric.set_condition(StringToId("APP_DIED"));
350 auto dim = metric.mutable_dimensions_in_what();
351 dim->set_field(tagId);
352 dim->add_child()->set_field(1);
353
354 dim = metric.mutable_dimensions_in_condition();
355 dim->set_field(conditionTag);
356 dim->add_child()->set_field(1);
357
358 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
359 EXPECT_CALL(*wizard, query(_, _, _, _, _, _))
360 .WillRepeatedly(
361 Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
362 const vector<Matcher>& dimensionFields, const bool isSubsetDim,
363 const bool isPartialLink,
364 std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
365 dimensionKeySet->clear();
366 int pos[] = {1, 0, 0};
367 Field f(conditionTag, pos, 0);
368 HashableDimensionKey key;
369 key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
370 dimensionKeySet->insert(key);
371
372 return ConditionState::kTrue;
373 }));
374
375 shared_ptr<MockStatsPullerManager> pullerManager =
376 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700377 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Yao Chen427d3722018-03-22 15:21:52 -0700378 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700379 EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
380 .WillOnce(Invoke([](int tagId, int64_t timeNs,
381 vector<std::shared_ptr<LogEvent>>* data) {
Yao Chen427d3722018-03-22 15:21:52 -0700382 data->clear();
383 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
384 event->write(1000);
385 event->write(100);
386 event->init();
387 data->push_back(event);
388 return true;
389 }));
390
391 GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
392 pullerManager);
393 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
394
395 gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
396
397 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
398 const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
399 EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
400 EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
401
402 EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size());
403 EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value);
404
405 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
406
407 vector<shared_ptr<LogEvent>> allData;
408 allData.clear();
409 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
410 event->write(1000);
411 event->write(110);
412 event->init();
413 allData.push_back(event);
414 gaugeProducer.onDataPulled(allData);
415
416 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
417 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
418}
419
Yangster-mace2cd6d52017-11-09 20:38:30 -0800420TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800421 sp<AlarmMonitor> alarmMonitor;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800422 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
423
Chenjie Yud9dfda72017-12-11 17:41:20 -0800424 shared_ptr<MockStatsPullerManager> pullerManager =
425 make_shared<StrictMock<MockStatsPullerManager>>();
Chenjie Yu1a0a9412018-03-28 10:07:22 -0700426 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800427 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
428
Yangster-mace2cd6d52017-11-09 20:38:30 -0800429 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800430 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800431 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800432 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
433 gaugeFieldMatcher->set_field(tagId);
434 gaugeFieldMatcher->add_child()->set_field(2);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800435 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -0800436 tagId, bucketStartTimeNs, pullerManager);
yro59cc24d2018-02-13 20:17:32 -0800437 gaugeProducer.setBucketSize(60 * NS_PER_SEC);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800438
439 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800440 alert.set_id(101);
441 alert.set_metric_id(metricId);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800442 alert.set_trigger_if_sum_gt(25);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800443 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800444 const int32_t refPeriodSec = 60;
445 alert.set_refractory_period_secs(refPeriodSec);
Yangster-mac932ecec2018-02-01 10:23:52 -0800446 sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800447
Yangster-mac20877162017-12-22 17:19:39 -0800448 int tagId = 1;
449 std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
450 event1->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800451 event1->write(13);
452 event1->init();
453
454 gaugeProducer.onDataPulled({event1});
455 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800456 EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
457 ->second.front()
458 .mFields->begin()
459 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800460 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800461
462 std::shared_ptr<LogEvent> event2 =
Bookatz1bf94382018-01-04 11:43:20 -0800463 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
Yangster-mac20877162017-12-22 17:19:39 -0800464 event2->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800465 event2->write(15);
466 event2->init();
467
468 gaugeProducer.onDataPulled({event2});
469 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800470 EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
471 ->second.front()
472 .mFields->begin()
473 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800474 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700475 std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800476
477 std::shared_ptr<LogEvent> event3 =
Yangster-mac20877162017-12-22 17:19:39 -0800478 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
479 event3->write("some value");
Bookatz1bf94382018-01-04 11:43:20 -0800480 event3->write(26);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800481 event3->init();
482
483 gaugeProducer.onDataPulled({event3});
484 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yao Chen8a8d16c2018-02-08 14:50:40 -0800485 EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
486 ->second.front()
487 .mFields->begin()
488 ->mValue.int_value);
Yangster-mac93694462018-01-22 20:49:31 -0800489 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
Bookatz6bf98252018-03-14 10:44:24 -0700490 std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800491
492 // The event4 does not have the gauge field. Thus the current bucket value is 0.
493 std::shared_ptr<LogEvent> event4 =
Yangster-mac20877162017-12-22 17:19:39 -0800494 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
495 event4->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800496 event4->init();
497 gaugeProducer.onDataPulled({event4});
Chenjie Yud9dfda72017-12-11 17:41:20 -0800498 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac34ea1102018-01-29 12:40:55 -0800499 EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800500}
501
502} // namespace statsd
503} // namespace os
504} // namespace android
505#else
506GTEST_LOG_(INFO) << "This test does nothing.\n";
507#endif