blob: 82772d854db27a2ade3e1728628e4b849d2201a0 [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;
Bookatz8f2f3d82017-12-07 13:53:21 -080047
Chenjie Yud9dfda72017-12-11 17:41:20 -080048TEST(GaugeMetricProducerTest, TestNoCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -080049 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -080050 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -080051 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -080052 metric.mutable_gauge_fields_filter()->set_include_all(false);
53 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
54 gaugeFieldMatcher->set_field(tagId);
55 gaugeFieldMatcher->add_child()->set_field(1);
56 gaugeFieldMatcher->add_child()->set_field(3);
Yangster-mace2cd6d52017-11-09 20:38:30 -080057
58 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
59
Chenjie Yud9dfda72017-12-11 17:41:20 -080060 // TODO: pending refactor of StatsPullerManager
61 // For now we still need this so that it doesn't do real pulling.
62 shared_ptr<MockStatsPullerManager> pullerManager =
63 make_shared<StrictMock<MockStatsPullerManager>>();
64 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
65 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
Yangster-mace2cd6d52017-11-09 20:38:30 -080066
Chenjie Yud9dfda72017-12-11 17:41:20 -080067 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -080068 tagId, bucketStartTimeNs, pullerManager);
Yangster-mace2cd6d52017-11-09 20:38:30 -080069
Chenjie Yud9dfda72017-12-11 17:41:20 -080070 vector<shared_ptr<LogEvent>> allData;
71 allData.clear();
72 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -080073 event->write(10);
74 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -080075 event->write(11);
76 event->init();
77 allData.push_back(event);
Yangster-mace2cd6d52017-11-09 20:38:30 -080078
79 gaugeProducer.onDataPulled(allData);
Chenjie Yud9dfda72017-12-11 17:41:20 -080080 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -080081 auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin();
82 EXPECT_EQ(10, it->second.value_int());
83 it++;
84 EXPECT_EQ(11, it->second.value_int());
Yangster-mace2cd6d52017-11-09 20:38:30 -080085 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
86
Chenjie Yud9dfda72017-12-11 17:41:20 -080087 allData.clear();
88 std::shared_ptr<LogEvent> event2 =
89 std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -080090 event2->write(24);
91 event2->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -080092 event2->write(25);
93 event2->init();
94 allData.push_back(event2);
Yangster-mace2cd6d52017-11-09 20:38:30 -080095 gaugeProducer.onDataPulled(allData);
Yangster-mace2cd6d52017-11-09 20:38:30 -080096 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -080097 it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin();
98 EXPECT_EQ(24, it->second.value_int());
99 it++;
100 EXPECT_EQ(25, it->second.value_int());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800101 // One dimension.
102 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
103 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac20877162017-12-22 17:19:39 -0800104 it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin();
105 EXPECT_EQ(10L, it->second.value_int());
106 it++;
107 EXPECT_EQ(11L, it->second.value_int());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800108 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
109
110 gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
111 EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
112 // One dimension.
113 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
114 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac20877162017-12-22 17:19:39 -0800115 it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin();
116 EXPECT_EQ(24L, it->second.value_int());
117 it++;
118 EXPECT_EQ(25L, it->second.value_int());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800119 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800120}
121
Chenjie Yud9dfda72017-12-11 17:41:20 -0800122TEST(GaugeMetricProducerTest, TestWithCondition) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800123 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800124 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800125 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800126 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
127 gaugeFieldMatcher->set_field(tagId);
128 gaugeFieldMatcher->add_child()->set_field(2);
Yangster-mac94e197c2018-01-02 16:03:03 -0800129 metric.set_condition(StringToId("SCREEN_ON"));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800130
131 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
132
Chenjie Yud9dfda72017-12-11 17:41:20 -0800133 shared_ptr<MockStatsPullerManager> pullerManager =
134 make_shared<StrictMock<MockStatsPullerManager>>();
135 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
136 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
137 EXPECT_CALL(*pullerManager, Pull(tagId, _))
138 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
139 data->clear();
140 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
Yangster-mac20877162017-12-22 17:19:39 -0800141 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800142 event->write(100);
143 event->init();
144 data->push_back(event);
145 return true;
146 }));
Yangster-mace2cd6d52017-11-09 20:38:30 -0800147
Yangster-maca070b6a2018-01-04 13:28:38 -0800148 GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId,
Chenjie Yud9dfda72017-12-11 17:41:20 -0800149 bucketStartTimeNs, pullerManager);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800150
Chenjie Yud9dfda72017-12-11 17:41:20 -0800151 gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800152 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -0800153 EXPECT_EQ(100,
154 gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800155 EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
156
157 vector<shared_ptr<LogEvent>> allData;
158 allData.clear();
159 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
Yangster-mac20877162017-12-22 17:19:39 -0800160 event->write("some value");
Chenjie Yud9dfda72017-12-11 17:41:20 -0800161 event->write(110);
162 event->init();
163 allData.push_back(event);
164 gaugeProducer.onDataPulled(allData);
165
166 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -0800167 EXPECT_EQ(110,
168 gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800169 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yangster-mac20877162017-12-22 17:19:39 -0800170 EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()->second.back()
171 .mGaugeFields->begin()->second.value_int());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800172
173 gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
174 gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
175 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800176 EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
Yangster-mac20877162017-12-22 17:19:39 -0800177 EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()->second.back()
178 .mGaugeFields->begin()->second.value_int());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800179 EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800180}
181
182TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800183 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
184
Chenjie Yud9dfda72017-12-11 17:41:20 -0800185 shared_ptr<MockStatsPullerManager> pullerManager =
186 make_shared<StrictMock<MockStatsPullerManager>>();
187 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
188 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
189
Yangster-mace2cd6d52017-11-09 20:38:30 -0800190 GaugeMetric metric;
Yangster-mac94e197c2018-01-02 16:03:03 -0800191 metric.set_id(metricId);
Yangster-macb8144812018-01-04 10:56:23 -0800192 metric.set_bucket(ONE_MINUTE);
Yangster-mac20877162017-12-22 17:19:39 -0800193 auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
194 gaugeFieldMatcher->set_field(tagId);
195 gaugeFieldMatcher->add_child()->set_field(2);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800196 GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
Yangster-maca070b6a2018-01-04 13:28:38 -0800197 tagId, bucketStartTimeNs, pullerManager);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800198
199 Alert alert;
Yangster-mac94e197c2018-01-02 16:03:03 -0800200 alert.set_id(101);
201 alert.set_metric_id(metricId);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800202 alert.set_trigger_if_sum_gt(25);
Yangster-maca7fb12d2018-01-03 17:17:20 -0800203 alert.set_num_buckets(2);
Bookatz1bf94382018-01-04 11:43:20 -0800204 const int32_t refPeriodSec = 60;
205 alert.set_refractory_period_secs(refPeriodSec);
Bookatz857aaa52017-12-19 15:29:06 -0800206 sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800207
Yangster-mac20877162017-12-22 17:19:39 -0800208 int tagId = 1;
209 std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
210 event1->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800211 event1->write(13);
212 event1->init();
213
214 gaugeProducer.onDataPulled({event1});
215 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -0800216 EXPECT_EQ(13L,
217 gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
Bookatz1bf94382018-01-04 11:43:20 -0800218 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800219
220 std::shared_ptr<LogEvent> event2 =
Bookatz1bf94382018-01-04 11:43:20 -0800221 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
Yangster-mac20877162017-12-22 17:19:39 -0800222 event2->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800223 event2->write(15);
224 event2->init();
225
226 gaugeProducer.onDataPulled({event2});
227 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -0800228 EXPECT_EQ(15L,
229 gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
Bookatz1bf94382018-01-04 11:43:20 -0800230 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
231 event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800232
233 std::shared_ptr<LogEvent> event3 =
Yangster-mac20877162017-12-22 17:19:39 -0800234 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
235 event3->write("some value");
Bookatz1bf94382018-01-04 11:43:20 -0800236 event3->write(26);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800237 event3->init();
238
239 gaugeProducer.onDataPulled({event3});
240 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Bookatz1bf94382018-01-04 11:43:20 -0800241 EXPECT_EQ(26L,
Yangster-mac20877162017-12-22 17:19:39 -0800242 gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
Bookatz1bf94382018-01-04 11:43:20 -0800243 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
244 event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800245
246 // The event4 does not have the gauge field. Thus the current bucket value is 0.
247 std::shared_ptr<LogEvent> event4 =
Yangster-mac20877162017-12-22 17:19:39 -0800248 std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
249 event4->write("some value");
Yangster-mace2cd6d52017-11-09 20:38:30 -0800250 event4->init();
251 gaugeProducer.onDataPulled({event4});
Chenjie Yud9dfda72017-12-11 17:41:20 -0800252 EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
Yangster-mac20877162017-12-22 17:19:39 -0800253 EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second->empty());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800254}
255
256} // namespace statsd
257} // namespace os
258} // namespace android
259#else
260GTEST_LOG_(INFO) << "This test does nothing.\n";
261#endif