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 "src/guardrail/StatsdStats.h"
16
17 #include <gtest/gtest.h>
18
19 #include <vector>
20
21 #include "gtest_matchers.h"
22 #include "src/metrics/parsing_utils/metrics_manager_util.h"
23 #include "src/shell/ShellSubscriber.h"
24 #include "src/stats_log.pb.h"
25 #include "statslog_statsdtest.h"
26 #include "tests/statsd_test_util.h"
27
28 #ifdef __ANDROID__
29
30 namespace std {
PrintTo(const tuple<int,size_t> & atomIdDimensionLimitTuple,ostream * os)31 void PrintTo(const tuple<int, size_t>& atomIdDimensionLimitTuple, ostream* os) {
32 *os << get<0>(atomIdDimensionLimitTuple) << "_" << get<1>(atomIdDimensionLimitTuple);
33 }
34 } // namespace std
35
36 namespace android {
37 namespace os {
38 namespace statsd {
39 namespace {
40
41 using namespace testing;
42 using PerSubscriptionStats = StatsdStatsReport_SubscriptionStats_PerSubscriptionStats;
43 using std::tuple;
44 using std::unordered_map;
45 using std::vector;
46
47 class StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap
48 : public TestWithParam<tuple<int, size_t>> {};
49 INSTANTIATE_TEST_SUITE_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap,
50 StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap,
51 Combine(Values(10022 /* BINDER_CALLS */, 10024 /* LOOPER_STATS */,
52 10010 /* CPU_TIME_PER_UID_FREQ */),
53 Values(-1, 0, 500, 800, 1000, 3000, 3300)),
54 PrintToStringParamName());
55
56 class StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap
57 : public StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap {};
58
59 INSTANTIATE_TEST_SUITE_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap,
60 StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap,
61 Combine(Values(util::TEST_ATOM_REPORTED, util::SCREEN_STATE_CHANGED,
62 util::SUBSYSTEM_SLEEP_STATE),
63 Values(-1, 0, 500, 800, 1000, 3000, 3300)),
64 PrintToStringParamName());
65
66 } // anonymous namespace
67
TEST(StatsdStatsTest,TestValidConfigAdd)68 TEST(StatsdStatsTest, TestValidConfigAdd) {
69 StatsdStats stats;
70 ConfigKey key(0, 12345);
71 const int metricsCount = 10;
72 const int conditionsCount = 20;
73 const int matchersCount = 30;
74 const int alertsCount = 10;
75 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
76 nullopt /*valid config*/);
77
78 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
79 ASSERT_EQ(1, report.config_stats_size());
80 const auto& configReport = report.config_stats(0);
81 EXPECT_EQ(0, configReport.uid());
82 EXPECT_EQ(12345, configReport.id());
83 EXPECT_EQ(metricsCount, configReport.metric_count());
84 EXPECT_EQ(conditionsCount, configReport.condition_count());
85 EXPECT_EQ(matchersCount, configReport.matcher_count());
86 EXPECT_EQ(alertsCount, configReport.alert_count());
87 EXPECT_EQ(true, configReport.is_valid());
88 EXPECT_FALSE(configReport.has_invalid_config_reason());
89 EXPECT_FALSE(configReport.has_deletion_time_sec());
90 }
91
TEST(StatsdStatsTest,TestConfigMetadataProviderPromotionFailed)92 TEST(StatsdStatsTest, TestConfigMetadataProviderPromotionFailed) {
93 StatsdStats stats;
94 ConfigKey key(0, 12345);
95 stats.noteConfigReceived(key, /*metricsCount=*/0, /*conditionsCount=*/0, /*matchersCount=*/0,
96 /*alertCount=*/0, /*annotations=*/{}, nullopt /*valid config*/);
97
98 stats.noteConfigMetadataProviderPromotionFailed(key);
99
100 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
101 ASSERT_EQ(1, report.config_stats_size());
102 const auto& configReport = report.config_stats(0);
103 EXPECT_EQ(1, configReport.config_metadata_provider_promotion_failed());
104 }
105
TEST(StatsdStatsTest,TestInvalidConfigAdd)106 TEST(StatsdStatsTest, TestInvalidConfigAdd) {
107 StatsdStats stats;
108 ConfigKey key(0, 12345);
109 const int metricsCount = 10;
110 const int conditionsCount = 20;
111 const int matchersCount = 30;
112 const int alertsCount = 10;
113 optional<InvalidConfigReason> invalidConfigReason =
114 InvalidConfigReason(INVALID_CONFIG_REASON_UNKNOWN, 1);
115 invalidConfigReason->stateId = 2;
116 invalidConfigReason->alertId = 3;
117 invalidConfigReason->alarmId = 4;
118 invalidConfigReason->subscriptionId = 5;
119 invalidConfigReason->matcherIds.push_back(6);
120 invalidConfigReason->matcherIds.push_back(7);
121 invalidConfigReason->conditionIds.push_back(8);
122 invalidConfigReason->conditionIds.push_back(9);
123 invalidConfigReason->conditionIds.push_back(10);
124 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
125 invalidConfigReason /*bad config*/);
126
127 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
128 ASSERT_EQ(1, report.config_stats_size());
129 const auto& configReport = report.config_stats(0);
130 // The invalid config should be put into icebox with a deletion time.
131 EXPECT_TRUE(configReport.has_deletion_time_sec());
132 EXPECT_TRUE(configReport.has_invalid_config_reason());
133 EXPECT_EQ(configReport.invalid_config_reason().reason(), INVALID_CONFIG_REASON_UNKNOWN);
134 EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
135 EXPECT_EQ(configReport.invalid_config_reason().state_id(), 2);
136 EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 3);
137 EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 4);
138 EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 5);
139 EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 2);
140 EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 6);
141 EXPECT_EQ(configReport.invalid_config_reason().matcher_id(1), 7);
142 EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 3);
143 EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 8);
144 EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 9);
145 EXPECT_EQ(configReport.invalid_config_reason().condition_id(2), 10);
146 }
147
TEST(StatsdStatsTest,TestInvalidConfigMissingMetricId)148 TEST(StatsdStatsTest, TestInvalidConfigMissingMetricId) {
149 StatsdStats stats;
150 ConfigKey key(0, 12345);
151 const int metricsCount = 10;
152 const int conditionsCount = 20;
153 const int matchersCount = 30;
154 const int alertsCount = 10;
155 optional<InvalidConfigReason> invalidConfigReason =
156 InvalidConfigReason(INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
157 invalidConfigReason->stateId = 1;
158 invalidConfigReason->alertId = 2;
159 invalidConfigReason->alarmId = 3;
160 invalidConfigReason->subscriptionId = 4;
161 invalidConfigReason->matcherIds.push_back(5);
162 invalidConfigReason->conditionIds.push_back(6);
163 invalidConfigReason->conditionIds.push_back(7);
164 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
165 invalidConfigReason /*bad config*/);
166
167 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
168 ASSERT_EQ(1, report.config_stats_size());
169 const auto& configReport = report.config_stats(0);
170 // The invalid config should be put into icebox with a deletion time.
171 EXPECT_TRUE(configReport.has_deletion_time_sec());
172 EXPECT_TRUE(configReport.has_invalid_config_reason());
173 EXPECT_EQ(configReport.invalid_config_reason().reason(),
174 INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
175 EXPECT_FALSE(configReport.invalid_config_reason().has_metric_id());
176 EXPECT_EQ(configReport.invalid_config_reason().state_id(), 1);
177 EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 2);
178 EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 3);
179 EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 4);
180 EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 1);
181 EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 5);
182 EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 2);
183 EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 6);
184 EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 7);
185 }
186
TEST(StatsdStatsTest,TestInvalidConfigOnlyMetricId)187 TEST(StatsdStatsTest, TestInvalidConfigOnlyMetricId) {
188 StatsdStats stats;
189 ConfigKey key(0, 12345);
190 const int metricsCount = 10;
191 const int conditionsCount = 20;
192 const int matchersCount = 30;
193 const int alertsCount = 10;
194 optional<InvalidConfigReason> invalidConfigReason =
195 InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG, 1);
196 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
197 invalidConfigReason /*bad config*/);
198
199 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
200 ASSERT_EQ(1, report.config_stats_size());
201 const auto& configReport = report.config_stats(0);
202 // The invalid config should be put into icebox with a deletion time.
203 EXPECT_TRUE(configReport.has_deletion_time_sec());
204 EXPECT_TRUE(configReport.has_invalid_config_reason());
205 EXPECT_EQ(configReport.invalid_config_reason().reason(),
206 INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG);
207 EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
208 EXPECT_FALSE(configReport.invalid_config_reason().has_state_id());
209 EXPECT_FALSE(configReport.invalid_config_reason().has_alert_id());
210 EXPECT_FALSE(configReport.invalid_config_reason().has_alarm_id());
211 EXPECT_FALSE(configReport.invalid_config_reason().has_subscription_id());
212 EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 0);
213 EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 0);
214 }
215
TEST(StatsdStatsTest,TestConfigRemove)216 TEST(StatsdStatsTest, TestConfigRemove) {
217 StatsdStats stats;
218 ConfigKey key(0, 12345);
219 const int metricsCount = 10;
220 const int conditionsCount = 20;
221 const int matchersCount = 30;
222 const int alertsCount = 10;
223 stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
224 nullopt);
225
226 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
227 ASSERT_EQ(1, report.config_stats_size());
228 const auto& configReport = report.config_stats(0);
229 EXPECT_FALSE(configReport.has_deletion_time_sec());
230
231 stats.noteConfigRemoved(key);
232
233 report = getStatsdStatsReport(stats, /* reset stats */ false);
234 ASSERT_EQ(1, report.config_stats_size());
235 const auto& configReport2 = report.config_stats(0);
236 EXPECT_TRUE(configReport2.has_deletion_time_sec());
237 }
238
TEST(StatsdStatsTest,TestSubStats)239 TEST(StatsdStatsTest, TestSubStats) {
240 StatsdStats stats;
241 ConfigKey key(0, 12345);
242 stats.noteConfigReceived(key, 2, 3, 4, 5, {std::make_pair(123, 456)}, nullopt);
243
244 stats.noteMatcherMatched(key, StringToId("matcher1"));
245 stats.noteMatcherMatched(key, StringToId("matcher1"));
246 stats.noteMatcherMatched(key, StringToId("matcher2"));
247
248 stats.noteConditionDimensionSize(key, StringToId("condition1"), 250);
249 stats.noteConditionDimensionSize(key, StringToId("condition1"), 240);
250
251 stats.noteMetricDimensionSize(key, StringToId("metric1"), 201);
252 stats.noteMetricDimensionSize(key, StringToId("metric1"), 202);
253
254 stats.noteAnomalyDeclared(key, StringToId("alert1"));
255 stats.noteAnomalyDeclared(key, StringToId("alert1"));
256 stats.noteAnomalyDeclared(key, StringToId("alert2"));
257
258 // broadcast-> 2
259 stats.noteBroadcastSent(key);
260 stats.noteBroadcastSent(key);
261
262 // data drop -> 1
263 stats.noteDataDropped(key, 123);
264
265 // dump report -> 3
266 stats.noteMetricsReportSent(key, 0, 1);
267 stats.noteMetricsReportSent(key, 0, 2);
268 stats.noteMetricsReportSent(key, 0, 3);
269
270 // activation_time_sec -> 2
271 stats.noteActiveStatusChanged(key, true);
272 stats.noteActiveStatusChanged(key, true);
273
274 // deactivation_time_sec -> 1
275 stats.noteActiveStatusChanged(key, false);
276
277 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true);
278 ASSERT_EQ(1, report.config_stats_size());
279 const auto& configReport = report.config_stats(0);
280 ASSERT_EQ(2, configReport.broadcast_sent_time_sec_size());
281 ASSERT_EQ(1, configReport.data_drop_time_sec_size());
282 ASSERT_EQ(1, configReport.data_drop_bytes_size());
283 EXPECT_EQ(123, configReport.data_drop_bytes(0));
284 ASSERT_EQ(3, configReport.dump_report_time_sec_size());
285 ASSERT_EQ(3, configReport.dump_report_data_size_size());
286 ASSERT_EQ(3, configReport.dump_report_number_size());
287 EXPECT_EQ(1, configReport.dump_report_number(0));
288 EXPECT_EQ(2, configReport.dump_report_number(1));
289 EXPECT_EQ(3, configReport.dump_report_number(2));
290 ASSERT_EQ(2, configReport.activation_time_sec_size());
291 ASSERT_EQ(1, configReport.deactivation_time_sec_size());
292 ASSERT_EQ(1, configReport.annotation_size());
293 EXPECT_EQ(123, configReport.annotation(0).field_int64());
294 EXPECT_EQ(456, configReport.annotation(0).field_int32());
295
296 ASSERT_EQ(2, configReport.matcher_stats_size());
297 // matcher1 is the first in the list
298 if (configReport.matcher_stats(0).id() == StringToId("matcher1")) {
299 EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
300 EXPECT_EQ(1, configReport.matcher_stats(1).matched_times());
301 EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(1).id());
302 } else {
303 // matcher1 is the second in the list.
304 EXPECT_EQ(1, configReport.matcher_stats(0).matched_times());
305 EXPECT_EQ(StringToId("matcher2"), configReport.matcher_stats(0).id());
306
307 EXPECT_EQ(2, configReport.matcher_stats(1).matched_times());
308 EXPECT_EQ(StringToId("matcher1"), configReport.matcher_stats(1).id());
309 }
310
311 ASSERT_EQ(2, configReport.alert_stats_size());
312 bool alert1first = configReport.alert_stats(0).id() == StringToId("alert1");
313 EXPECT_EQ(StringToId("alert1"), configReport.alert_stats(alert1first ? 0 : 1).id());
314 EXPECT_EQ(2, configReport.alert_stats(alert1first ? 0 : 1).alerted_times());
315 EXPECT_EQ(StringToId("alert2"), configReport.alert_stats(alert1first ? 1 : 0).id());
316 EXPECT_EQ(1, configReport.alert_stats(alert1first ? 1 : 0).alerted_times());
317
318 ASSERT_EQ(1, configReport.condition_stats_size());
319 EXPECT_EQ(StringToId("condition1"), configReport.condition_stats(0).id());
320 EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
321
322 ASSERT_EQ(1, configReport.metric_stats_size());
323 EXPECT_EQ(StringToId("metric1"), configReport.metric_stats(0).id());
324 EXPECT_EQ(202, configReport.metric_stats(0).max_tuple_counts());
325
326 // after resetting the stats, some new events come
327 stats.noteMatcherMatched(key, StringToId("matcher99"));
328 stats.noteConditionDimensionSize(key, StringToId("condition99"), 300);
329 stats.noteMetricDimensionSize(key, StringToId("metric99tion99"), 270);
330 stats.noteAnomalyDeclared(key, StringToId("alert99"));
331
332 // now the config stats should only contain the stats about the new event.
333 report = getStatsdStatsReport(stats, /* reset stats */ false);
334 ASSERT_EQ(1, report.config_stats_size());
335 const auto& configReport2 = report.config_stats(0);
336 ASSERT_EQ(1, configReport2.matcher_stats_size());
337 EXPECT_EQ(StringToId("matcher99"), configReport2.matcher_stats(0).id());
338 EXPECT_EQ(1, configReport2.matcher_stats(0).matched_times());
339
340 ASSERT_EQ(1, configReport2.condition_stats_size());
341 EXPECT_EQ(StringToId("condition99"), configReport2.condition_stats(0).id());
342 EXPECT_EQ(300, configReport2.condition_stats(0).max_tuple_counts());
343
344 ASSERT_EQ(1, configReport2.metric_stats_size());
345 EXPECT_EQ(StringToId("metric99tion99"), configReport2.metric_stats(0).id());
346 EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
347
348 ASSERT_EQ(1, configReport2.alert_stats_size());
349 EXPECT_EQ(StringToId("alert99"), configReport2.alert_stats(0).id());
350 EXPECT_EQ(1, configReport2.alert_stats(0).alerted_times());
351 }
352
TEST(StatsdStatsTest,TestAtomLog)353 TEST(StatsdStatsTest, TestAtomLog) {
354 StatsdStats stats;
355 time_t now = time(nullptr);
356 // old event, we get it from the stats buffer. should be ignored.
357 stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, 1000, false);
358
359 stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 1, false);
360 stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 2, false);
361 stats.noteAtomLogged(util::APP_CRASH_OCCURRED, now + 3, false);
362
363 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
364 ASSERT_EQ(2, report.atom_stats_size());
365 bool sensorAtomGood = false;
366 bool dropboxAtomGood = false;
367
368 for (const auto& atomStats : report.atom_stats()) {
369 if (atomStats.tag() == util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
370 sensorAtomGood = true;
371 }
372 if (atomStats.tag() == util::APP_CRASH_OCCURRED && atomStats.count() == 1) {
373 dropboxAtomGood = true;
374 }
375 EXPECT_FALSE(atomStats.has_dropped_count());
376 EXPECT_FALSE(atomStats.has_skip_count());
377 }
378
379 EXPECT_TRUE(dropboxAtomGood);
380 EXPECT_TRUE(sensorAtomGood);
381 }
382
TEST(StatsdStatsTest,TestNonPlatformAtomLog)383 TEST(StatsdStatsTest, TestNonPlatformAtomLog) {
384 StatsdStats stats;
385 time_t now = time(nullptr);
386 int newAtom1 = StatsdStats::kMaxPushedAtomId + 1;
387 int newAtom2 = StatsdStats::kMaxPushedAtomId + 2;
388
389 stats.noteAtomLogged(newAtom1, now + 1, false);
390 stats.noteAtomLogged(newAtom1, now + 2, false);
391 stats.noteAtomLogged(newAtom2, now + 3, false);
392
393 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
394 ASSERT_EQ(2, report.atom_stats_size());
395 bool newAtom1Good = false;
396 bool newAtom2Good = false;
397
398 for (const auto& atomStats : report.atom_stats()) {
399 if (atomStats.tag() == newAtom1 && atomStats.count() == 2) {
400 newAtom1Good = true;
401 }
402 if (atomStats.tag() == newAtom2 && atomStats.count() == 1) {
403 newAtom2Good = true;
404 }
405 EXPECT_FALSE(atomStats.has_dropped_count());
406 EXPECT_FALSE(atomStats.has_skip_count());
407 }
408
409 EXPECT_TRUE(newAtom1Good);
410 EXPECT_TRUE(newAtom2Good);
411 }
412
TEST(StatsdStatsTest,TestPullAtomStats)413 TEST(StatsdStatsTest, TestPullAtomStats) {
414 StatsdStats stats;
415
416 stats.updateMinPullIntervalSec(util::DISK_SPACE, 3333L);
417 stats.updateMinPullIntervalSec(util::DISK_SPACE, 2222L);
418 stats.updateMinPullIntervalSec(util::DISK_SPACE, 4444L);
419
420 stats.notePull(util::DISK_SPACE);
421 stats.notePullTime(util::DISK_SPACE, 1111L);
422 stats.notePullDelay(util::DISK_SPACE, 1111L);
423 stats.notePull(util::DISK_SPACE);
424 stats.notePullTime(util::DISK_SPACE, 3333L);
425 stats.notePullDelay(util::DISK_SPACE, 3335L);
426 stats.notePull(util::DISK_SPACE);
427 stats.notePullFromCache(util::DISK_SPACE);
428 stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
429 stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, false);
430 stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
431 stats.notePullBinderCallFailed(util::DISK_SPACE);
432 stats.notePullUidProviderNotFound(util::DISK_SPACE);
433 stats.notePullerNotFound(util::DISK_SPACE);
434 stats.notePullerNotFound(util::DISK_SPACE);
435 stats.notePullTimeout(util::DISK_SPACE, 3000L, 6000L);
436 stats.notePullTimeout(util::DISK_SPACE, 4000L, 7000L);
437
438 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
439 ASSERT_EQ(1, report.pulled_atom_stats_size());
440
441 EXPECT_EQ(util::DISK_SPACE, report.pulled_atom_stats(0).atom_id());
442 EXPECT_EQ(3, report.pulled_atom_stats(0).total_pull());
443 EXPECT_EQ(1, report.pulled_atom_stats(0).total_pull_from_cache());
444 EXPECT_EQ(2222L, report.pulled_atom_stats(0).min_pull_interval_sec());
445 EXPECT_EQ(2222L, report.pulled_atom_stats(0).average_pull_time_nanos());
446 EXPECT_EQ(3333L, report.pulled_atom_stats(0).max_pull_time_nanos());
447 EXPECT_EQ(2223L, report.pulled_atom_stats(0).average_pull_delay_nanos());
448 EXPECT_EQ(3335L, report.pulled_atom_stats(0).max_pull_delay_nanos());
449 EXPECT_EQ(2L, report.pulled_atom_stats(0).registered_count());
450 EXPECT_EQ(1L, report.pulled_atom_stats(0).unregistered_count());
451 EXPECT_EQ(1L, report.pulled_atom_stats(0).binder_call_failed());
452 EXPECT_EQ(1L, report.pulled_atom_stats(0).failed_uid_provider_not_found());
453 EXPECT_EQ(2L, report.pulled_atom_stats(0).puller_not_found());
454 ASSERT_EQ(2, report.pulled_atom_stats(0).pull_atom_metadata_size());
455 EXPECT_EQ(3000L, report.pulled_atom_stats(0).pull_atom_metadata(0).pull_timeout_uptime_millis());
456 EXPECT_EQ(4000L, report.pulled_atom_stats(0).pull_atom_metadata(1).pull_timeout_uptime_millis());
457 EXPECT_EQ(6000L, report.pulled_atom_stats(0).pull_atom_metadata(0)
458 .pull_timeout_elapsed_millis());
459 EXPECT_EQ(7000L, report.pulled_atom_stats(0).pull_atom_metadata(1)
460 .pull_timeout_elapsed_millis());
461 }
462
TEST(StatsdStatsTest,TestAtomMetricsStats)463 TEST(StatsdStatsTest, TestAtomMetricsStats) {
464 StatsdStats stats;
465 time_t now = time(nullptr);
466 // old event, we get it from the stats buffer. should be ignored.
467 stats.noteBucketDropped(10000000000LL);
468
469 stats.noteBucketBoundaryDelayNs(10000000000LL, -1L);
470 stats.noteBucketBoundaryDelayNs(10000000000LL, -10L);
471 stats.noteBucketBoundaryDelayNs(10000000000LL, 2L);
472
473 stats.noteBucketBoundaryDelayNs(10000000001LL, 1L);
474
475 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
476 ASSERT_EQ(2, report.atom_metric_stats().size());
477
478 auto atomStats = report.atom_metric_stats(0);
479 EXPECT_EQ(10000000000LL, atomStats.metric_id());
480 EXPECT_EQ(1L, atomStats.bucket_dropped());
481 EXPECT_EQ(-10L, atomStats.min_bucket_boundary_delay_ns());
482 EXPECT_EQ(2L, atomStats.max_bucket_boundary_delay_ns());
483
484 auto atomStats2 = report.atom_metric_stats(1);
485 EXPECT_EQ(10000000001LL, atomStats2.metric_id());
486 EXPECT_EQ(0L, atomStats2.bucket_dropped());
487 EXPECT_EQ(0L, atomStats2.min_bucket_boundary_delay_ns());
488 EXPECT_EQ(1L, atomStats2.max_bucket_boundary_delay_ns());
489 }
490
TEST(StatsdStatsTest,TestRestrictedMetricsStats)491 TEST(StatsdStatsTest, TestRestrictedMetricsStats) {
492 StatsdStats stats;
493 const int64_t metricId = -1234556L;
494 ConfigKey key(0, 12345);
495 stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
496 stats.noteRestrictedMetricInsertError(key, metricId);
497 stats.noteRestrictedMetricTableCreationError(key, metricId);
498 stats.noteRestrictedMetricTableDeletionError(key, metricId);
499 stats.noteDeviceInfoTableCreationFailed(key);
500 stats.noteRestrictedMetricFlushLatency(key, metricId, 3000);
501 stats.noteRestrictedMetricFlushLatency(key, metricId, 3001);
502 stats.noteRestrictedMetricCategoryChanged(key, metricId);
503 stats.noteRestrictedConfigFlushLatency(key, 4000);
504 ConfigKey configKeyWithoutError(0, 666);
505 stats.noteConfigReceived(configKeyWithoutError, 2, 3, 4, 5, {}, nullopt);
506 stats.noteDbCorrupted(key);
507 stats.noteDbCorrupted(key);
508 stats.noteDbSizeExceeded(key);
509 stats.noteDbStatFailed(key);
510 stats.noteDbConfigInvalid(key);
511 stats.noteDbTooOld(key);
512 stats.noteDbDeletionConfigRemoved(key);
513 stats.noteDbDeletionConfigUpdated(key);
514 stats.noteRestrictedConfigDbSize(key, 999, 111);
515
516 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
517 ASSERT_EQ(2, report.config_stats().size());
518 ASSERT_EQ(0, report.config_stats(0).restricted_metric_stats().size());
519 ASSERT_EQ(1, report.config_stats(1).restricted_metric_stats().size());
520 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).insert_error());
521 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).table_creation_error());
522 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).table_deletion_error());
523 EXPECT_EQ(1, report.config_stats(1).restricted_metric_stats(0).category_changed_count());
524 ASSERT_EQ(2, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns().size());
525 EXPECT_EQ(3000, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns(0));
526 EXPECT_EQ(3001, report.config_stats(1).restricted_metric_stats(0).flush_latency_ns(1));
527 ASSERT_EQ(1, report.config_stats(1).restricted_db_size_time_sec().size());
528 EXPECT_EQ(999, report.config_stats(1).restricted_db_size_time_sec(0));
529 ASSERT_EQ(1, report.config_stats(1).restricted_db_size_bytes().size());
530 EXPECT_EQ(111, report.config_stats(1).restricted_db_size_bytes(0));
531 ASSERT_EQ(1, report.config_stats(1).restricted_flush_latency().size());
532 EXPECT_EQ(4000, report.config_stats(1).restricted_flush_latency(0));
533 EXPECT_TRUE(report.config_stats(1).device_info_table_creation_failed());
534 EXPECT_EQ(metricId, report.config_stats(1).restricted_metric_stats(0).restricted_metric_id());
535 EXPECT_EQ(2, report.config_stats(1).restricted_db_corrupted_count());
536 EXPECT_EQ(1, report.config_stats(1).db_deletion_stat_failed());
537 EXPECT_EQ(1, report.config_stats(1).db_deletion_size_exceeded_limit());
538 EXPECT_EQ(1, report.config_stats(1).db_deletion_config_invalid());
539 EXPECT_EQ(1, report.config_stats(1).db_deletion_too_old());
540 EXPECT_EQ(1, report.config_stats(1).db_deletion_config_removed());
541 EXPECT_EQ(1, report.config_stats(1).db_deletion_config_updated());
542 }
543
TEST(StatsdStatsTest,TestRestrictedMetricsQueryStats)544 TEST(StatsdStatsTest, TestRestrictedMetricsQueryStats) {
545 StatsdStats stats;
546 const int32_t callingUid = 100;
547 ConfigKey configKey(0, 12345);
548 const string configPackage = "com.google.android.gm";
549 int64_t beforeNoteMetricSucceed = getWallClockNs();
550 stats.noteQueryRestrictedMetricSucceed(configKey.GetId(), configPackage, configKey.GetUid(),
551 callingUid, /*queryLatencyNs=*/5 * NS_PER_SEC);
552 int64_t afterNoteMetricSucceed = getWallClockNs();
553
554 const int64_t configIdWithError = 111;
555 stats.noteQueryRestrictedMetricFailed(configIdWithError, configPackage, std::nullopt,
556 callingUid, InvalidQueryReason(AMBIGUOUS_CONFIG_KEY));
557 stats.noteQueryRestrictedMetricFailed(configIdWithError, configPackage, std::nullopt,
558 callingUid, InvalidQueryReason(AMBIGUOUS_CONFIG_KEY),
559 "error_message");
560
561 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
562 ASSERT_EQ(3, report.restricted_metric_query_stats().size());
563 EXPECT_EQ(configKey.GetId(), report.restricted_metric_query_stats(0).config_id());
564 EXPECT_EQ(configKey.GetUid(), report.restricted_metric_query_stats(0).config_uid());
565 EXPECT_EQ(callingUid, report.restricted_metric_query_stats(0).calling_uid());
566 EXPECT_EQ(configPackage, report.restricted_metric_query_stats(0).config_package());
567 EXPECT_FALSE(report.restricted_metric_query_stats(0).has_query_error());
568 EXPECT_LT(beforeNoteMetricSucceed,
569 report.restricted_metric_query_stats(0).query_wall_time_ns());
570 EXPECT_GT(afterNoteMetricSucceed, report.restricted_metric_query_stats(0).query_wall_time_ns());
571 EXPECT_EQ(5 * NS_PER_SEC, report.restricted_metric_query_stats(0).query_latency_ns());
572 EXPECT_EQ(configIdWithError, report.restricted_metric_query_stats(1).config_id());
573 EXPECT_EQ(AMBIGUOUS_CONFIG_KEY, report.restricted_metric_query_stats(1).invalid_query_reason());
574 EXPECT_EQ(false, report.restricted_metric_query_stats(1).has_config_uid());
575 EXPECT_FALSE(report.restricted_metric_query_stats(1).has_query_error());
576 EXPECT_FALSE(report.restricted_metric_query_stats(1).has_query_latency_ns());
577 EXPECT_EQ("error_message", report.restricted_metric_query_stats(2).query_error());
578 EXPECT_FALSE(report.restricted_metric_query_stats(2).has_query_latency_ns());
579 EXPECT_NE(report.restricted_metric_query_stats(1).query_wall_time_ns(),
580 report.restricted_metric_query_stats(0).query_wall_time_ns());
581 }
582
TEST(StatsdStatsTest,TestAnomalyMonitor)583 TEST(StatsdStatsTest, TestAnomalyMonitor) {
584 StatsdStats stats;
585 stats.noteRegisteredAnomalyAlarmChanged();
586 stats.noteRegisteredAnomalyAlarmChanged();
587
588 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
589 EXPECT_EQ(2, report.anomaly_alarm_stats().alarms_registered());
590 }
591
TEST(StatsdStatsTest,TestTimestampThreshold)592 TEST(StatsdStatsTest, TestTimestampThreshold) {
593 StatsdStats stats;
594 vector<int32_t> timestamps;
595 for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
596 timestamps.push_back(i);
597 }
598 ConfigKey key(0, 12345);
599 stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
600
601 for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
602 stats.noteDataDropped(key, timestamps[i]);
603 stats.noteBroadcastSent(key, timestamps[i]);
604 stats.noteMetricsReportSent(key, 0, timestamps[i], i + 1);
605 stats.noteActiveStatusChanged(key, true, timestamps[i]);
606 stats.noteActiveStatusChanged(key, false, timestamps[i]);
607 }
608
609 int32_t newTimestamp = 10000;
610
611 // now it should trigger removing oldest timestamp
612 stats.noteDataDropped(key, 123, 10000);
613 stats.noteBroadcastSent(key, 10000);
614 stats.noteMetricsReportSent(key, 0, 10000, 21);
615 stats.noteActiveStatusChanged(key, true, 10000);
616 stats.noteActiveStatusChanged(key, false, 10000);
617
618 EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
619 const auto& configStats = stats.mConfigStats[key];
620
621 size_t maxCount = StatsdStats::kMaxTimestampCount;
622 ASSERT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
623 ASSERT_EQ(maxCount, configStats->data_drop_time_sec.size());
624 ASSERT_EQ(maxCount, configStats->dump_report_stats.size());
625 ASSERT_EQ(maxCount, configStats->activation_time_sec.size());
626 ASSERT_EQ(maxCount, configStats->deactivation_time_sec.size());
627
628 // the oldest timestamp is the second timestamp in history
629 EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
630 EXPECT_EQ(1, configStats->data_drop_bytes.front());
631 EXPECT_EQ(1, configStats->dump_report_stats.front().mDumpReportTimeSec);
632 EXPECT_EQ(1, configStats->activation_time_sec.front());
633 EXPECT_EQ(1, configStats->deactivation_time_sec.front());
634
635 // the last timestamp is the newest timestamp.
636 EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
637 EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
638 EXPECT_EQ(123, configStats->data_drop_bytes.back());
639 EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().mDumpReportTimeSec);
640 EXPECT_EQ(newTimestamp, configStats->activation_time_sec.back());
641 EXPECT_EQ(newTimestamp, configStats->deactivation_time_sec.back());
642 }
643
TEST(StatsdStatsTest,TestSystemServerCrash)644 TEST(StatsdStatsTest, TestSystemServerCrash) {
645 StatsdStats stats;
646 vector<int32_t> timestamps;
647 for (int i = 0; i < StatsdStats::kMaxSystemServerRestarts; i++) {
648 timestamps.push_back(i);
649 stats.noteSystemServerRestart(timestamps[i]);
650 }
651
652 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
653 const int maxCount = StatsdStats::kMaxSystemServerRestarts;
654 ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
655
656 stats.noteSystemServerRestart(StatsdStats::kMaxSystemServerRestarts + 1);
657
658 report = getStatsdStatsReport(stats, /* reset stats */ false);
659 ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
660 EXPECT_EQ(StatsdStats::kMaxSystemServerRestarts + 1, report.system_restart_sec(maxCount - 1));
661 }
662
TEST(StatsdStatsTest,TestActivationBroadcastGuardrailHit)663 TEST(StatsdStatsTest, TestActivationBroadcastGuardrailHit) {
664 StatsdStats stats;
665 int uid1 = 1;
666 int uid2 = 2;
667 stats.noteActivationBroadcastGuardrailHit(uid1, 10);
668 stats.noteActivationBroadcastGuardrailHit(uid1, 20);
669
670 // Test that we only keep 20 timestamps.
671 for (int i = 0; i < 100; i++) {
672 stats.noteActivationBroadcastGuardrailHit(uid2, i);
673 }
674
675 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
676 ASSERT_EQ(2, report.activation_guardrail_stats_size());
677 bool uid1Good = false;
678 bool uid2Good = false;
679 for (const auto& guardrailTimes : report.activation_guardrail_stats()) {
680 if (uid1 == guardrailTimes.uid()) {
681 uid1Good = true;
682 ASSERT_EQ(2, guardrailTimes.guardrail_met_sec_size());
683 EXPECT_EQ(10, guardrailTimes.guardrail_met_sec(0));
684 EXPECT_EQ(20, guardrailTimes.guardrail_met_sec(1));
685 } else if (uid2 == guardrailTimes.uid()) {
686 int maxCount = StatsdStats::kMaxTimestampCount;
687 uid2Good = true;
688 ASSERT_EQ(maxCount, guardrailTimes.guardrail_met_sec_size());
689 for (int i = 0; i < maxCount; i++) {
690 EXPECT_EQ(100 - maxCount + i, guardrailTimes.guardrail_met_sec(i));
691 }
692 } else {
693 FAIL() << "Unexpected uid.";
694 }
695 }
696 EXPECT_TRUE(uid1Good);
697 EXPECT_TRUE(uid2Good);
698 }
699
TEST(StatsdStatsTest,TestAtomErrorStats)700 TEST(StatsdStatsTest, TestAtomErrorStats) {
701 StatsdStats stats;
702
703 int pushAtomTag = 100;
704 int pullAtomTag = 1000;
705 int numErrors = 10;
706
707 for (int i = 0; i < numErrors; i++) {
708 // We must call noteAtomLogged as well because only those pushed atoms
709 // that have been logged will have stats printed about them in the
710 // proto.
711 stats.noteAtomLogged(pushAtomTag, /*timeSec=*/0, false);
712 stats.noteAtomError(pushAtomTag, /*pull=*/false);
713
714 stats.noteAtomError(pullAtomTag, /*pull=*/true);
715 }
716
717 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
718
719 // Check error count = numErrors for push atom
720 ASSERT_EQ(1, report.atom_stats_size());
721 const auto& pushedAtomStats = report.atom_stats(0);
722 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
723 EXPECT_EQ(numErrors, pushedAtomStats.error_count());
724 EXPECT_FALSE(pushedAtomStats.has_dropped_count());
725 EXPECT_FALSE(pushedAtomStats.has_skip_count());
726
727 // Check error count = numErrors for pull atom
728 ASSERT_EQ(1, report.pulled_atom_stats_size());
729 const auto& pulledAtomStats = report.pulled_atom_stats(0);
730 EXPECT_EQ(pullAtomTag, pulledAtomStats.atom_id());
731 EXPECT_EQ(numErrors, pulledAtomStats.atom_error_count());
732 }
733
TEST(StatsdStatsTest,TestAtomDroppedStats)734 TEST(StatsdStatsTest, TestAtomDroppedStats) {
735 StatsdStats stats;
736
737 const int pushAtomTag = 100;
738 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
739
740 const int numDropped = 10;
741 for (int i = 0; i < numDropped; i++) {
742 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, false);
743 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, false);
744 }
745
746 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true);
747
748 ASSERT_EQ(0, stats.mPushedAtomDropsStats.size());
749
750 // Check dropped_count = numDropped for push atoms
751 ASSERT_EQ(2, report.atom_stats_size());
752
753 const auto& pushedAtomStats = report.atom_stats(0);
754 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
755 EXPECT_EQ(numDropped, pushedAtomStats.count());
756 EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
757 EXPECT_FALSE(pushedAtomStats.has_error_count());
758 EXPECT_FALSE(pushedAtomStats.has_skip_count());
759
760 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
761 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
762 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.count());
763 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
764 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
765 EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count());
766 }
767
TEST(StatsdStatsTest,TestQueueStats)768 TEST(StatsdStatsTest, TestQueueStats) {
769 StatsdStats stats;
770
771 stats.noteEventQueueSize(100, 1000);
772 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true);
773
774 ASSERT_EQ(100, report.event_queue_stats().max_size_observed());
775 ASSERT_EQ(1000, report.event_queue_stats().max_size_observed_elapsed_nanos());
776 }
777
TEST(StatsdStatsTest,TestAtomLoggedAndDroppedStats)778 TEST(StatsdStatsTest, TestAtomLoggedAndDroppedStats) {
779 StatsdStats stats;
780
781 const int pushAtomTag = 100;
782 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
783
784 const int numLogged = 10;
785 for (int i = 0; i < numLogged; i++) {
786 stats.noteAtomLogged(pushAtomTag, /*timeSec*/ 0, false);
787 stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec*/ 0, false);
788 }
789
790 const int numDropped = 10;
791 for (int i = 0; i < numDropped; i++) {
792 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, false);
793 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, false);
794 }
795
796 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
797
798 // Check dropped_count = numDropped for push atoms
799 ASSERT_EQ(2, report.atom_stats_size());
800
801 const auto& pushedAtomStats = report.atom_stats(0);
802 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
803 EXPECT_EQ(numLogged + numDropped, pushedAtomStats.count());
804 EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
805 EXPECT_FALSE(pushedAtomStats.has_error_count());
806 EXPECT_FALSE(pushedAtomStats.has_skip_count());
807
808 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
809 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
810 EXPECT_EQ(numLogged + numDropped, nonPlatformPushedAtomStats.count());
811 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
812 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
813 EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count());
814 }
815
TEST(StatsdStatsTest,TestAtomSkippedStats)816 TEST(StatsdStatsTest, TestAtomSkippedStats) {
817 StatsdStats stats;
818
819 const int pushAtomTag = 100;
820 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
821 const int numSkipped = 10;
822
823 for (int i = 0; i < numSkipped; i++) {
824 stats.noteAtomLogged(pushAtomTag, /*timeSec=*/0, /*isSkipped*/ true);
825 stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec=*/0, /*isSkipped*/ true);
826 }
827
828 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
829
830 // Check skip_count = numSkipped for push atoms
831 ASSERT_EQ(2, report.atom_stats_size());
832
833 const auto& pushedAtomStats = report.atom_stats(0);
834 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
835 EXPECT_EQ(numSkipped, pushedAtomStats.count());
836 EXPECT_EQ(numSkipped, pushedAtomStats.skip_count());
837 EXPECT_FALSE(pushedAtomStats.has_error_count());
838
839 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
840 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
841 EXPECT_EQ(numSkipped, nonPlatformPushedAtomStats.count());
842 EXPECT_EQ(numSkipped, nonPlatformPushedAtomStats.skip_count());
843 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
844 }
845
TEST(StatsdStatsTest,TestAtomLoggedAndDroppedAndSkippedStats)846 TEST(StatsdStatsTest, TestAtomLoggedAndDroppedAndSkippedStats) {
847 StatsdStats stats;
848
849 const int pushAtomTag = 100;
850 const int nonPlatformPushAtomTag = StatsdStats::kMaxPushedAtomId + 100;
851
852 const int numLogged = 10;
853 for (int i = 0; i < numLogged; i++) {
854 stats.noteAtomLogged(pushAtomTag, /*timeSec*/ 0, false);
855 stats.noteAtomLogged(nonPlatformPushAtomTag, /*timeSec*/ 0, false);
856 }
857
858 const int numDropped = 10;
859 for (int i = 0; i < numDropped; i++) {
860 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, pushAtomTag, true);
861 stats.noteEventQueueOverflow(/*oldestEventTimestampNs*/ 0, nonPlatformPushAtomTag, true);
862 }
863
864 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
865
866 // Check dropped_count = numDropped for push atoms
867 ASSERT_EQ(2, report.atom_stats_size());
868
869 const auto& pushedAtomStats = report.atom_stats(0);
870 EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
871 EXPECT_EQ(numLogged + numDropped, pushedAtomStats.count());
872 EXPECT_EQ(numDropped, pushedAtomStats.dropped_count());
873 EXPECT_EQ(numDropped, pushedAtomStats.skip_count());
874 EXPECT_FALSE(pushedAtomStats.has_error_count());
875
876 const auto& nonPlatformPushedAtomStats = report.atom_stats(1);
877 EXPECT_EQ(nonPlatformPushAtomTag, nonPlatformPushedAtomStats.tag());
878 EXPECT_EQ(numLogged + numDropped, nonPlatformPushedAtomStats.count());
879 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.dropped_count());
880 EXPECT_EQ(numDropped, nonPlatformPushedAtomStats.skip_count());
881 EXPECT_FALSE(nonPlatformPushedAtomStats.has_error_count());
882 }
883
TEST(StatsdStatsTest,TestShardOffsetProvider)884 TEST(StatsdStatsTest, TestShardOffsetProvider) {
885 StatsdStats stats;
886 ShardOffsetProvider::getInstance().setShardOffset(15);
887
888 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
889 EXPECT_EQ(report.shard_offset(), 15);
890 }
891
TEST(StatsdStatsTest,TestHasHitDimensionGuardrail)892 TEST(StatsdStatsTest, TestHasHitDimensionGuardrail) {
893 StatsdStats stats;
894 int metricId1 = 1;
895 int metricId2 = 2;
896 int metricId3 = 3;
897
898 stats.noteBucketCount(metricId2);
899 stats.noteHardDimensionLimitReached(metricId3);
900
901 // No AtomMetricStats.
902 EXPECT_FALSE(stats.hasHitDimensionGuardrail(metricId1));
903
904 // Has AtomMetricStats but hasn't hit dimension guardrail.
905 EXPECT_FALSE(stats.hasHitDimensionGuardrail(metricId2));
906
907 // Has hit dimension guardrail.
908 EXPECT_TRUE(stats.hasHitDimensionGuardrail(metricId3));
909 }
910
TEST(StatsdStatsTest,TestSubscriptionStarted)911 TEST(StatsdStatsTest, TestSubscriptionStarted) {
912 StatsdStats stats;
913
914 stats.noteSubscriptionStarted(/* id */ 1, /* pushedCount */ 3, /* pulledCount */ 1);
915
916 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
917
918 auto subscriptionStats = report.subscription_stats();
919 EXPECT_EQ(subscriptionStats.pull_thread_wakeup_count(), 0);
920 ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), 1);
921 auto perSubscriptionStats = subscriptionStats.per_subscription_stats(0);
922 EXPECT_EQ(perSubscriptionStats.pushed_atom_count(), 3);
923 EXPECT_EQ(perSubscriptionStats.pulled_atom_count(), 1);
924 EXPECT_GT(perSubscriptionStats.start_time_sec(), 0);
925 EXPECT_FALSE(perSubscriptionStats.has_end_time_sec());
926 EXPECT_EQ(perSubscriptionStats.flush_count(), 0);
927 }
928
TEST(StatsdStatsTest,TestSubscriptionFlushed)929 TEST(StatsdStatsTest, TestSubscriptionFlushed) {
930 StatsdStats stats;
931
932 stats.noteSubscriptionStarted(/* id */ 1, /* pushedCount */ 3, /* pulledCount */ 1);
933 stats.noteSubscriptionFlushed(/* id */ 1);
934
935 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
936
937 auto subscriptionStats = report.subscription_stats();
938 ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), 1);
939 auto perSubscriptionStats = subscriptionStats.per_subscription_stats(0);
940 EXPECT_EQ(perSubscriptionStats.flush_count(), 1);
941 }
942
TEST(StatsdStatsTest,TestSubscriptionEnded)943 TEST(StatsdStatsTest, TestSubscriptionEnded) {
944 StatsdStats stats;
945
946 stats.noteSubscriptionStarted(/* id */ 1, /* pushedCount */ 3, /* pulledCount */ 1);
947 stats.noteSubscriptionEnded(/* id */ 1);
948
949 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
950
951 auto subscriptionStats = report.subscription_stats();
952 ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), 1);
953 EXPECT_GT(subscriptionStats.per_subscription_stats(0).end_time_sec(), 0);
954 }
955
TEST(StatsdStatsTest,TestSubscriptionAtomPulled)956 TEST(StatsdStatsTest, TestSubscriptionAtomPulled) {
957 StatsdStats stats;
958
959 stats.noteSubscriptionAtomPulled(/* atomId */ 10'001);
960
961 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
962
963 ASSERT_EQ(report.pulled_atom_stats_size(), 1);
964 auto pulledAtomStats = report.pulled_atom_stats(0);
965 EXPECT_EQ(pulledAtomStats.subscription_pull_count(), 1);
966 }
967
TEST(StatsdStatsTest,TestSubscriptionPullThreadWakeup)968 TEST(StatsdStatsTest, TestSubscriptionPullThreadWakeup) {
969 StatsdStats stats;
970
971 stats.noteSubscriptionPullThreadWakeup();
972
973 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
974
975 auto subscriptionStats = report.subscription_stats();
976 EXPECT_EQ(subscriptionStats.pull_thread_wakeup_count(), 1);
977 }
978
TEST(StatsdStatsTest,TestSubscriptionStartedMaxActiveSubscriptions)979 TEST(StatsdStatsTest, TestSubscriptionStartedMaxActiveSubscriptions) {
980 StatsdStats stats;
981
982 const int maxSubs = ShellSubscriber::getMaxSubscriptions();
983
984 // Start more than max # of allowed subscriptions.
985 // maxSub + 1th subscriptions should not have been added.
986 for (int id = 1; id <= maxSubs + 1; id++) {
987 stats.noteSubscriptionStarted(id, /* pushedCount */ 3, /* pulledCount */ 1);
988 }
989
990 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
991
992 auto subscriptionStats = report.subscription_stats();
993 ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), maxSubs);
994 EXPECT_THAT(subscriptionStats.per_subscription_stats(),
995 Not(Contains(Property(&PerSubscriptionStats::id, Eq(maxSubs + 1)))));
996 }
997
TEST(StatsdStatsTest,TestSubscriptionStartedRemoveFinishedSubscription)998 TEST(StatsdStatsTest, TestSubscriptionStartedRemoveFinishedSubscription) {
999 StatsdStats stats;
1000
1001 const int maxSubs = ShellSubscriber::getMaxSubscriptions();
1002
1003 // Start max # of allowed subscriptions
1004 for (int id = 1; id <= maxSubs; id++) {
1005 stats.noteSubscriptionStarted(id, /* pushedCount */ 3, /* pulledCount */ 1);
1006 }
1007
1008 // End subscription with id 5.
1009 stats.noteSubscriptionEnded(/* id */ 5);
1010
1011 // Add one more subscription after we've added max # of subscriptions.
1012 // Subscription wth id 5 should be removed and the new subscription added here should be
1013 // accepted.
1014 stats.noteSubscriptionStarted(maxSubs + 1, /* pushedCount */ 3, /* pulledCount */ 1);
1015
1016 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1017
1018 auto subscriptionStats = report.subscription_stats();
1019 ASSERT_EQ(subscriptionStats.per_subscription_stats_size(), maxSubs);
1020 EXPECT_THAT(subscriptionStats.per_subscription_stats(),
1021 Not(Contains(Property(&PerSubscriptionStats::id, Eq(5)))));
1022 EXPECT_THAT(subscriptionStats.per_subscription_stats(),
1023 Contains(Property(&PerSubscriptionStats::id, Eq(maxSubs + 1))));
1024 }
1025
TEST(StatsdStatsTest,TestEnforceDimensionKeySizeLimit)1026 TEST(StatsdStatsTest, TestEnforceDimensionKeySizeLimit) {
1027 EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(-1),
1028 StatsdStats::kDimensionKeySizeHardLimitMin);
1029 EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(0),
1030 StatsdStats::kDimensionKeySizeHardLimitMin);
1031 EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(500),
1032 StatsdStats::kDimensionKeySizeHardLimitMin);
1033 EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(1000), 1000);
1034 EXPECT_EQ(StatsdStats::clampDimensionKeySizeLimit(3500),
1035 StatsdStats::kDimensionKeySizeHardLimitMax);
1036 }
1037
TEST(StatsdStatsTest,TestSocketLossStats)1038 TEST(StatsdStatsTest, TestSocketLossStats) {
1039 StatsdStats stats;
1040
1041 const int maxLossEvents = StatsdStats::kMaxSocketLossStatsSize;
1042
1043 // Note maxLossEvents + 1
1044 for (int eventId = 0; eventId <= maxLossEvents; eventId++) {
1045 SocketLossInfo info;
1046
1047 info.uid = eventId;
1048 info.firstLossTsNanos = 10 * eventId;
1049 info.lastLossTsNanos = 10 * eventId + 1;
1050
1051 info.atomIds.push_back(eventId * 10);
1052 info.errors.push_back(eventId * 20);
1053 info.counts.push_back(eventId * 30);
1054
1055 stats.noteAtomSocketLoss(info);
1056 }
1057
1058 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1059
1060 auto socketLossStats = report.socket_loss_stats();
1061 ASSERT_EQ(socketLossStats.loss_stats_per_uid().size(), maxLossEvents);
1062
1063 for (int i = 0; i < socketLossStats.loss_stats_per_uid().size(); i++) {
1064 const auto& info = report.socket_loss_stats().loss_stats_per_uid(i);
1065
1066 // due to the very first one with id 0 is popped out from the list ids (index) start from 1
1067 const int index = i + 1;
1068
1069 ASSERT_EQ(info.uid(), index);
1070 ASSERT_EQ(info.first_timestamp_nanos(), 10 * index);
1071 ASSERT_EQ(info.last_timestamp_nanos(), 10 * index + 1);
1072
1073 ASSERT_EQ(info.atom_id_loss_stats().size(), 1);
1074
1075 ASSERT_EQ(info.atom_id_loss_stats(0).atom_id(), index * 10);
1076 ASSERT_EQ(info.atom_id_loss_stats(0).error(), index * 20);
1077 ASSERT_EQ(info.atom_id_loss_stats(0).count(), index * 30);
1078 }
1079 }
1080
TEST(StatsdStatsTest,TestSocketLossStatsOverflowCounter)1081 TEST(StatsdStatsTest, TestSocketLossStatsOverflowCounter) {
1082 StatsdStats stats;
1083
1084 const int uidsCount = 5;
1085 const int lossEventCount = 5;
1086
1087 for (int uid = 0; uid < uidsCount; uid++) {
1088 for (int eventId = 0; eventId < lossEventCount; eventId++) {
1089 SocketLossInfo info;
1090
1091 info.uid = uid;
1092 info.firstLossTsNanos = 10 * eventId;
1093 info.lastLossTsNanos = 10 * eventId + 1;
1094 // the counter value will be accumulated
1095 info.overflowCounter = 1;
1096
1097 info.atomIds.push_back(eventId * 10);
1098 info.errors.push_back(eventId * 20);
1099 info.counts.push_back(eventId * 30);
1100
1101 stats.noteAtomSocketLoss(info);
1102 }
1103 }
1104 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1105
1106 auto socketLossStatsOverflowCounters =
1107 report.socket_loss_stats().loss_stats_overflow_counters();
1108 ASSERT_EQ(socketLossStatsOverflowCounters.size(), uidsCount);
1109
1110 for (int i = 0; i < socketLossStatsOverflowCounters.size(); i++) {
1111 const auto& counters = report.socket_loss_stats().loss_stats_overflow_counters(i);
1112
1113 ASSERT_EQ(counters.uid(), i);
1114 ASSERT_EQ(counters.count(), lossEventCount);
1115 }
1116 }
1117
TEST(StatsdStatsTest,TestSocketBatchReadStats)1118 TEST(StatsdStatsTest, TestSocketBatchReadStats) {
1119 unordered_map<int32_t, int32_t> empty;
1120 unordered_map<int32_t, int32_t> m1199 = {{1, 1}, {2, 1190}, {3, 8}}; // only 2 should show up
1121 unordered_map<int32_t, int32_t> m1200 = {{1, 1}, {2, 4}, {3, 8}}; // none should show up
1122 unordered_map<int32_t, int32_t> m120000 = {{1, 1000}, {2, 2000}, {3, 800}}; // all show up
1123 StatsdStats stats;
1124 stats.noteBatchSocketRead(1, 0, 0, 0, 0, empty); // bin 1
1125 stats.noteBatchSocketRead(2, 0, 0, 0, 0, empty); // bin 2
1126 stats.noteBatchSocketRead(2, 0, 0, 0, 0, empty); // bin 2
1127 stats.noteBatchSocketRead(4, 0, 0, 0, 0, empty); // bin 4
1128 stats.noteBatchSocketRead(5, 0, 0, 0, 0, empty); // bin 5
1129 stats.noteBatchSocketRead(9, 0, 0, 0, 0, empty); // bin 5
1130 stats.noteBatchSocketRead(9, 0, 0, 0, 0, empty); // bin 5
1131 stats.noteBatchSocketRead(10, 0, 0, 0, 0, empty); // bin 6
1132 stats.noteBatchSocketRead(19, 0, 0, 0, 0, empty); // bin 6
1133 stats.noteBatchSocketRead(30, 0, 0, 0, 0, empty); // bin 8
1134 stats.noteBatchSocketRead(32, 0, 0, 0, 0, empty); // bin 8
1135 stats.noteBatchSocketRead(39, 0, 0, 0, 0, empty); // bin 8
1136 stats.noteBatchSocketRead(90, 0, 0, 0, 0, empty); // bin 14
1137 stats.noteBatchSocketRead(99, 0, 0, 0, 0, empty); // bin 14
1138 stats.noteBatchSocketRead(100, 0, 0, 0, 0, empty); // bin 15
1139 stats.noteBatchSocketRead(100, 0, 0, 0, 0, empty); // bin 15
1140 stats.noteBatchSocketRead(199, 0, 0, 0, 0, empty); // bin 15
1141 stats.noteBatchSocketRead(200, 0, 0, 0, 0, empty); // bin 16
1142 stats.noteBatchSocketRead(299, 0, 0, 0, 0, empty); // bin 16
1143 stats.noteBatchSocketRead(999, 0, 0, 0, 0, empty); // bin 23
1144 stats.noteBatchSocketRead(1000, 0, 0, 0, 0, empty); // bin 24
1145 stats.noteBatchSocketRead(1199, 1, 2, 3, 4, m1199); // bin 24
1146 stats.noteBatchSocketRead(1200, 5, 6, 7, 8, m1200); // bin 25
1147 stats.noteBatchSocketRead(1800, 0, 0, 0, 0, empty); // bin 28
1148 stats.noteBatchSocketRead(1999, 0, 0, 0, 0, empty); // bin 28
1149 stats.noteBatchSocketRead(2000, 0, 0, 0, 0, empty); // bin 29
1150 stats.noteBatchSocketRead(120000, 10, INT64_MAX, 50, INT64_MAX, m120000); // bin 29
1151
1152 StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ false);
1153 EXPECT_THAT(report.socket_read_stats().batched_read_size(),
1154 ElementsAre(0, 1, 2, 0, 1, 3, 2, 0, 3, 0, 0, 0, 0, 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, 1,
1155 2, 1, 0, 0, 2, 2));
1156
1157 // Check the large batch stats
1158 ASSERT_EQ(report.socket_read_stats().large_batch_read_stats_size(), 7);
1159 auto largeBatchStats = report.socket_read_stats().large_batch_read_stats(1); // 1199
1160 EXPECT_EQ(largeBatchStats.total_atoms_read(), 1199);
1161 EXPECT_EQ(largeBatchStats.last_read_time_elapsed_ns(), 1);
1162 EXPECT_EQ(largeBatchStats.curr_read_time_elapsed_ns(), 2);
1163 EXPECT_EQ(largeBatchStats.min_atom_time_elapsed_ns(), 3);
1164 EXPECT_EQ(largeBatchStats.max_atom_time_elapsed_ns(), 4);
1165 ASSERT_EQ(largeBatchStats.atom_stats_size(), 1);
1166 EXPECT_EQ(largeBatchStats.atom_stats(0).atom_id(), 2);
1167 EXPECT_EQ(largeBatchStats.atom_stats(0).count(), 1190);
1168
1169 largeBatchStats = report.socket_read_stats().large_batch_read_stats(2); // 1200
1170 EXPECT_EQ(largeBatchStats.total_atoms_read(), 1200);
1171 EXPECT_EQ(largeBatchStats.last_read_time_elapsed_ns(), 5);
1172 EXPECT_EQ(largeBatchStats.curr_read_time_elapsed_ns(), 6);
1173 EXPECT_EQ(largeBatchStats.min_atom_time_elapsed_ns(), 7);
1174 EXPECT_EQ(largeBatchStats.max_atom_time_elapsed_ns(), 8);
1175 ASSERT_EQ(largeBatchStats.atom_stats_size(), 0);
1176
1177 largeBatchStats = report.socket_read_stats().large_batch_read_stats(6); // 120000
1178 EXPECT_EQ(largeBatchStats.total_atoms_read(), 120000);
1179 EXPECT_EQ(largeBatchStats.last_read_time_elapsed_ns(), 10);
1180 EXPECT_EQ(largeBatchStats.curr_read_time_elapsed_ns(), INT64_MAX);
1181 EXPECT_EQ(largeBatchStats.min_atom_time_elapsed_ns(), 50);
1182 EXPECT_EQ(largeBatchStats.max_atom_time_elapsed_ns(), INT64_MAX);
1183 ASSERT_EQ(largeBatchStats.atom_stats_size(), 3);
1184 EXPECT_EQ(largeBatchStats.atom_stats(0).atom_id(), 3);
1185 EXPECT_EQ(largeBatchStats.atom_stats(0).count(), 800);
1186 EXPECT_EQ(largeBatchStats.atom_stats(1).atom_id(), 2);
1187 EXPECT_EQ(largeBatchStats.atom_stats(1).count(), 2000);
1188 EXPECT_EQ(largeBatchStats.atom_stats(2).atom_id(), 1);
1189 EXPECT_EQ(largeBatchStats.atom_stats(2).count(), 1000);
1190
1191 stats.reset();
1192 report = getStatsdStatsReport(stats, /* reset stats */ false);
1193 EXPECT_THAT(report.socket_read_stats().batched_read_size(),
1194 AllOf(SizeIs(StatsdStats::kNumBinsInSocketBatchReadHistogram), Each(0)));
1195 ASSERT_EQ(report.socket_read_stats().large_batch_read_stats_size(), 0);
1196 }
1197
TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap,TestGetAtomDimensionKeySizeLimits)1198 TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_InMap, TestGetAtomDimensionKeySizeLimits) {
1199 const auto& [atomId, defaultHardLimit] = GetParam();
1200 EXPECT_EQ(StatsdStats::getAtomDimensionKeySizeLimits(atomId, defaultHardLimit),
1201 StatsdStats::kAtomDimensionKeySizeLimitMap.at(atomId));
1202 }
1203
TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap,TestGetAtomDimensionKeySizeLimits)1204 TEST_P(StatsdStatsTest_GetAtomDimensionKeySizeLimit_NotInMap, TestGetAtomDimensionKeySizeLimits) {
1205 const auto& [atomId, defaultHardLimit] = GetParam();
1206 EXPECT_EQ(
1207 StatsdStats::getAtomDimensionKeySizeLimits(atomId, defaultHardLimit),
1208 (std::pair<size_t, size_t>(StatsdStats::kDimensionKeySizeSoftLimit, defaultHardLimit)));
1209 }
1210
1211 } // namespace statsd
1212 } // namespace os
1213 } // namespace android
1214 #else
1215 GTEST_LOG_(INFO) << "This test does nothing.\n";
1216 #endif
1217