1 // 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
15 #include <android/binder_interface_utils.h>
16 #include <gtest/gtest.h>
17
18 #include <vector>
19
20 #include "src/StatsLogProcessor.h"
21 #include "src/stats_log_util.h"
22 #include "tests/statsd_test_util.h"
23
24 using ::ndk::SharedRefBase;
25
26 namespace android {
27 namespace os {
28 namespace statsd {
29
30 #ifdef __ANDROID__
31
32 namespace {
33
34 const int64_t metricId = 123456;
35 const int32_t ATOM_TAG = util::SUBSYSTEM_SLEEP_STATE;
36
CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,bool useCondition=true)37 StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,
38 bool useCondition = true) {
39 StatsdConfig config;
40 config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
41 auto atomMatcher = CreateSimpleAtomMatcher("TestMatcher", ATOM_TAG);
42 *config.add_atom_matcher() = atomMatcher;
43 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
44 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
45
46 auto screenIsOffPredicate = CreateScreenIsOffPredicate();
47 *config.add_predicate() = screenIsOffPredicate;
48
49 auto gaugeMetric = config.add_gauge_metric();
50 gaugeMetric->set_id(metricId);
51 gaugeMetric->set_what(atomMatcher.id());
52 if (useCondition) {
53 gaugeMetric->set_condition(screenIsOffPredicate.id());
54 }
55 gaugeMetric->set_sampling_type(sampling_type);
56 gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true);
57 *gaugeMetric->mutable_dimensions_in_what() =
58 CreateDimensions(ATOM_TAG, {1 /* subsystem name */});
59 gaugeMetric->set_bucket(FIVE_MINUTES);
60 gaugeMetric->set_max_pull_delay_sec(INT_MAX);
61 config.set_hash_strings_in_metric_report(false);
62 gaugeMetric->set_split_bucket_for_app_upgrade(true);
63 gaugeMetric->set_min_bucket_size_nanos(1000);
64
65 return config;
66 }
67
68 } // namespaces
69
TEST(GaugeMetricE2ePulledTest,TestRandomSamplePulledEvents)70 TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents) {
71 auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
72 int64_t baseTimeNs = getElapsedRealtimeNs();
73 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
74 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
75
76 ConfigKey cfgKey;
77 auto processor =
78 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
79 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
80 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
81 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
82 processor->mPullerManager->ForceClearPullerCache();
83
84 int startBucketNum = processor->mMetricsManagers.begin()
85 ->second->mAllMetricProducers[0]
86 ->getCurrentBucketNum();
87 EXPECT_GT(startBucketNum, (int64_t)0);
88
89 // When creating the config, the gauge metric producer should register the alarm at the
90 // end of the current bucket.
91 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
92 EXPECT_EQ(bucketSizeNs,
93 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
94 int64_t& nextPullTimeNs =
95 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
96 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
97
98 auto screenOffEvent =
99 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
100 processor->OnLogEvent(screenOffEvent.get());
101
102 // Pulling alarm arrives on time and reset the sequential pulling alarm.
103 processor->informPullAlarmFired(nextPullTimeNs + 1);
104 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
105
106 auto screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
107 android::view::DISPLAY_STATE_ON);
108 processor->OnLogEvent(screenOnEvent.get());
109
110 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 100,
111 android::view::DISPLAY_STATE_OFF);
112 processor->OnLogEvent(screenOffEvent.get());
113
114 processor->informPullAlarmFired(nextPullTimeNs + 1);
115 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
116
117 processor->informPullAlarmFired(nextPullTimeNs + 1);
118 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
119
120 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 2,
121 android::view::DISPLAY_STATE_ON);
122 processor->OnLogEvent(screenOnEvent.get());
123
124 processor->informPullAlarmFired(nextPullTimeNs + 3);
125 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
126
127 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 1,
128 android::view::DISPLAY_STATE_OFF);
129 processor->OnLogEvent(screenOffEvent.get());
130
131 processor->informPullAlarmFired(nextPullTimeNs + 2);
132 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
133
134 processor->informPullAlarmFired(nextPullTimeNs + 2);
135
136 ConfigMetricsReportList reports;
137 vector<uint8_t> buffer;
138 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
139 ADB_DUMP, FAST, &buffer);
140 EXPECT_TRUE(buffer.size() > 0);
141 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
142 backfillDimensionPath(&reports);
143 backfillStringInReport(&reports);
144 backfillStartEndTimestamp(&reports);
145 backfillAggregatedAtoms(&reports);
146 ASSERT_EQ(1, reports.reports_size());
147 ASSERT_EQ(1, reports.reports(0).metrics_size());
148 EXPECT_TRUE(reports.reports(0).metrics(0).has_estimated_data_bytes());
149 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
150 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
151 ASSERT_GT((int)gaugeMetrics.data_size(), 1);
152
153 auto data = gaugeMetrics.data(0);
154 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
155 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
156 EXPECT_EQ(1 /* subsystem name field */,
157 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
158 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
159 ASSERT_EQ(6, data.bucket_info_size());
160
161 ASSERT_EQ(1, data.bucket_info(0).atom_size());
162 ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
163 EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
164 ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
165 EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
166 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
167 EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
168 EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
169
170 ASSERT_EQ(1, data.bucket_info(1).atom_size());
171 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
172 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
173 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
174 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
175 EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
176 EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
177
178 ASSERT_EQ(1, data.bucket_info(2).atom_size());
179 ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
180 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, data.bucket_info(2).elapsed_timestamp_nanos(0));
181 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
182 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
183 EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
184 EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
185
186 ASSERT_EQ(1, data.bucket_info(3).atom_size());
187 ASSERT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
188 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1, data.bucket_info(3).elapsed_timestamp_nanos(0));
189 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
190 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
191 EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
192 EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
193
194 ASSERT_EQ(1, data.bucket_info(4).atom_size());
195 ASSERT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
196 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1, data.bucket_info(4).elapsed_timestamp_nanos(0));
197 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
198 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
199 EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
200 EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
201
202 ASSERT_EQ(1, data.bucket_info(5).atom_size());
203 ASSERT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
204 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2, data.bucket_info(5).elapsed_timestamp_nanos(0));
205 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
206 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
207 EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
208 EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
209 }
210
TEST(GaugeMetricE2ePulledTest,TestFirstNSamplesPulledNoTrigger)211 TEST(GaugeMetricE2ePulledTest, TestFirstNSamplesPulledNoTrigger) {
212 StatsdConfig config = CreateStatsdConfig(GaugeMetric::FIRST_N_SAMPLES);
213 auto gaugeMetric = config.mutable_gauge_metric(0);
214 gaugeMetric->set_max_num_gauge_atoms_per_bucket(3);
215 int64_t baseTimeNs = getElapsedRealtimeNs();
216 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
217 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
218
219 ConfigKey cfgKey;
220 auto processor =
221 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
222 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
223 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
224 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
225 processor->mPullerManager->ForceClearPullerCache();
226
227 // When creating the config, the gauge metric producer should register the alarm at the
228 // end of the current bucket.
229 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
230 EXPECT_EQ(bucketSizeNs,
231 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
232 int64_t& nextPullTimeNs =
233 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
234
235 auto screenOffEvent =
236 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
237 processor->OnLogEvent(screenOffEvent.get());
238
239 auto screenOnEvent =
240 CreateScreenStateChangedEvent(configAddedTimeNs + 100, android::view::DISPLAY_STATE_ON);
241 processor->OnLogEvent(screenOnEvent.get());
242
243 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 150,
244 android::view::DISPLAY_STATE_OFF);
245 processor->OnLogEvent(screenOffEvent.get());
246
247 screenOnEvent =
248 CreateScreenStateChangedEvent(configAddedTimeNs + 200, android::view::DISPLAY_STATE_ON);
249 processor->OnLogEvent(screenOnEvent.get());
250
251 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 250,
252 android::view::DISPLAY_STATE_OFF);
253 processor->OnLogEvent(screenOffEvent.get());
254
255 screenOnEvent =
256 CreateScreenStateChangedEvent(configAddedTimeNs + 300, android::view::DISPLAY_STATE_ON);
257 processor->OnLogEvent(screenOnEvent.get());
258
259 // Not logged. max_num_gauge_atoms_per_bucket already hit.
260 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 325,
261 android::view::DISPLAY_STATE_OFF);
262 processor->OnLogEvent(screenOffEvent.get());
263
264 // Pulling alarm arrives on time and reset the sequential pulling alarm.
265 processor->informPullAlarmFired(nextPullTimeNs + 1);
266
267 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
268 android::view::DISPLAY_STATE_ON);
269 processor->OnLogEvent(screenOnEvent.get());
270
271 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 100,
272 android::view::DISPLAY_STATE_OFF);
273 processor->OnLogEvent(screenOffEvent.get());
274
275 processor->informPullAlarmFired(nextPullTimeNs + 2);
276
277 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + (3 * bucketSizeNs) + 15,
278 android::view::DISPLAY_STATE_ON);
279 processor->OnLogEvent(screenOnEvent.get());
280
281 processor->informPullAlarmFired(nextPullTimeNs + 4);
282
283 ConfigMetricsReportList reports;
284 vector<uint8_t> buffer;
285 processor->onDumpReport(cfgKey, configAddedTimeNs + (4 * bucketSizeNs) + 10, false, true,
286 ADB_DUMP, FAST, &buffer);
287 EXPECT_TRUE(buffer.size() > 0);
288 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
289 backfillDimensionPath(&reports);
290 backfillStringInReport(&reports);
291 backfillStartEndTimestamp(&reports);
292 backfillAggregatedAtoms(&reports);
293 ASSERT_EQ(1, reports.reports_size());
294 ASSERT_EQ(1, reports.reports(0).metrics_size());
295 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
296 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
297 ASSERT_GT((int)gaugeMetrics.data_size(), 1);
298
299 auto data = gaugeMetrics.data(1);
300 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
301 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
302 EXPECT_EQ(1 /* subsystem name field */,
303 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
304 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
305 ASSERT_EQ(3, data.bucket_info_size());
306
307 ASSERT_EQ(3, data.bucket_info(0).atom_size());
308 ASSERT_EQ(3, data.bucket_info(0).elapsed_timestamp_nanos_size());
309 ValidateGaugeBucketTimes(data.bucket_info(0),
310 /*startTimeNs=*/configAddedTimeNs,
311 /*endTimeNs=*/configAddedTimeNs + bucketSizeNs,
312 /*eventTimesNs=*/
313 {(int64_t)(configAddedTimeNs + 55), (int64_t)(configAddedTimeNs + 150),
314 (int64_t)(configAddedTimeNs + 250)});
315
316 ASSERT_EQ(2, data.bucket_info(1).atom_size());
317 ASSERT_EQ(2, data.bucket_info(1).elapsed_timestamp_nanos_size());
318 ValidateGaugeBucketTimes(data.bucket_info(1),
319 /*startTimeNs=*/configAddedTimeNs + bucketSizeNs,
320 /*endTimeNs=*/configAddedTimeNs + (2 * bucketSizeNs),
321 /*eventTimesNs=*/
322 {(int64_t)(configAddedTimeNs + bucketSizeNs + 1),
323 (int64_t)(configAddedTimeNs + bucketSizeNs + 100)});
324
325 ASSERT_EQ(1, data.bucket_info(2).atom_size());
326 ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
327 ValidateGaugeBucketTimes(
328 data.bucket_info(2), /*startTimeNs=*/configAddedTimeNs + (2 * bucketSizeNs),
329 /*endTimeNs=*/configAddedTimeNs + (3 * bucketSizeNs),
330 /*eventTimesNs=*/{(int64_t)(configAddedTimeNs + (2 * bucketSizeNs) + 2)});
331 }
332
TEST(GaugeMetricE2ePulledTest,TestConditionChangeToTrueSamplePulledEvents)333 TEST(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents) {
334 auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
335 int64_t baseTimeNs = getElapsedRealtimeNs();
336 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
337 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
338
339 ConfigKey cfgKey;
340 auto processor =
341 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
342 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
343 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
344 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
345 processor->mPullerManager->ForceClearPullerCache();
346
347 int startBucketNum = processor->mMetricsManagers.begin()
348 ->second->mAllMetricProducers[0]
349 ->getCurrentBucketNum();
350 EXPECT_GT(startBucketNum, (int64_t)0);
351
352 auto screenOffEvent =
353 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
354 processor->OnLogEvent(screenOffEvent.get());
355
356 auto screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
357 android::view::DISPLAY_STATE_ON);
358 processor->OnLogEvent(screenOnEvent.get());
359
360 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 100,
361 android::view::DISPLAY_STATE_OFF);
362 processor->OnLogEvent(screenOffEvent.get());
363
364 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 2,
365 android::view::DISPLAY_STATE_ON);
366 processor->OnLogEvent(screenOnEvent.get());
367
368 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 1,
369 android::view::DISPLAY_STATE_OFF);
370 processor->OnLogEvent(screenOffEvent.get());
371 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 3,
372 android::view::DISPLAY_STATE_ON);
373 processor->OnLogEvent(screenOnEvent.get());
374 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 5 * bucketSizeNs + 10,
375 android::view::DISPLAY_STATE_OFF);
376 processor->OnLogEvent(screenOffEvent.get());
377
378 ConfigMetricsReportList reports;
379 vector<uint8_t> buffer;
380 processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
381 ADB_DUMP, FAST, &buffer);
382 EXPECT_TRUE(buffer.size() > 0);
383 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
384 backfillDimensionPath(&reports);
385 backfillStringInReport(&reports);
386 backfillStartEndTimestamp(&reports);
387 backfillAggregatedAtoms(&reports);
388 ASSERT_EQ(1, reports.reports_size());
389 ASSERT_EQ(1, reports.reports(0).metrics_size());
390 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
391 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
392 ASSERT_GT((int)gaugeMetrics.data_size(), 1);
393
394 auto data = gaugeMetrics.data(0);
395 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
396 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
397 EXPECT_EQ(1 /* subsystem name field */,
398 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
399 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
400 ASSERT_EQ(3, data.bucket_info_size());
401
402 ASSERT_EQ(1, data.bucket_info(0).atom_size());
403 ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
404 EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
405 ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
406 EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
407 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
408 EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
409 EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
410
411 ASSERT_EQ(1, data.bucket_info(1).atom_size());
412 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100, data.bucket_info(1).elapsed_timestamp_nanos(0));
413 EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
414 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
415 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
416 EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
417 EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
418
419 ASSERT_EQ(2, data.bucket_info(2).atom_size());
420 ASSERT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
421 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1, data.bucket_info(2).elapsed_timestamp_nanos(0));
422 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10, data.bucket_info(2).elapsed_timestamp_nanos(1));
423 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
424 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
425 EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
426 EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
427 EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
428 EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
429 }
430
TEST(GaugeMetricE2ePulledTest,TestRandomSamplePulledEvent_LateAlarm)431 TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm) {
432 auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
433 int64_t baseTimeNs = getElapsedRealtimeNs();
434 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
435 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
436
437 ConfigKey cfgKey;
438 auto processor =
439 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
440 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
441 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
442 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
443 processor->mPullerManager->ForceClearPullerCache();
444
445 int startBucketNum = processor->mMetricsManagers.begin()
446 ->second->mAllMetricProducers[0]
447 ->getCurrentBucketNum();
448 EXPECT_GT(startBucketNum, (int64_t)0);
449
450 // When creating the config, the gauge metric producer should register the alarm at the
451 // end of the current bucket.
452 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
453 EXPECT_EQ(bucketSizeNs,
454 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
455 int64_t& nextPullTimeNs =
456 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
457 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
458
459 auto screenOffEvent =
460 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
461 processor->OnLogEvent(screenOffEvent.get());
462
463 auto screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 10,
464 android::view::DISPLAY_STATE_ON);
465 processor->OnLogEvent(screenOnEvent.get());
466
467 // Pulling alarm arrives one bucket size late.
468 processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
469 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
470
471 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 11,
472 android::view::DISPLAY_STATE_OFF);
473 processor->OnLogEvent(screenOffEvent.get());
474
475 // Pulling alarm arrives more than one bucket size late.
476 processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
477 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
478
479 ConfigMetricsReportList reports;
480 vector<uint8_t> buffer;
481 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
482 ADB_DUMP, FAST, &buffer);
483 EXPECT_TRUE(buffer.size() > 0);
484 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
485 backfillDimensionPath(&reports);
486 backfillStringInReport(&reports);
487 backfillStartEndTimestamp(&reports);
488 backfillAggregatedAtoms(&reports);
489 ASSERT_EQ(1, reports.reports_size());
490 ASSERT_EQ(1, reports.reports(0).metrics_size());
491 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
492 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
493 ASSERT_GT((int)gaugeMetrics.data_size(), 1);
494
495 auto data = gaugeMetrics.data(0);
496 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
497 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
498 EXPECT_EQ(1 /* subsystem name field */,
499 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
500 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
501 ASSERT_EQ(3, data.bucket_info_size());
502
503 ASSERT_EQ(1, data.bucket_info(0).atom_size());
504 ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
505 EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
506 EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
507 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
508 EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
509 EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
510
511 ASSERT_EQ(1, data.bucket_info(1).atom_size());
512 EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
513 data.bucket_info(1).elapsed_timestamp_nanos(0));
514 EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
515 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
516 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
517 EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
518 EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
519
520 ASSERT_EQ(1, data.bucket_info(2).atom_size());
521 ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
522 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12, data.bucket_info(2).elapsed_timestamp_nanos(0));
523 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
524 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
525 EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
526 EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
527 }
528
TEST(GaugeMetricE2ePulledTest,TestRandomSamplePulledEventsWithActivation)529 TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation) {
530 auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
531
532 int64_t baseTimeNs = getElapsedRealtimeNs();
533 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
534 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
535
536 auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
537 *config.add_atom_matcher() = batterySaverStartMatcher;
538 const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
539 auto metric_activation = config.add_metric_activation();
540 metric_activation->set_metric_id(metricId);
541 metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
542 auto event_activation = metric_activation->add_event_activation();
543 event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
544 event_activation->set_ttl_seconds(ttlNs / 1000000000);
545
546 StatsdStats::getInstance().reset();
547
548 ConfigKey cfgKey;
549 auto processor =
550 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
551 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
552 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
553 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
554 processor->mPullerManager->ForceClearPullerCache();
555
556 const int startBucketNum = processor->mMetricsManagers.begin()
557 ->second->mAllMetricProducers[0]
558 ->getCurrentBucketNum();
559 EXPECT_EQ(startBucketNum, 2);
560 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
561
562 // When creating the config, the gauge metric producer should register the alarm at the
563 // end of the current bucket.
564 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
565 EXPECT_EQ(bucketSizeNs,
566 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
567 int64_t& nextPullTimeNs =
568 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
569 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
570
571 // Check no pull occurred on metric initialization when it's not active.
572 const int64_t metricInitTimeNs = configAddedTimeNs + 1; // 10 mins + 1 ns.
573 processor->onStatsdInitCompleted(metricInitTimeNs);
574 StatsdStatsReport_PulledAtomStats pulledAtomStats =
575 getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
576 EXPECT_EQ(pulledAtomStats.atom_id(), ATOM_TAG);
577 EXPECT_EQ(pulledAtomStats.total_pull(), 0);
578
579 // Check no pull occurred on app upgrade when metric is not active.
580 const int64_t appUpgradeTimeNs = metricInitTimeNs + 1; // 10 mins + 2 ns.
581 processor->notifyAppUpgrade(appUpgradeTimeNs, "appName", 1000 /* uid */, 2 /* version */);
582 pulledAtomStats = getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
583 EXPECT_EQ(pulledAtomStats.atom_id(), ATOM_TAG);
584 EXPECT_EQ(pulledAtomStats.total_pull(), 0);
585
586 // Check skipped bucket is not added when metric is not active.
587 int64_t dumpReportTimeNs = appUpgradeTimeNs + 1; // 10 mins + 3 ns.
588 vector<uint8_t> buffer;
589 processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
590 true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
591 ConfigMetricsReportList reports;
592 EXPECT_TRUE(buffer.size() > 0);
593 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
594 ASSERT_EQ(1, reports.reports_size());
595 ASSERT_EQ(1, reports.reports(0).metrics_size());
596 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics =
597 reports.reports(0).metrics(0).gauge_metrics();
598 EXPECT_EQ(gaugeMetrics.skipped_size(), 0);
599
600 // Pulling alarm arrives on time and reset the sequential pulling alarm.
601 // Event should not be kept.
602 processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
603 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
604 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
605
606 // Activate the metric. A pull occurs upon activation. The event is kept. 1 total
607 // 15 mins + 2 ms
608 const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
609 auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
610 processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
611 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
612
613 // This event should be kept. 2 total.
614 processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
615 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
616
617 // This event should be kept. 3 total.
618 processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
619 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
620
621 // Create random event to deactivate metric.
622 // A pull should not occur here. 3 total.
623 // 25 mins + 2 ms + 1 ns.
624 const int64_t deactivationNs = activationNs + ttlNs + 1;
625 auto deactivationEvent = CreateScreenBrightnessChangedEvent(deactivationNs, 50);
626 processor->OnLogEvent(deactivationEvent.get());
627 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
628
629 // Event should not be kept. 3 total.
630 // 30 mins + 3 ns.
631 processor->informPullAlarmFired(nextPullTimeNs + 3);
632 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
633
634 // Event should not be kept. 3 total.
635 // 35 mins + 2 ns.
636 processor->informPullAlarmFired(nextPullTimeNs + 2);
637 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
638
639 buffer.clear();
640 // 40 mins + 10 ns.
641 processor->onDumpReport(cfgKey, configAddedTimeNs + 6 * bucketSizeNs + 10,
642 false /* include_current_partial_bucket */, true /* erase_data */,
643 ADB_DUMP, FAST, &buffer);
644 EXPECT_TRUE(buffer.size() > 0);
645 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
646 backfillDimensionPath(&reports);
647 backfillStringInReport(&reports);
648 backfillStartEndTimestamp(&reports);
649 backfillAggregatedAtoms(&reports);
650 ASSERT_EQ(1, reports.reports_size());
651 ASSERT_EQ(1, reports.reports(0).metrics_size());
652 gaugeMetrics = StatsLogReport::GaugeMetricDataWrapper();
653 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
654 ASSERT_GT((int)gaugeMetrics.data_size(), 0);
655
656 auto data = gaugeMetrics.data(0);
657 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
658 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
659 EXPECT_EQ(1 /* subsystem name field */,
660 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
661 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
662 ASSERT_EQ(3, data.bucket_info_size());
663
664 auto bucketInfo = data.bucket_info(0);
665 ASSERT_EQ(1, bucketInfo.atom_size());
666 ASSERT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
667 EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
668 ASSERT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
669 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
670 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
671 EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
672 EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
673
674 bucketInfo = data.bucket_info(1);
675 ASSERT_EQ(1, bucketInfo.atom_size());
676 ASSERT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
677 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
678 ASSERT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
679 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
680 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
681 EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
682 EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
683
684 bucketInfo = data.bucket_info(2);
685 ASSERT_EQ(1, bucketInfo.atom_size());
686 ASSERT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
687 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
688 ASSERT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
689 EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
690 bucketInfo.start_bucket_elapsed_nanos());
691 EXPECT_EQ(MillisToNano(NanoToMillis(deactivationNs)), bucketInfo.end_bucket_elapsed_nanos());
692 EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
693 EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
694
695 // Check skipped bucket is not added after deactivation.
696 dumpReportTimeNs = configAddedTimeNs + 8 * bucketSizeNs + 10;
697 buffer.clear();
698 processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
699 true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
700 EXPECT_TRUE(buffer.size() > 0);
701 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
702 ASSERT_EQ(1, reports.reports_size());
703 ASSERT_EQ(1, reports.reports(0).metrics_size());
704 gaugeMetrics = reports.reports(0).metrics(0).gauge_metrics();
705 EXPECT_EQ(gaugeMetrics.skipped_size(), 0);
706 }
707
TEST(GaugeMetricE2ePulledTest,TestFirstNSamplesPulledNoTriggerWithActivation)708 TEST(GaugeMetricE2ePulledTest, TestFirstNSamplesPulledNoTriggerWithActivation) {
709 StatsdConfig config = CreateStatsdConfig(GaugeMetric::FIRST_N_SAMPLES);
710 auto gaugeMetric = config.mutable_gauge_metric(0);
711 gaugeMetric->set_max_num_gauge_atoms_per_bucket(2);
712 int64_t baseTimeNs = getElapsedRealtimeNs();
713 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
714 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
715
716 auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
717 *config.add_atom_matcher() = batterySaverStartMatcher;
718 const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
719 auto metric_activation = config.add_metric_activation();
720 metric_activation->set_metric_id(metricId);
721 metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
722 auto event_activation = metric_activation->add_event_activation();
723 event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
724 event_activation->set_ttl_seconds(ttlNs / NS_PER_SEC);
725
726 StatsdStats::getInstance().reset();
727
728 ConfigKey cfgKey;
729 auto processor =
730 CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
731 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
732 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
733 processor->mPullerManager->ForceClearPullerCache();
734
735 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
736
737 // When creating the config, the gauge metric producer should register the alarm at the
738 // end of the current bucket.
739 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
740 EXPECT_EQ(bucketSizeNs,
741 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
742 int64_t& nextPullTimeNs =
743 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
744
745 // Condition true but Active false
746 auto screenOffEvent =
747 CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF);
748 processor->OnLogEvent(screenOffEvent.get());
749
750 auto screenOnEvent =
751 CreateScreenStateChangedEvent(configAddedTimeNs + 100, android::view::DISPLAY_STATE_ON);
752 processor->OnLogEvent(screenOnEvent.get());
753
754 // Pulling alarm arrives on time and reset the sequential pulling alarm.
755 // Event should not be kept.
756 processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
757 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
758
759 // Activate the metric. A pull occurs upon activation. The event is not kept. 0 total
760 // 15 mins + 1000 ns.
761 const int64_t activationNs = configAddedTimeNs + bucketSizeNs + 1000;
762 auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
763 processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 1000 ns.
764 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
765
766 // A pull occurs upon condition change. The event is kept. 1 total. 1 in bucket
767 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 150,
768 android::view::DISPLAY_STATE_OFF);
769 processor->OnLogEvent(screenOffEvent.get());
770
771 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 200,
772 android::view::DISPLAY_STATE_ON);
773 processor->OnLogEvent(screenOnEvent.get());
774
775 // A pull occurs upon condition change. The event is kept. 1 total. 2 in bucket
776 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 250,
777 android::view::DISPLAY_STATE_OFF);
778 processor->OnLogEvent(screenOffEvent.get());
779
780 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 300,
781 android::view::DISPLAY_STATE_ON);
782 processor->OnLogEvent(screenOnEvent.get());
783
784 // A pull occurs upon condition change. The event is not kept due to
785 // max_num_gauge_atoms_per_bucket. 1 total. 2 total in bucket
786 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 325,
787 android::view::DISPLAY_STATE_OFF);
788 processor->OnLogEvent(screenOffEvent.get());
789
790 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + bucketSizeNs + 375,
791 android::view::DISPLAY_STATE_ON);
792 processor->OnLogEvent(screenOnEvent.get());
793 // Condition false but Active true
794
795 // This event should not be kept. 1 total.
796 processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
797
798 // This event should not be kept. 1 total.
799 processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
800
801 // A pull occurs upon condition change. The event is kept. 2 total. 1 in bucket
802 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 50,
803 android::view::DISPLAY_STATE_OFF);
804 processor->OnLogEvent(screenOffEvent.get());
805 // Condition true but Active true
806
807 // Create random event to deactivate metric.
808 // A pull should not occur here. 2 total. 1 in bucket.
809 // 25 mins + 1000 ns + 1 ns.
810 const int64_t deactivationNs = activationNs + ttlNs + 1;
811 auto deactivationEvent = CreateScreenBrightnessChangedEvent(deactivationNs, 50);
812 processor->OnLogEvent(deactivationEvent.get());
813 EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
814 // Condition true but Active false
815
816 screenOnEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 50,
817 android::view::DISPLAY_STATE_ON);
818 processor->OnLogEvent(screenOnEvent.get());
819
820 screenOffEvent = CreateScreenStateChangedEvent(configAddedTimeNs + 3 * bucketSizeNs + 100,
821 android::view::DISPLAY_STATE_OFF);
822 processor->OnLogEvent(screenOffEvent.get());
823
824 vector<uint8_t> buffer;
825 // 30 mins + 10 ns.
826 processor->onDumpReport(cfgKey, configAddedTimeNs + 4 * bucketSizeNs + 10,
827 false /* include_current_partial_bucket */, true /* erase_data */,
828 ADB_DUMP, FAST, &buffer);
829 ConfigMetricsReportList reports;
830 EXPECT_TRUE(buffer.size() > 0);
831 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
832 backfillDimensionPath(&reports);
833 backfillStringInReport(&reports);
834 backfillStartEndTimestamp(&reports);
835 backfillAggregatedAtoms(&reports);
836 ASSERT_EQ(1, reports.reports_size());
837 ASSERT_EQ(1, reports.reports(0).metrics_size());
838 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics = StatsLogReport::GaugeMetricDataWrapper();
839 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
840 ASSERT_GT((int)gaugeMetrics.data_size(), 0);
841
842 auto data = gaugeMetrics.data(0);
843 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
844 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
845 EXPECT_EQ(1 /* subsystem name field */,
846 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
847 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
848 ASSERT_EQ(2, data.bucket_info_size());
849
850 ASSERT_EQ(2, data.bucket_info(0).atom_size());
851 ASSERT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
852 ValidateGaugeBucketTimes(data.bucket_info(0),
853 /*startTimeNs=*/configAddedTimeNs + bucketSizeNs,
854 /*endTimeNs=*/configAddedTimeNs + (2 * bucketSizeNs),
855 /*eventTimesNs=*/
856 {(int64_t)(configAddedTimeNs + bucketSizeNs + 150),
857 (int64_t)(configAddedTimeNs + bucketSizeNs + 250)});
858
859 ASSERT_EQ(1, data.bucket_info(1).atom_size());
860 ASSERT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
861 ValidateGaugeBucketTimes(data.bucket_info(1),
862 /*startTimeNs=*/
863 MillisToNano(NanoToMillis(configAddedTimeNs + (3 * bucketSizeNs))),
864 /*endTimeNs=*/MillisToNano(NanoToMillis(deactivationNs)),
865 /*eventTimesNs=*/
866 {(int64_t)(configAddedTimeNs + (3 * bucketSizeNs) + 50)});
867 }
868
TEST(GaugeMetricE2ePulledTest,TestRandomSamplePulledEventsNoCondition)869 TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition) {
870 auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
871
872 int64_t baseTimeNs = getElapsedRealtimeNs();
873 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
874 int64_t bucketSizeNs =
875 TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
876
877 ConfigKey cfgKey;
878 auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
879 SharedRefBase::make<FakeSubsystemSleepCallback>(),
880 ATOM_TAG);
881 ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
882 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
883 processor->mPullerManager->ForceClearPullerCache();
884
885 int startBucketNum = processor->mMetricsManagers.begin()->second->
886 mAllMetricProducers[0]->getCurrentBucketNum();
887 EXPECT_GT(startBucketNum, (int64_t)0);
888
889 // When creating the config, the gauge metric producer should register the alarm at the
890 // end of the current bucket.
891 ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
892 EXPECT_EQ(bucketSizeNs,
893 processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
894 int64_t& nextPullTimeNs =
895 processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
896 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
897
898 // Pulling alarm arrives on time and reset the sequential pulling alarm.
899 processor->informPullAlarmFired(nextPullTimeNs + 1);
900 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
901
902 processor->informPullAlarmFired(nextPullTimeNs + 4);
903 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
904 nextPullTimeNs);
905
906 ConfigMetricsReportList reports;
907 vector<uint8_t> buffer;
908 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
909 ADB_DUMP, FAST, &buffer);
910 EXPECT_TRUE(buffer.size() > 0);
911 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
912 backfillDimensionPath(&reports);
913 backfillStringInReport(&reports);
914 backfillStartEndTimestamp(&reports);
915 backfillAggregatedAtoms(&reports);
916 ASSERT_EQ(1, reports.reports_size());
917 ASSERT_EQ(1, reports.reports(0).metrics_size());
918 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
919 sortMetricDataByDimensionsValue(
920 reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
921 ASSERT_GT((int)gaugeMetrics.data_size(), 0);
922
923 auto data = gaugeMetrics.data(0);
924 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
925 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
926 EXPECT_EQ(1 /* subsystem name field */,
927 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
928 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
929 ASSERT_EQ(3, data.bucket_info_size());
930
931 ASSERT_EQ(1, data.bucket_info(0).atom_size());
932 ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
933 EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).elapsed_timestamp_nanos(0));
934 ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
935 EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
936 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
937 EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
938 EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
939
940 ASSERT_EQ(1, data.bucket_info(1).atom_size());
941 ASSERT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
942 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
943 ASSERT_EQ(0, data.bucket_info(1).wall_clock_timestamp_nanos_size());
944 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
945 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
946 EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
947 EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
948
949 ASSERT_EQ(1, data.bucket_info(2).atom_size());
950 ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
951 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 4, data.bucket_info(2).elapsed_timestamp_nanos(0));
952 ASSERT_EQ(0, data.bucket_info(2).wall_clock_timestamp_nanos_size());
953 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
954 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
955 EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
956 EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
957 }
958
TEST(GaugeMetricE2ePulledTest,TestGaugeMetricPullProbabilityWithTriggerEvent)959 TEST(GaugeMetricE2ePulledTest, TestGaugeMetricPullProbabilityWithTriggerEvent) {
960 // Initiating StatsdStats at the start of this test, so it doesn't call rand() during the test.
961 StatsdStats::getInstance();
962 // Set srand seed to make rand deterministic for testing.
963 srand(0);
964
965 auto config = CreateStatsdConfig(GaugeMetric::FIRST_N_SAMPLES, /*useCondition=*/false);
966 auto gaugeMetric = config.mutable_gauge_metric(0);
967 gaugeMetric->set_pull_probability(50);
968 auto triggerEventMatcher = CreateScreenTurnedOnAtomMatcher();
969 gaugeMetric->set_trigger_event(triggerEventMatcher.id());
970 gaugeMetric->set_max_num_gauge_atoms_per_bucket(200);
971 gaugeMetric->set_bucket(ONE_HOUR);
972
973 int64_t configAddedTimeNs = 60 * NS_PER_SEC;
974 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
975
976 ConfigKey cfgKey;
977 auto processor =
978 CreateStatsLogProcessor(configAddedTimeNs, configAddedTimeNs, config, cfgKey,
979 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
980
981 std::vector<std::unique_ptr<LogEvent>> events;
982 // First bucket events.
983 for (int i = 0; i < 30; i++) {
984 events.push_back(CreateScreenStateChangedEvent(configAddedTimeNs + (i * 10 * NS_PER_SEC),
985 android::view::DISPLAY_STATE_ON));
986 }
987 // Second bucket events.
988 for (int i = 0; i < 30; i++) {
989 events.push_back(CreateScreenStateChangedEvent(
990 configAddedTimeNs + bucketSizeNs + (i * 10 * NS_PER_SEC),
991 android::view::DISPLAY_STATE_ON));
992 }
993
994 // Send log events to StatsLogProcessor.
995 for (auto& event : events) {
996 processor->OnLogEvent(event.get());
997 }
998
999 ConfigMetricsReportList reports;
1000 vector<uint8_t> buffer;
1001 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
1002 ADB_DUMP, FAST, &buffer);
1003
1004 EXPECT_TRUE(buffer.size() > 0);
1005 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1006 backfillDimensionPath(&reports);
1007 backfillStringInReport(&reports);
1008 backfillStartEndTimestamp(&reports);
1009 backfillAggregatedAtoms(&reports);
1010 ASSERT_EQ(1, reports.reports_size());
1011 ASSERT_EQ(1, reports.reports(0).metrics_size());
1012 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
1013 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
1014 ASSERT_EQ((int)gaugeMetrics.data_size(), 2); // 2 sets of data for each pull.
1015
1016 // Data 1
1017 auto data = gaugeMetrics.data(0);
1018 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
1019 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1020 EXPECT_EQ(1 /* subsystem name field */,
1021 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1022 EXPECT_EQ("subsystem_name_1",
1023 data.dimensions_in_what().value_tuple().dimensions_value(0).value_str());
1024 ASSERT_EQ(2, data.bucket_info_size());
1025
1026 // Data 1, Bucket 1
1027 ASSERT_EQ(13, data.bucket_info(0).atom_size());
1028 ValidateGaugeBucketTimes(
1029 data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1030 {(int64_t)60 * NS_PER_SEC, (int64_t)80 * NS_PER_SEC, (int64_t)90 * NS_PER_SEC,
1031 (int64_t)130 * NS_PER_SEC, (int64_t)150 * NS_PER_SEC, (int64_t)170 * NS_PER_SEC,
1032 (int64_t)190 * NS_PER_SEC, (int64_t)200 * NS_PER_SEC, (int64_t)240 * NS_PER_SEC,
1033 (int64_t)250 * NS_PER_SEC, (int64_t)300 * NS_PER_SEC, (int64_t)330 * NS_PER_SEC,
1034 (int64_t)340 * NS_PER_SEC});
1035
1036 // Data 1, Bucket 2
1037 ASSERT_EQ(18, data.bucket_info(1).atom_size());
1038 ValidateGaugeBucketTimes(
1039 data.bucket_info(1), configAddedTimeNs + bucketSizeNs,
1040 configAddedTimeNs + 2 * bucketSizeNs,
1041 {(int64_t)3660 * NS_PER_SEC, (int64_t)3680 * NS_PER_SEC, (int64_t)3700 * NS_PER_SEC,
1042 (int64_t)3710 * NS_PER_SEC, (int64_t)3720 * NS_PER_SEC, (int64_t)3740 * NS_PER_SEC,
1043 (int64_t)3780 * NS_PER_SEC, (int64_t)3790 * NS_PER_SEC, (int64_t)3820 * NS_PER_SEC,
1044 (int64_t)3850 * NS_PER_SEC, (int64_t)3860 * NS_PER_SEC, (int64_t)3870 * NS_PER_SEC,
1045 (int64_t)3880 * NS_PER_SEC, (int64_t)3900 * NS_PER_SEC, (int64_t)3910 * NS_PER_SEC,
1046 (int64_t)3920 * NS_PER_SEC, (int64_t)3930 * NS_PER_SEC, (int64_t)3940 * NS_PER_SEC});
1047
1048 // Data 2
1049 data = gaugeMetrics.data(1);
1050 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
1051 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1052 EXPECT_EQ(1 /* subsystem name field */,
1053 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1054 EXPECT_EQ("subsystem_name_2",
1055 data.dimensions_in_what().value_tuple().dimensions_value(0).value_str());
1056 ASSERT_EQ(2, data.bucket_info_size());
1057
1058 // Data 2, Bucket 1
1059 ASSERT_EQ(13, data.bucket_info(0).atom_size());
1060 ValidateGaugeBucketTimes(
1061 data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1062 {(int64_t)60 * NS_PER_SEC, (int64_t)80 * NS_PER_SEC, (int64_t)90 * NS_PER_SEC,
1063 (int64_t)130 * NS_PER_SEC, (int64_t)150 * NS_PER_SEC, (int64_t)170 * NS_PER_SEC,
1064 (int64_t)190 * NS_PER_SEC, (int64_t)200 * NS_PER_SEC, (int64_t)240 * NS_PER_SEC,
1065 (int64_t)250 * NS_PER_SEC, (int64_t)300 * NS_PER_SEC, (int64_t)330 * NS_PER_SEC,
1066 (int64_t)340 * NS_PER_SEC});
1067
1068 // Data 2, Bucket 2
1069 ASSERT_EQ(18, data.bucket_info(1).atom_size());
1070 ValidateGaugeBucketTimes(
1071 data.bucket_info(1), configAddedTimeNs + bucketSizeNs,
1072 configAddedTimeNs + 2 * bucketSizeNs,
1073 {(int64_t)3660 * NS_PER_SEC, (int64_t)3680 * NS_PER_SEC, (int64_t)3700 * NS_PER_SEC,
1074 (int64_t)3710 * NS_PER_SEC, (int64_t)3720 * NS_PER_SEC, (int64_t)3740 * NS_PER_SEC,
1075 (int64_t)3780 * NS_PER_SEC, (int64_t)3790 * NS_PER_SEC, (int64_t)3820 * NS_PER_SEC,
1076 (int64_t)3850 * NS_PER_SEC, (int64_t)3860 * NS_PER_SEC, (int64_t)3870 * NS_PER_SEC,
1077 (int64_t)3880 * NS_PER_SEC, (int64_t)3900 * NS_PER_SEC, (int64_t)3910 * NS_PER_SEC,
1078 (int64_t)3920 * NS_PER_SEC, (int64_t)3930 * NS_PER_SEC, (int64_t)3940 * NS_PER_SEC});
1079 }
1080
TEST(GaugeMetricE2ePulledTest,TestGaugeMetricPullProbabilityWithBucketBoundaryAlarm)1081 TEST(GaugeMetricE2ePulledTest, TestGaugeMetricPullProbabilityWithBucketBoundaryAlarm) {
1082 // Initiating StatsdStats at the start of this test, so it doesn't call rand() during the test.
1083 StatsdStats::getInstance();
1084 // Set srand seed to make rand deterministic for testing.
1085 srand(0);
1086
1087 auto config = CreateStatsdConfig(GaugeMetric::FIRST_N_SAMPLES, /*useCondition=*/false);
1088 auto gaugeMetric = config.mutable_gauge_metric(0);
1089 gaugeMetric->set_pull_probability(50);
1090 gaugeMetric->set_max_num_gauge_atoms_per_bucket(200);
1091
1092 int64_t baseTimeNs = 5 * 60 * NS_PER_SEC;
1093 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC;
1094 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
1095
1096 ConfigKey cfgKey;
1097 auto processor =
1098 CreateStatsLogProcessor(configAddedTimeNs, configAddedTimeNs, config, cfgKey,
1099 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
1100
1101 // Pulling alarm arrives on time and resets the sequential pulling alarm.
1102 for (int i = 1; i < 31; i++) {
1103 processor->informPullAlarmFired(configAddedTimeNs + i * bucketSizeNs);
1104 }
1105
1106 ConfigMetricsReportList reports;
1107 vector<uint8_t> buffer;
1108 processor->onDumpReport(cfgKey, configAddedTimeNs + 32 * bucketSizeNs + 10, false, true,
1109 ADB_DUMP, FAST, &buffer);
1110 EXPECT_TRUE(buffer.size() > 0);
1111 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1112 backfillDimensionPath(&reports);
1113 backfillStringInReport(&reports);
1114 backfillStartEndTimestamp(&reports);
1115 backfillAggregatedAtoms(&reports);
1116 ASSERT_EQ(1, reports.reports_size());
1117 ASSERT_EQ(1, reports.reports(0).metrics_size());
1118 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
1119 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
1120 ASSERT_EQ((int)gaugeMetrics.data_size(), 2);
1121
1122 // Data 1
1123 auto data = gaugeMetrics.data(0);
1124 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
1125 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1126 EXPECT_EQ(1 /* subsystem name field */,
1127 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1128 EXPECT_EQ("subsystem_name_1",
1129 data.dimensions_in_what().value_tuple().dimensions_value(0).value_str());
1130 ASSERT_EQ(14, data.bucket_info_size());
1131
1132 EXPECT_EQ(1, data.bucket_info(0).atom_size());
1133 ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs,
1134 configAddedTimeNs + bucketSizeNs, {configAddedTimeNs});
1135
1136 EXPECT_EQ(1, data.bucket_info(1).atom_size());
1137 ValidateGaugeBucketTimes(data.bucket_info(1), configAddedTimeNs + 2 * bucketSizeNs,
1138 configAddedTimeNs + 3 * bucketSizeNs,
1139 {configAddedTimeNs + 2 * bucketSizeNs}); // 1200000000000ns
1140
1141 EXPECT_EQ(1, data.bucket_info(2).atom_size());
1142 ValidateGaugeBucketTimes(data.bucket_info(2), configAddedTimeNs + 3 * bucketSizeNs,
1143 configAddedTimeNs + 4 * bucketSizeNs,
1144 {(int64_t)configAddedTimeNs + 3 * bucketSizeNs}); // 1500000000000ns
1145
1146 EXPECT_EQ(1, data.bucket_info(3).atom_size());
1147 ValidateGaugeBucketTimes(data.bucket_info(3), configAddedTimeNs + 7 * bucketSizeNs,
1148 configAddedTimeNs + 8 * bucketSizeNs,
1149 {configAddedTimeNs + 7 * bucketSizeNs}); // 2700000000000ns
1150
1151 EXPECT_EQ(1, data.bucket_info(4).atom_size());
1152 ValidateGaugeBucketTimes(data.bucket_info(4), configAddedTimeNs + 9 * bucketSizeNs,
1153 configAddedTimeNs + 10 * bucketSizeNs,
1154 {configAddedTimeNs + 9 * bucketSizeNs}); // 3300000000000ns
1155
1156 EXPECT_EQ(1, data.bucket_info(5).atom_size());
1157 ValidateGaugeBucketTimes(data.bucket_info(5), configAddedTimeNs + 11 * bucketSizeNs,
1158 configAddedTimeNs + 12 * bucketSizeNs,
1159 {configAddedTimeNs + 11 * bucketSizeNs}); // 3900000000000ns
1160
1161 EXPECT_EQ(1, data.bucket_info(6).atom_size());
1162 ValidateGaugeBucketTimes(data.bucket_info(6), configAddedTimeNs + 13 * bucketSizeNs,
1163 configAddedTimeNs + 14 * bucketSizeNs,
1164 {configAddedTimeNs + 13 * bucketSizeNs}); // 4500000000000ns
1165
1166 EXPECT_EQ(1, data.bucket_info(7).atom_size());
1167 ValidateGaugeBucketTimes(data.bucket_info(7), configAddedTimeNs + 14 * bucketSizeNs,
1168 configAddedTimeNs + 15 * bucketSizeNs,
1169 {configAddedTimeNs + 14 * bucketSizeNs}); // 4800000000000ns
1170
1171 EXPECT_EQ(1, data.bucket_info(8).atom_size());
1172 ValidateGaugeBucketTimes(data.bucket_info(8), configAddedTimeNs + 18 * bucketSizeNs,
1173 configAddedTimeNs + 19 * bucketSizeNs,
1174 {configAddedTimeNs + 18 * bucketSizeNs}); // 6000000000000ns
1175
1176 EXPECT_EQ(1, data.bucket_info(9).atom_size());
1177 ValidateGaugeBucketTimes(data.bucket_info(9), configAddedTimeNs + 19 * bucketSizeNs,
1178 configAddedTimeNs + 20 * bucketSizeNs,
1179 {configAddedTimeNs + 19 * bucketSizeNs}); // 6300000000000ns
1180
1181 EXPECT_EQ(1, data.bucket_info(10).atom_size());
1182 ValidateGaugeBucketTimes(data.bucket_info(10), configAddedTimeNs + 24 * bucketSizeNs,
1183 configAddedTimeNs + 25 * bucketSizeNs,
1184 {configAddedTimeNs + 24 * bucketSizeNs}); // 7800000000000ns
1185
1186 EXPECT_EQ(1, data.bucket_info(11).atom_size());
1187 ValidateGaugeBucketTimes(data.bucket_info(11), configAddedTimeNs + 27 * bucketSizeNs,
1188 configAddedTimeNs + 28 * bucketSizeNs,
1189 {configAddedTimeNs + 27 * bucketSizeNs}); // 8700000000000ns
1190
1191 EXPECT_EQ(1, data.bucket_info(12).atom_size());
1192 ValidateGaugeBucketTimes(data.bucket_info(12), configAddedTimeNs + 28 * bucketSizeNs,
1193 configAddedTimeNs + 29 * bucketSizeNs,
1194 {configAddedTimeNs + 28 * bucketSizeNs}); // 9000000000000ns
1195
1196 EXPECT_EQ(1, data.bucket_info(13).atom_size());
1197 ValidateGaugeBucketTimes(data.bucket_info(13), configAddedTimeNs + 30 * bucketSizeNs,
1198 configAddedTimeNs + 31 * bucketSizeNs,
1199 {configAddedTimeNs + 30 * bucketSizeNs}); // 9600000000000ns
1200
1201 // Data 2
1202 data = gaugeMetrics.data(1);
1203 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
1204 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1205 EXPECT_EQ(1 /* subsystem name field */,
1206 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1207 EXPECT_EQ("subsystem_name_2",
1208 data.dimensions_in_what().value_tuple().dimensions_value(0).value_str());
1209 ASSERT_EQ(14, data.bucket_info_size());
1210
1211 EXPECT_EQ(1, data.bucket_info(0).atom_size());
1212 ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs,
1213 configAddedTimeNs + bucketSizeNs, {configAddedTimeNs});
1214
1215 EXPECT_EQ(1, data.bucket_info(1).atom_size());
1216 ValidateGaugeBucketTimes(data.bucket_info(1), configAddedTimeNs + 2 * bucketSizeNs,
1217 configAddedTimeNs + 3 * bucketSizeNs,
1218 {configAddedTimeNs + 2 * bucketSizeNs});
1219
1220 EXPECT_EQ(1, data.bucket_info(2).atom_size());
1221 ValidateGaugeBucketTimes(data.bucket_info(2), configAddedTimeNs + 3 * bucketSizeNs,
1222 configAddedTimeNs + 4 * bucketSizeNs,
1223 {(int64_t)configAddedTimeNs + 3 * bucketSizeNs});
1224
1225 EXPECT_EQ(1, data.bucket_info(3).atom_size());
1226 ValidateGaugeBucketTimes(data.bucket_info(3), configAddedTimeNs + 7 * bucketSizeNs,
1227 configAddedTimeNs + 8 * bucketSizeNs,
1228 {configAddedTimeNs + 7 * bucketSizeNs});
1229
1230 EXPECT_EQ(1, data.bucket_info(4).atom_size());
1231 ValidateGaugeBucketTimes(data.bucket_info(4), configAddedTimeNs + 9 * bucketSizeNs,
1232 configAddedTimeNs + 10 * bucketSizeNs,
1233 {configAddedTimeNs + 9 * bucketSizeNs});
1234
1235 EXPECT_EQ(1, data.bucket_info(5).atom_size());
1236 ValidateGaugeBucketTimes(data.bucket_info(5), configAddedTimeNs + 11 * bucketSizeNs,
1237 configAddedTimeNs + 12 * bucketSizeNs,
1238 {configAddedTimeNs + 11 * bucketSizeNs});
1239
1240 EXPECT_EQ(1, data.bucket_info(6).atom_size());
1241 ValidateGaugeBucketTimes(data.bucket_info(6), configAddedTimeNs + 13 * bucketSizeNs,
1242 configAddedTimeNs + 14 * bucketSizeNs,
1243 {configAddedTimeNs + 13 * bucketSizeNs});
1244
1245 EXPECT_EQ(1, data.bucket_info(7).atom_size());
1246 ValidateGaugeBucketTimes(data.bucket_info(7), configAddedTimeNs + 14 * bucketSizeNs,
1247 configAddedTimeNs + 15 * bucketSizeNs,
1248 {configAddedTimeNs + 14 * bucketSizeNs});
1249
1250 EXPECT_EQ(1, data.bucket_info(8).atom_size());
1251 ValidateGaugeBucketTimes(data.bucket_info(8), configAddedTimeNs + 18 * bucketSizeNs,
1252 configAddedTimeNs + 19 * bucketSizeNs,
1253 {configAddedTimeNs + 18 * bucketSizeNs});
1254
1255 EXPECT_EQ(1, data.bucket_info(9).atom_size());
1256 ValidateGaugeBucketTimes(data.bucket_info(9), configAddedTimeNs + 19 * bucketSizeNs,
1257 configAddedTimeNs + 20 * bucketSizeNs,
1258 {configAddedTimeNs + 19 * bucketSizeNs});
1259
1260 EXPECT_EQ(1, data.bucket_info(10).atom_size());
1261 ValidateGaugeBucketTimes(data.bucket_info(10), configAddedTimeNs + 24 * bucketSizeNs,
1262 configAddedTimeNs + 25 * bucketSizeNs,
1263 {configAddedTimeNs + 24 * bucketSizeNs});
1264
1265 EXPECT_EQ(1, data.bucket_info(11).atom_size());
1266 ValidateGaugeBucketTimes(data.bucket_info(11), configAddedTimeNs + 27 * bucketSizeNs,
1267 configAddedTimeNs + 28 * bucketSizeNs,
1268 {configAddedTimeNs + 27 * bucketSizeNs});
1269
1270 EXPECT_EQ(1, data.bucket_info(12).atom_size());
1271 ValidateGaugeBucketTimes(data.bucket_info(12), configAddedTimeNs + 28 * bucketSizeNs,
1272 configAddedTimeNs + 29 * bucketSizeNs,
1273 {configAddedTimeNs + 28 * bucketSizeNs});
1274
1275 EXPECT_EQ(1, data.bucket_info(13).atom_size());
1276 ValidateGaugeBucketTimes(data.bucket_info(13), configAddedTimeNs + 30 * bucketSizeNs,
1277 configAddedTimeNs + 31 * bucketSizeNs,
1278 {configAddedTimeNs + 30 * bucketSizeNs});
1279 }
1280
TEST(GaugeMetricE2ePulledTest,TestGaugeMetricPullProbabilityWithCondition)1281 TEST(GaugeMetricE2ePulledTest, TestGaugeMetricPullProbabilityWithCondition) {
1282 // Initiating StatsdStats at the start of this test, so it doesn't call rand() during the test.
1283 StatsdStats::getInstance();
1284 // Set srand seed to make rand deterministic for testing.
1285 srand(0);
1286
1287 auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE, /*useCondition=*/true);
1288 auto gaugeMetric = config.mutable_gauge_metric(0);
1289 gaugeMetric->set_pull_probability(50);
1290 gaugeMetric->set_max_num_gauge_atoms_per_bucket(200);
1291 gaugeMetric->set_bucket(ONE_HOUR);
1292
1293 int64_t configAddedTimeNs = 60 * NS_PER_SEC;
1294 int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
1295
1296 ConfigKey cfgKey;
1297 auto processor =
1298 CreateStatsLogProcessor(configAddedTimeNs, configAddedTimeNs, config, cfgKey,
1299 SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
1300
1301 std::vector<std::unique_ptr<LogEvent>> events;
1302 // First bucket events.
1303 for (int i = 0; i < 30; i++) {
1304 events.push_back(CreateScreenStateChangedEvent(configAddedTimeNs + (i * 10 * NS_PER_SEC),
1305 android::view::DISPLAY_STATE_OFF));
1306 events.push_back(CreateScreenStateChangedEvent(configAddedTimeNs + (i * 11 * NS_PER_SEC),
1307 android::view::DISPLAY_STATE_ON));
1308 }
1309
1310 // Send log events to StatsLogProcessor.
1311 for (auto& event : events) {
1312 processor->OnLogEvent(event.get());
1313 }
1314
1315 ConfigMetricsReportList reports;
1316 vector<uint8_t> buffer;
1317 processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs, false, true, ADB_DUMP,
1318 FAST, &buffer);
1319
1320 EXPECT_TRUE(buffer.size() > 0);
1321 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
1322 backfillDimensionPath(&reports);
1323 backfillStringInReport(&reports);
1324 backfillStartEndTimestamp(&reports);
1325 backfillAggregatedAtoms(&reports);
1326 ASSERT_EQ(1, reports.reports_size());
1327 ASSERT_EQ(1, reports.reports(0).metrics_size());
1328 StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
1329 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
1330 ASSERT_EQ((int)gaugeMetrics.data_size(), 2); // 2 sets of data for each pull.
1331
1332 // Data 1
1333 auto data = gaugeMetrics.data(0);
1334 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
1335 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1336 EXPECT_EQ(1 /* subsystem name field */,
1337 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1338 EXPECT_EQ("subsystem_name_1",
1339 data.dimensions_in_what().value_tuple().dimensions_value(0).value_str());
1340 ASSERT_EQ(1, data.bucket_info_size());
1341
1342 // Data 1, Bucket 1
1343 ASSERT_EQ(13, data.bucket_info(0).atom_size());
1344 ValidateGaugeBucketTimes(
1345 data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1346 {(int64_t)60 * NS_PER_SEC, (int64_t)80 * NS_PER_SEC, (int64_t)90 * NS_PER_SEC,
1347 (int64_t)130 * NS_PER_SEC, (int64_t)150 * NS_PER_SEC, (int64_t)170 * NS_PER_SEC,
1348 (int64_t)190 * NS_PER_SEC, (int64_t)200 * NS_PER_SEC, (int64_t)240 * NS_PER_SEC,
1349 (int64_t)250 * NS_PER_SEC, (int64_t)300 * NS_PER_SEC, (int64_t)330 * NS_PER_SEC,
1350 (int64_t)340 * NS_PER_SEC});
1351
1352 // Data 2
1353 data = gaugeMetrics.data(1);
1354 EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
1355 ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
1356 EXPECT_EQ(1 /* subsystem name field */,
1357 data.dimensions_in_what().value_tuple().dimensions_value(0).field());
1358 EXPECT_EQ("subsystem_name_2",
1359 data.dimensions_in_what().value_tuple().dimensions_value(0).value_str());
1360 ASSERT_EQ(1, data.bucket_info_size());
1361
1362 // Data 2, Bucket 1
1363 ASSERT_EQ(13, data.bucket_info(0).atom_size());
1364 ValidateGaugeBucketTimes(
1365 data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
1366 {(int64_t)60 * NS_PER_SEC, (int64_t)80 * NS_PER_SEC, (int64_t)90 * NS_PER_SEC,
1367 (int64_t)130 * NS_PER_SEC, (int64_t)150 * NS_PER_SEC, (int64_t)170 * NS_PER_SEC,
1368 (int64_t)190 * NS_PER_SEC, (int64_t)200 * NS_PER_SEC, (int64_t)240 * NS_PER_SEC,
1369 (int64_t)250 * NS_PER_SEC, (int64_t)300 * NS_PER_SEC, (int64_t)330 * NS_PER_SEC,
1370 (int64_t)340 * NS_PER_SEC});
1371 }
1372
1373 #else
1374 GTEST_LOG_(INFO) << "This test does nothing.\n";
1375 #endif
1376
1377 } // namespace statsd
1378 } // namespace os
1379 } // namespace android
1380