diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-01-10 19:01:51 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-01-10 19:01:51 +0000 |
commit | f1e994f48707c8873df54b21c35c97021f7f0042 (patch) | |
tree | 15cc6c86634152ed0f749e86e2073619182b0293 | |
parent | 9d4097eb0548c080ff0ce91eb413083ded40e678 (diff) | |
parent | d2d81490a87d353c8070885791eff55235c7b5cf (diff) | |
download | StatsD-aml_tz5_341510010.tar.gz |
Snap for 11296156 from d2d81490a87d353c8070885791eff55235c7b5cf to mainline-tzdata5-releaseaml_tz5_341510050aml_tz5_341510010aml_tz5_341510010
Change-Id: If5c6ba514bc5e851ab66e58d6ef78ce96e230b43
126 files changed, 3712 insertions, 1695 deletions
diff --git a/lib/libstatsgtestmatchers/include/gtest_matchers.h b/lib/libstatsgtestmatchers/include/gtest_matchers.h index 084346dd..3d9b792b 100644 --- a/lib/libstatsgtestmatchers/include/gtest_matchers.h +++ b/lib/libstatsgtestmatchers/include/gtest_matchers.h @@ -206,13 +206,30 @@ TYPE_PRINTER(CpuActiveTime, EQ_MATCHER(PluggedStateChanged, PROPERTY_EQ(PluggedStateChanged, state)); TYPE_PRINTER(PluggedStateChanged, PROPERTY_PRINT(state)); +EQ_MATCHER(WakelockStateChanged, + REPEATED_PROPERTY_MATCHER(WakelockStateChanged, attribution_node, EqAttributionNode), + PROPERTY_EQ(WakelockStateChanged, type), + PROPERTY_EQ(WakelockStateChanged, tag), + PROPERTY_EQ(WakelockStateChanged, state), + PROPERTY_EQ(WakelockStateChanged, process_state) +); +TYPE_PRINTER(WakelockStateChanged, + REPEATED_PROPERTY_PRINT(attribution_node) + PROPERTY_PRINT(type) + PROPERTY_PRINT(tag) + PROPERTY_PRINT(state) + PROPERTY_PRINT(process_state) +); + EQ_MATCHER(Atom, PROPERTY_MATCHER(Atom, screen_state_changed, EqScreenStateChanged), - PROPERTY_MATCHER(Atom, test_atom_reported, EqTestAtomReported) + PROPERTY_MATCHER(Atom, test_atom_reported, EqTestAtomReported), + PROPERTY_MATCHER(Atom, wakelock_state_changed, EqWakelockStateChanged) ); TYPE_PRINTER(Atom, PROPERTY_PRINT(screen_state_changed) PROPERTY_PRINT(test_atom_reported) + PROPERTY_PRINT(wakelock_state_changed) ); EQ_MATCHER(ShellData, diff --git a/lib/libstatspull/libstatspull.map.txt b/lib/libstatspull/libstatspull.map.txt index 30641e47..a76342c9 100644 --- a/lib/libstatspull/libstatspull.map.txt +++ b/lib/libstatspull/libstatspull.map.txt @@ -1,21 +1,21 @@ LIBSTATSPULL { global: - AStatsManager_PullAtomMetadata_obtain; # apex # introduced=30 - AStatsManager_PullAtomMetadata_release; # apex # introduced=30 - AStatsManager_PullAtomMetadata_setCoolDownMillis; # apex # introduced=30 - AStatsManager_PullAtomMetadata_getCoolDownMillis; # apex # introduced=30 - AStatsManager_PullAtomMetadata_setTimeoutMillis; # apex # introduced=30 - AStatsManager_PullAtomMetadata_getTimeoutMillis; # apex # introduced=30 - AStatsManager_PullAtomMetadata_setAdditiveFields; # apex # introduced=30 - AStatsManager_PullAtomMetadata_getNumAdditiveFields; # apex # introduced=30 - AStatsManager_PullAtomMetadata_getAdditiveFields; # apex # introduced=30 - AStatsEventList_addStatsEvent; # apex # introduced=30 - AStatsManager_setPullAtomCallback; # apex # introduced=30 - AStatsManager_clearPullAtomCallback; # apex # introduced=30 + AStatsManager_PullAtomMetadata_obtain; # apex introduced=30 + AStatsManager_PullAtomMetadata_release; # apex introduced=30 + AStatsManager_PullAtomMetadata_setCoolDownMillis; # apex introduced=30 + AStatsManager_PullAtomMetadata_getCoolDownMillis; # apex introduced=30 + AStatsManager_PullAtomMetadata_setTimeoutMillis; # apex introduced=30 + AStatsManager_PullAtomMetadata_getTimeoutMillis; # apex introduced=30 + AStatsManager_PullAtomMetadata_setAdditiveFields; # apex introduced=30 + AStatsManager_PullAtomMetadata_getNumAdditiveFields; # apex introduced=30 + AStatsManager_PullAtomMetadata_getAdditiveFields; # apex introduced=30 + AStatsEventList_addStatsEvent; # apex introduced=30 + AStatsManager_setPullAtomCallback; # apex introduced=30 + AStatsManager_clearPullAtomCallback; # apex introduced=30 - AStatsManager_addSubscription; # apex # introduced=UpsideDownCake - AStatsManager_removeSubscription; # apex # introduced=UpsideDownCake - AStatsManager_flushSubscription; # apex # introduced=UpsideDownCake + AStatsManager_addSubscription; # apex introduced=UpsideDownCake + AStatsManager_removeSubscription; # apex introduced=UpsideDownCake + AStatsManager_flushSubscription; # apex introduced=UpsideDownCake local: *; }; diff --git a/lib/libstatssocket/libstatssocket.map.txt b/lib/libstatssocket/libstatssocket.map.txt index aa6eb305..f48e1595 100644 --- a/lib/libstatssocket/libstatssocket.map.txt +++ b/lib/libstatssocket/libstatssocket.map.txt @@ -1,25 +1,25 @@ LIBSTATSSOCKET { global: - AStatsEvent_obtain; # apex # introduced=30 - AStatsEvent_build; # apex # introduced=30 - AStatsEvent_write; # apex # introduced=30 - AStatsEvent_release; # apex # introduced=30 - AStatsEvent_setAtomId; # apex # introduced=30 - AStatsEvent_writeInt32; # apex # introduced=30 - AStatsEvent_writeInt64; # apex # introduced=30 - AStatsEvent_writeFloat; # apex # introduced=30 - AStatsEvent_writeBool; # apex # introduced=30 - AStatsEvent_writeByteArray; # apex # introduced=30 - AStatsEvent_writeString; # apex # introduced=30 - AStatsEvent_writeAttributionChain; # apex # introduced=30 - AStatsEvent_writeInt32Array; # apex # introduced=Tiramisu - AStatsEvent_writeInt64Array; # apex # introduced=Tiramisu - AStatsEvent_writeFloatArray; # apex # introduced=Tiramisu - AStatsEvent_writeBoolArray; # apex # introduced=Tiramisu - AStatsEvent_writeStringArray; # apex # introduced=Tiramisu - AStatsEvent_addBoolAnnotation; # apex # introduced=30 - AStatsEvent_addInt32Annotation; # apex # introduced=30 - AStatsSocket_close; # apex # introduced=30 + AStatsEvent_obtain; # apex introduced=30 + AStatsEvent_build; # apex introduced=30 + AStatsEvent_write; # apex introduced=30 + AStatsEvent_release; # apex introduced=30 + AStatsEvent_setAtomId; # apex introduced=30 + AStatsEvent_writeInt32; # apex introduced=30 + AStatsEvent_writeInt64; # apex introduced=30 + AStatsEvent_writeFloat; # apex introduced=30 + AStatsEvent_writeBool; # apex introduced=30 + AStatsEvent_writeByteArray; # apex introduced=30 + AStatsEvent_writeString; # apex introduced=30 + AStatsEvent_writeAttributionChain; # apex introduced=30 + AStatsEvent_writeInt32Array; # apex introduced=Tiramisu + AStatsEvent_writeInt64Array; # apex introduced=Tiramisu + AStatsEvent_writeFloatArray; # apex introduced=Tiramisu + AStatsEvent_writeBoolArray; # apex introduced=Tiramisu + AStatsEvent_writeStringArray; # apex introduced=Tiramisu + AStatsEvent_addBoolAnnotation; # apex introduced=30 + AStatsEvent_addInt32Annotation; # apex introduced=30 + AStatsSocket_close; # apex introduced=30 local: *; }; diff --git a/lib/libstatssocket/utils.h b/lib/libstatssocket/utils.h index be1339e1..1eada991 100644 --- a/lib/libstatssocket/utils.h +++ b/lib/libstatssocket/utils.h @@ -18,6 +18,7 @@ #include <stddef.h> #include <stdint.h> +#include <sys/cdefs.h> __BEGIN_DECLS diff --git a/statsd/Android.bp b/statsd/Android.bp index e39c77bd..0373bf10 100644 --- a/statsd/Android.bp +++ b/statsd/Android.bp @@ -116,6 +116,7 @@ cc_defaults { "server_configurable_flags", "statsd-aidl-ndk", "libsqlite_static_noicu", + "libstats_regex", ], shared_libs: [ "libbinder_ndk", @@ -231,13 +232,60 @@ cc_binary { min_sdk_version: "30", } +cc_defaults { + name: "statsd_test_defaults", + defaults: ["statsd_defaults"], + srcs: [ + // atom_field_options.proto needs field_options.proto, but that is + // not included in libprotobuf-cpp-lite, so compile it here. + ":libprotobuf-internal-protos", + ":libstats_internal_protos", + + "src/shell/shell_data.proto", + "src/stats_log.proto", + ], + cflags: [ + "-Wall", + "-Werror", + "-Wno-enum-compare", + "-Wno-missing-field-initializers", + "-Wno-unused-function", + "-Wno-unused-parameter", + "-Wno-unused-variable", + ], + static_libs: [ + "libgmock", + "libstatslog_statsdtest", + "libstatssocket_private", + ], + proto: { + type: "lite", + include_dirs: [ + "external/protobuf/src", + "frameworks/proto_logging/stats", + ], + static: true, + }, +} + +cc_library_static { + name: "libstats_test_utils", + defaults: ["statsd_test_defaults"], + srcs: [ + "tests/statsd_test_util.cpp", + ], + tidy_timeout_srcs: [ + "tests/statsd_test_util.cpp", + ], +} + // ============== // statsd_test // ============== cc_test { name: "statsd_test", - defaults: ["statsd_defaults"], + defaults: ["statsd_test_defaults"], test_suites: [ "device-tests", "mts-statsd", @@ -256,16 +304,6 @@ cc_test { }, }, - cflags: [ - "-Wall", - "-Werror", - "-Wno-enum-compare", - "-Wno-missing-field-initializers", - "-Wno-unused-function", - "-Wno-unused-parameter", - "-Wno-unused-variable", - ], - require_root: true, tidy_timeout_srcs: [ @@ -300,19 +338,11 @@ cc_test { "tests/metrics/parsing_utils/config_update_utils_test.cpp", "tests/metrics/parsing_utils/metrics_manager_util_test.cpp", "tests/state/StateTracker_test.cpp", - "tests/statsd_test_util.cpp", "tests/StatsLogProcessor_test.cpp", "tests/UidMap_test.cpp", ], srcs: [ - // atom_field_options.proto needs field_options.proto, but that is - // not included in libprotobuf-cpp-lite, so compile it here. - ":libprotobuf-internal-protos", - ":libstats_internal_protos", - - "src/shell/shell_data.proto", - "src/stats_log.proto", "tests/AlarmMonitor_test.cpp", "tests/anomaly/AlarmTracker_test.cpp", "tests/anomaly/AnomalyTracker_test.cpp", @@ -337,9 +367,10 @@ cc_test { "tests/e2e/MetricConditionLink_e2e_test.cpp", "tests/e2e/PartialBucket_e2e_test.cpp", "tests/e2e/RestrictedConfig_e2e_test.cpp", + "tests/e2e/RestrictedEventMetric_e2e_test.cpp", + "tests/e2e/StringReplace_e2e_test.cpp", "tests/e2e/ValueMetric_pull_e2e_test.cpp", "tests/e2e/WakelockDuration_e2e_test.cpp", - "tests/e2e/RestrictedEventMetric_e2e_test.cpp", "tests/external/puller_util_test.cpp", "tests/external/StatsCallbackPuller_test.cpp", "tests/external/StatsPuller_test.cpp", @@ -370,7 +401,6 @@ cc_test { "tests/MetricsManager_test.cpp", "tests/shell/ShellSubscriber_test.cpp", "tests/state/StateTracker_test.cpp", - "tests/statsd_test_util.cpp", "tests/statsd_test_util_test.cpp", "tests/SocketListener_test.cpp", "tests/StatsLogProcessor_test.cpp", @@ -382,20 +412,10 @@ cc_test { ], static_libs: [ - "libgmock", "libstatsgtestmatchers", - "libstatslog_statsdtest", - "libstatssocket_private", + "libstats_test_utils", ], - proto: { - type: "lite", - include_dirs: [ - "external/protobuf/src", - "frameworks/proto_logging/stats", - ], - static: true, - }, min_sdk_version: "30", } @@ -406,14 +426,10 @@ cc_test { cc_benchmark { name: "statsd_benchmark", - defaults: ["statsd_defaults"], + defaults: ["statsd_test_defaults"], srcs: [ - // atom_field_options.proto needs field_options.proto, but that is - // not included in libprotobuf-cpp-lite, so compile it here. - ":libprotobuf-internal-protos", - ":libstats_internal_protos", - + "benchmark/data_structures_benchmark.cpp", "benchmark/db_benchmark.cpp", "benchmark/duration_metric_benchmark.cpp", "benchmark/filter_value_benchmark.cpp", @@ -422,43 +438,32 @@ cc_benchmark { "benchmark/log_event_benchmark.cpp", "benchmark/log_event_filter_benchmark.cpp", "benchmark/main.cpp", - "benchmark/metric_util.cpp", + "benchmark/on_log_event_benchmark.cpp", "benchmark/stats_write_benchmark.cpp", "benchmark/loss_info_container_benchmark.cpp", - "src/stats_log.proto", ], - proto: { - type: "lite", - include_dirs: [ - "external/protobuf/src", - "frameworks/proto_logging/stats", - ], - }, - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wno-unused-variable", - "-Wno-unused-function", - // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374 "-Wno-varargs", ], static_libs: [ - "libplatformprotos", - "libstatssocket_private", - ], - - shared_libs: [ - "libprotobuf-cpp-lite", - "libstatslog", + "libgtest", + "libstats_test_utils", ], +} - header_libs: [ - "libgtest_prod_headers", +// Build regex support in a separate library to catch std::regex_error exception. +cc_library_static { + name: "libstats_regex", + srcs: ["lib/stats_regex.cpp"], + cppflags: ["-fexceptions"], + static_libs: ["libbase"], + min_sdk_version: "30", + apex_available: [ + "com.android.os.statsd", + "test_com.android.os.statsd", ], } @@ -551,6 +556,37 @@ filegroup { ], } +cc_fuzz { + name: "statsd_service_fuzzer", + defaults: [ + "statsd_defaults", + "service_fuzzer_defaults", + ], + srcs: [ + "fuzzers/statsd_service_fuzzer.cpp" + ], + shared_libs: [ + "libstatssocket", + "libvndksupport", + ], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wno-unused-parameter", + ], + fuzz_config: { + cc: [ + "singhtejinder@google.com", + "sharaienko@google.com", + ] + }, + proto: { + type: "lite", + static: true, + }, +} + // Filegroup for subscription protos. filegroup { name: "libstats_subscription_protos", diff --git a/statsd/benchmark/data_structures_benchmark.cpp b/statsd/benchmark/data_structures_benchmark.cpp new file mode 100644 index 00000000..5ee451c5 --- /dev/null +++ b/statsd/benchmark/data_structures_benchmark.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <cstdlib> +#include <ctime> +#include <vector> + +#include "benchmark/benchmark.h" + +namespace android { +namespace os { +namespace statsd { + +namespace { + +template <typename ContainerType> +void benchmarkFunctionForVector(std::vector<ContainerType>& vec, int capacity) { + ContainerType result = false; + for (int i = 0; i < capacity; i++) { + vec[i] = !result; + result = !result; + } + + int resultInt = 0; + for (int i = 0; i < capacity; i++) { + resultInt += vec[i]; + } + + // Make sure the variable is not optimized away by compiler + benchmark::DoNotOptimize(vec); + benchmark::DoNotOptimize(resultInt); +} + +template <typename ContainerType> +void benchmarkStdFillForVector(std::vector<ContainerType>& vec, int capacity) { + std::fill(vec.begin(), vec.end(), true); + int resultInt = 0; + for (int i = 0; i < capacity; i++) { + resultInt += vec[i]; + } + + // Make sure the variable is not optimized away by compiler + benchmark::DoNotOptimize(vec); + benchmark::DoNotOptimize(resultInt); +} + +} // namespace + +static void BM_BasicVectorBoolUsage(benchmark::State& state) { + const int capacity = state.range(0); + std::vector<bool> vec(capacity); + + while (state.KeepRunning()) { + benchmarkFunctionForVector<bool>(vec, capacity); + } +} +BENCHMARK(BM_BasicVectorBoolUsage)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100}); + +static void BM_VectorBoolStdFill(benchmark::State& state) { + const int capacity = state.range(0); + std::vector<bool> vec(capacity); + + while (state.KeepRunning()) { + benchmarkStdFillForVector<bool>(vec, capacity); + } +} +BENCHMARK(BM_VectorBoolStdFill)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100}); + +static void BM_BasicVectorInt8Usage(benchmark::State& state) { + const int capacity = state.range(0); + std::vector<int8_t> vec(capacity); + + while (state.KeepRunning()) { + benchmarkFunctionForVector<int8_t>(vec, capacity); + } +} +BENCHMARK(BM_BasicVectorInt8Usage)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100}); + +static void BM_VectorInt8StdFill(benchmark::State& state) { + const int capacity = state.range(0); + std::vector<int8_t> vec(capacity); + + while (state.KeepRunning()) { + benchmarkStdFillForVector<int8_t>(vec, capacity); + } +} +BENCHMARK(BM_VectorInt8StdFill)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100}); + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/statsd/benchmark/db_benchmark.cpp b/statsd/benchmark/db_benchmark.cpp index ebe751a2..b9b16949 100644 --- a/statsd/benchmark/db_benchmark.cpp +++ b/statsd/benchmark/db_benchmark.cpp @@ -15,7 +15,7 @@ */ #include "benchmark/benchmark.h" -#include "metric_util.h" +#include "tests/statsd_test_util.h" #include "utils/DbUtils.h" using namespace std; diff --git a/statsd/benchmark/duration_metric_benchmark.cpp b/statsd/benchmark/duration_metric_benchmark.cpp index 2d315d93..a87b5eed 100644 --- a/statsd/benchmark/duration_metric_benchmark.cpp +++ b/statsd/benchmark/duration_metric_benchmark.cpp @@ -14,12 +14,13 @@ * limitations under the License. */ #include <vector> -#include "benchmark/benchmark.h" + #include "FieldValue.h" #include "HashableDimensionKey.h" +#include "benchmark/benchmark.h" #include "logd/LogEvent.h" #include "stats_log_util.h" -#include "metric_util.h" +#include "tests/statsd_test_util.h" namespace android { namespace os { @@ -39,15 +40,15 @@ static StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( auto scheduledJobPredicate = CreateScheduledJobPredicate(); auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - dimensions->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); + dimensions->set_field(util::SCHEDULED_JOB_STATE_CHANGED); dimensions->add_child()->set_field(2); // job name field. auto screenIsOffPredicate = CreateScreenIsOffPredicate(); auto isSyncingPredicate = CreateIsSyncingPredicate(); auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidAndTagDimensions(android::util::SYNC_STATE_CHANGED, - {Position::FIRST}); + *syncDimension = + CreateAttributionUidAndTagDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST}); if (addExtraDimensionInCondition) { syncDimension->add_child()->set_field(2 /* name field*/); } @@ -68,10 +69,10 @@ static StatsdConfig CreateDurationMetricConfig_NoLink_AND_CombinationCondition( metric->set_condition(combinationPredicate->id()); metric->set_aggregation_type(aggregationType); auto dimensionWhat = metric->mutable_dimensions_in_what(); - dimensionWhat->set_field(android::util::SCHEDULED_JOB_STATE_CHANGED); + dimensionWhat->set_field(util::SCHEDULED_JOB_STATE_CHANGED); dimensionWhat->add_child()->set_field(2); // job name field. - *metric->mutable_dimensions_in_condition() = CreateAttributionUidAndTagDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + *metric->mutable_dimensions_in_condition() = + CreateAttributionUidAndTagDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST}); return config; } @@ -87,14 +88,13 @@ static StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition( auto scheduledJobPredicate = CreateScheduledJobPredicate(); auto dimensions = scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions(); - *dimensions = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); + *dimensions = + CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); dimensions->add_child()->set_field(2); // job name field. auto isSyncingPredicate = CreateIsSyncingPredicate(); auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions(); - *syncDimension = CreateAttributionUidDimensions( - android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + *syncDimension = CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST}); if (addExtraDimensionInCondition) { syncDimension->add_child()->set_field(2 /* name field*/); } @@ -116,16 +116,15 @@ static StatsdConfig CreateDurationMetricConfig_Link_AND_CombinationCondition( metric->set_what(scheduledJobPredicate.id()); metric->set_condition(combinationPredicate->id()); metric->set_aggregation_type(aggregationType); - *metric->mutable_dimensions_in_what() = CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); + *metric->mutable_dimensions_in_what() = + CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); auto links = metric->add_links(); links->set_condition(isSyncingPredicate.id()); *links->mutable_fields_in_what() = - CreateAttributionUidDimensions( - android::util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); + CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST}); *links->mutable_fields_in_condition() = - CreateAttributionUidDimensions(android::util::SYNC_STATE_CHANGED, {Position::FIRST}); + CreateAttributionUidDimensions(util::SYNC_STATE_CHANGED, {Position::FIRST}); return config; } @@ -208,8 +207,8 @@ static void BM_DurationMetricNoLink(benchmark::State& state) { sortLogEventsByTimestamp(&events); while (state.KeepRunning()) { - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + auto processor = + CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); for (const auto& event : events) { processor->OnLogEvent(event.get()); } @@ -299,8 +298,8 @@ static void BM_DurationMetricLink(benchmark::State& state) { sortLogEventsByTimestamp(&events); while (state.KeepRunning()) { - auto processor = CreateStatsLogProcessor( - bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + auto processor = + CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); for (const auto& event : events) { processor->OnLogEvent(event.get()); } diff --git a/statsd/benchmark/filter_value_benchmark.cpp b/statsd/benchmark/filter_value_benchmark.cpp index 743ccc4e..06420706 100644 --- a/statsd/benchmark/filter_value_benchmark.cpp +++ b/statsd/benchmark/filter_value_benchmark.cpp @@ -19,9 +19,9 @@ #include "HashableDimensionKey.h" #include "benchmark/benchmark.h" #include "logd/LogEvent.h" -#include "metric_util.h" #include "stats_event.h" #include "stats_log_util.h" +#include "tests/statsd_test_util.h" namespace android { namespace os { diff --git a/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp b/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp index 7a455650..99570667 100644 --- a/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp +++ b/statsd/benchmark/get_dimensions_for_condition_benchmark.cpp @@ -19,9 +19,9 @@ #include "HashableDimensionKey.h" #include "benchmark/benchmark.h" #include "logd/LogEvent.h" -#include "metric_util.h" #include "stats_event.h" #include "stats_log_util.h" +#include "tests/statsd_test_util.h" namespace android { namespace os { diff --git a/statsd/benchmark/metric_util.cpp b/statsd/benchmark/metric_util.cpp deleted file mode 100644 index a1e978ac..00000000 --- a/statsd/benchmark/metric_util.cpp +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "metric_util.h" - -#include "stats_event.h" - -namespace android { -namespace os { -namespace statsd { - -AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId) { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId(name)); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(atomId); - return atom_matcher; -} - -AtomMatcher CreateScheduledJobStateChangedAtomMatcher(const string& name, - ScheduledJobStateChanged::State state) { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId(name)); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::SCHEDULED_JOB_STATE_CHANGED); - auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); - field_value_matcher->set_field(3); // State field. - field_value_matcher->set_eq_int(state); - return atom_matcher; -} - -AtomMatcher CreateStartScheduledJobAtomMatcher() { - return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobStart", - ScheduledJobStateChanged::STARTED); -} - -AtomMatcher CreateFinishScheduledJobAtomMatcher() { - return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobFinish", - ScheduledJobStateChanged::FINISHED); -} - -AtomMatcher CreateScreenBrightnessChangedAtomMatcher() { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId("ScreenBrightnessChanged")); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::SCREEN_BRIGHTNESS_CHANGED); - return atom_matcher; -} - -AtomMatcher CreateUidProcessStateChangedAtomMatcher() { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId("UidProcessStateChanged")); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::UID_PROCESS_STATE_CHANGED); - return atom_matcher; -} - -AtomMatcher CreateWakelockStateChangedAtomMatcher(const string& name, - WakelockStateChanged::State state) { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId(name)); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::WAKELOCK_STATE_CHANGED); - auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); - field_value_matcher->set_field(4); // State field. - field_value_matcher->set_eq_int(state); - return atom_matcher; -} - -AtomMatcher CreateAcquireWakelockAtomMatcher() { - return CreateWakelockStateChangedAtomMatcher("AcquireWakelock", WakelockStateChanged::ACQUIRE); -} - -AtomMatcher CreateReleaseWakelockAtomMatcher() { - return CreateWakelockStateChangedAtomMatcher("ReleaseWakelock", WakelockStateChanged::RELEASE); -} - -AtomMatcher CreateScreenStateChangedAtomMatcher( - const string& name, android::view::DisplayStateEnum state) { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId(name)); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::SCREEN_STATE_CHANGED); - auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); - field_value_matcher->set_field(1); // State field. - field_value_matcher->set_eq_int(state); - return atom_matcher; -} - -AtomMatcher CreateScreenTurnedOnAtomMatcher() { - return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", - android::view::DisplayStateEnum::DISPLAY_STATE_ON); -} - -AtomMatcher CreateScreenTurnedOffAtomMatcher() { - return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff", - ::android::view::DisplayStateEnum::DISPLAY_STATE_OFF); -} - -AtomMatcher CreateSyncStateChangedAtomMatcher( - const string& name, SyncStateChanged::State state) { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId(name)); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::SYNC_STATE_CHANGED); - auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); - field_value_matcher->set_field(3); // State field. - field_value_matcher->set_eq_int(state); - return atom_matcher; -} - -AtomMatcher CreateSyncStartAtomMatcher() { - return CreateSyncStateChangedAtomMatcher("SyncStart", SyncStateChanged::ON); -} - -AtomMatcher CreateSyncEndAtomMatcher() { - return CreateSyncStateChangedAtomMatcher("SyncEnd", SyncStateChanged::OFF); -} - -AtomMatcher CreateActivityForegroundStateChangedAtomMatcher( - const string& name, ActivityForegroundStateChanged::State state) { - AtomMatcher atom_matcher; - atom_matcher.set_id(StringToId(name)); - auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher(); - simple_atom_matcher->set_atom_id(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); - auto field_value_matcher = simple_atom_matcher->add_field_value_matcher(); - field_value_matcher->set_field(4); // Activity field. - field_value_matcher->set_eq_int(state); - return atom_matcher; -} - -AtomMatcher CreateMoveToBackgroundAtomMatcher() { - return CreateActivityForegroundStateChangedAtomMatcher( - "MoveToBackground", ActivityForegroundStateChanged::BACKGROUND); -} - -AtomMatcher CreateMoveToForegroundAtomMatcher() { - return CreateActivityForegroundStateChangedAtomMatcher( - "MoveToForeground", ActivityForegroundStateChanged::FOREGROUND); -} - -Predicate CreateScheduledJobPredicate() { - Predicate predicate; - predicate.set_id(StringToId("ScheduledJobRunningPredicate")); - predicate.mutable_simple_predicate()->set_start(StringToId("ScheduledJobStart")); - predicate.mutable_simple_predicate()->set_stop(StringToId("ScheduledJobFinish")); - return predicate; -} - -Predicate CreateBatterySaverModePredicate() { - Predicate predicate; - predicate.set_id(StringToId("BatterySaverIsOn")); - predicate.mutable_simple_predicate()->set_start(StringToId("BatterySaverModeStart")); - predicate.mutable_simple_predicate()->set_stop(StringToId("BatterySaverModeStop")); - return predicate; -} - -Predicate CreateScreenIsOnPredicate() { - Predicate predicate; - predicate.set_id(StringToId("ScreenIsOn")); - predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOn")); - predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOff")); - return predicate; -} - -Predicate CreateScreenIsOffPredicate() { - Predicate predicate; - predicate.set_id(1111123); - predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOff")); - predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOn")); - return predicate; -} - -Predicate CreateHoldingWakelockPredicate() { - Predicate predicate; - predicate.set_id(StringToId("HoldingWakelock")); - predicate.mutable_simple_predicate()->set_start(StringToId("AcquireWakelock")); - predicate.mutable_simple_predicate()->set_stop(StringToId("ReleaseWakelock")); - return predicate; -} - -Predicate CreateIsSyncingPredicate() { - Predicate predicate; - predicate.set_id(33333333333333); - predicate.mutable_simple_predicate()->set_start(StringToId("SyncStart")); - predicate.mutable_simple_predicate()->set_stop(StringToId("SyncEnd")); - return predicate; -} - -Predicate CreateIsInBackgroundPredicate() { - Predicate predicate; - predicate.set_id(StringToId("IsInBackground")); - predicate.mutable_simple_predicate()->set_start(StringToId("MoveToBackground")); - predicate.mutable_simple_predicate()->set_stop(StringToId("MoveToForeground")); - return predicate; -} - -void addPredicateToPredicateCombination(const Predicate& predicate, - Predicate* combinationPredicate) { - combinationPredicate->mutable_combination()->add_predicate(predicate.id()); -} - -FieldMatcher CreateAttributionUidDimensions(const int atomId, - const std::vector<Position>& positions) { - FieldMatcher dimensions; - dimensions.set_field(atomId); - for (const auto position : positions) { - auto child = dimensions.add_child(); - child->set_field(1); - child->set_position(position); - child->add_child()->set_field(1); - } - return dimensions; -} - -FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId, - const std::vector<Position>& positions) { - FieldMatcher dimensions; - dimensions.set_field(atomId); - for (const auto position : positions) { - auto child = dimensions.add_child(); - child->set_field(1); - child->set_position(position); - child->add_child()->set_field(1); - child->add_child()->set_field(2); - } - return dimensions; -} - -FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields) { - FieldMatcher dimensions; - dimensions.set_field(atomId); - for (const int field : fields) { - dimensions.add_child()->set_field(field); - } - return dimensions; -} - -void writeAttribution(AStatsEvent* statsEvent, const vector<int>& attributionUids, - const vector<string>& attributionTags) { - vector<const char*> cTags(attributionTags.size()); - for (int i = 0; i < cTags.size(); i++) { - cTags[i] = attributionTags[i].c_str(); - } - - AStatsEvent_writeAttributionChain(statsEvent, - reinterpret_cast<const uint32_t*>(attributionUids.data()), - cTags.data(), attributionUids.size()); -} - -void parseStatsEventToLogEvent(AStatsEvent* statsEvent, LogEvent* logEvent) { - AStatsEvent_build(statsEvent); - - size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); - logEvent->parseBuffer(buf, size); - - AStatsEvent_release(statsEvent); -} - -std::unique_ptr<LogEvent> CreateScreenStateChangedEvent( - uint64_t timestampNs, const android::view::DisplayStateEnum state) { - AStatsEvent* statsEvent = AStatsEvent_obtain(); - AStatsEvent_setAtomId(statsEvent, util::SCREEN_STATE_CHANGED); - AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); - AStatsEvent_writeInt32(statsEvent, state); - - std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0); - parseStatsEventToLogEvent(statsEvent, logEvent.get()); - return logEvent; -} - -std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent( - const vector<int>& attributionUids, const vector<string>& attributionTags, - const string& jobName, const ScheduledJobStateChanged::State state, uint64_t timestampNs) { - AStatsEvent* statsEvent = AStatsEvent_obtain(); - AStatsEvent_setAtomId(statsEvent, util::SCHEDULED_JOB_STATE_CHANGED); - AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); - - writeAttribution(statsEvent, attributionUids, attributionTags); - AStatsEvent_writeString(statsEvent, jobName.c_str()); - AStatsEvent_writeInt32(statsEvent, state); - - std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0); - parseStatsEventToLogEvent(statsEvent, logEvent.get()); - return logEvent; -} - -std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& jobName) { - return CreateScheduledJobStateChangedEvent(attributionUids, attributionTags, jobName, - ScheduledJobStateChanged::STARTED, timestampNs); -} - -// Create log event when scheduled job finishes. -std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& jobName) { - return CreateScheduledJobStateChangedEvent(attributionUids, attributionTags, jobName, - ScheduledJobStateChanged::FINISHED, timestampNs); -} - -std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& name, - const SyncStateChanged::State state) { - AStatsEvent* statsEvent = AStatsEvent_obtain(); - AStatsEvent_setAtomId(statsEvent, util::SYNC_STATE_CHANGED); - AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); - - writeAttribution(statsEvent, attributionUids, attributionTags); - AStatsEvent_writeString(statsEvent, name.c_str()); - AStatsEvent_writeInt32(statsEvent, state); - - std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0); - parseStatsEventToLogEvent(statsEvent, logEvent.get()); - return logEvent; -} - -std::unique_ptr<LogEvent> CreateSyncStartEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& name) { - return CreateSyncStateChangedEvent(timestampNs, attributionUids, attributionTags, name, - SyncStateChanged::ON); -} - -std::unique_ptr<LogEvent> CreateSyncEndEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& name) { - return CreateSyncStateChangedEvent(timestampNs, attributionUids, attributionTags, name, - SyncStateChanged::OFF); -} - -sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config, - const ConfigKey& key) { - sp<UidMap> uidMap = new UidMap(); - sp<StatsPullerManager> pullerManager = new StatsPullerManager(); - sp<AlarmMonitor> anomalyAlarmMonitor; - sp<AlarmMonitor> periodicAlarmMonitor; - sp<StatsLogProcessor> processor = new StatsLogProcessor( - uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor, - timeBaseSec * NS_PER_SEC, [](const ConfigKey&) { return true; }, - [](const int&, const vector<int64_t>&) { return true; }, - [](const ConfigKey&, const string&, const vector<int64_t>&) {}, - std::make_shared<LogEventFilter>()); - processor->OnConfigUpdated(timeBaseSec * NS_PER_SEC, key, config); - return processor; -} - -void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events) { - std::sort(events->begin(), events->end(), - [](const std::unique_ptr<LogEvent>& a, const std::unique_ptr<LogEvent>& b) { - return a->GetElapsedTimestampNs() < b->GetElapsedTimestampNs(); - }); -} - -int64_t StringToId(const string& str) { - return static_cast<int64_t>(std::hash<std::string>()(str)); -} - - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/statsd/benchmark/metric_util.h b/statsd/benchmark/metric_util.h deleted file mode 100644 index 693bf459..00000000 --- a/statsd/benchmark/metric_util.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include "src/stats_log.pb.h" -#include "src/statsd_config.pb.h" -#include "src/StatsLogProcessor.h" -#include "src/logd/LogEvent.h" -#include "stats_event.h" -#include "statslog.h" - -namespace android { -namespace os { -namespace statsd { - -// Create AtomMatcher proto to simply match a specific atom type. -AtomMatcher CreateSimpleAtomMatcher(const string& name, int atomId); - -// Create AtomMatcher proto for scheduled job state changed. -AtomMatcher CreateScheduledJobStateChangedAtomMatcher(); - -// Create AtomMatcher proto for starting a scheduled job. -AtomMatcher CreateStartScheduledJobAtomMatcher(); - -// Create AtomMatcher proto for a scheduled job is done. -AtomMatcher CreateFinishScheduledJobAtomMatcher(); - -// Create AtomMatcher proto for screen brightness state changed. -AtomMatcher CreateScreenBrightnessChangedAtomMatcher(); - -// Create AtomMatcher proto for acquiring wakelock. -AtomMatcher CreateAcquireWakelockAtomMatcher(); - -// Create AtomMatcher proto for releasing wakelock. -AtomMatcher CreateReleaseWakelockAtomMatcher() ; - -// Create AtomMatcher proto for screen turned on. -AtomMatcher CreateScreenTurnedOnAtomMatcher(); - -// Create AtomMatcher proto for screen turned off. -AtomMatcher CreateScreenTurnedOffAtomMatcher(); - -// Create AtomMatcher proto for app sync turned on. -AtomMatcher CreateSyncStartAtomMatcher(); - -// Create AtomMatcher proto for app sync turned off. -AtomMatcher CreateSyncEndAtomMatcher(); - -// Create AtomMatcher proto for app sync moves to background. -AtomMatcher CreateMoveToBackgroundAtomMatcher(); - -// Create AtomMatcher proto for app sync moves to foreground. -AtomMatcher CreateMoveToForegroundAtomMatcher(); - -// Create Predicate proto for screen is off. -Predicate CreateScreenIsOffPredicate(); - -// Create Predicate proto for a running scheduled job. -Predicate CreateScheduledJobPredicate(); - -// Create Predicate proto for holding wakelock. -Predicate CreateHoldingWakelockPredicate(); - -// Create a Predicate proto for app syncing. -Predicate CreateIsSyncingPredicate(); - -// Create a Predicate proto for app is in background. -Predicate CreateIsInBackgroundPredicate(); - -// Add a predicate to the predicate combination. -void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination); - -// Create dimensions from primitive fields. -FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields); - -// Create dimensions by attribution uid and tag. -FieldMatcher CreateAttributionUidAndTagDimensions(const int atomId, - const std::vector<Position>& positions); - -// Create dimensions by attribution uid only. -FieldMatcher CreateAttributionUidDimensions(const int atomId, - const std::vector<Position>& positions); - -void writeAttribution(AStatsEvent* statsEvent, const vector<int>& attributionUids, - const vector<string>& attributionTags); - -void parseStatsEventToLogEvent(AStatsEvent* statsEvent, LogEvent* logEvent); - -// Create log event for screen state changed. -std::unique_ptr<LogEvent> CreateScreenStateChangedEvent( - uint64_t timestampNs, const android::view::DisplayStateEnum state); - -// Create log event when scheduled job starts. -std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& jobName); - -// Create log event when scheduled job finishes. -std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& jobName); - -// Create log event when the app sync starts. -std::unique_ptr<LogEvent> CreateSyncStartEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& name); - -// Create log event when the app sync ends. -std::unique_ptr<LogEvent> CreateSyncEndEvent(uint64_t timestampNs, - const vector<int>& attributionUids, - const vector<string>& attributionTags, - const string& name); - -// Create a statsd log event processor upon the start time in seconds, config and key. -sp<StatsLogProcessor> CreateStatsLogProcessor(const long timeBaseSec, const StatsdConfig& config, - const ConfigKey& key); - -// Util function to sort the log events by timestamp. -void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events); - -int64_t StringToId(const string& str); - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/statsd/benchmark/on_log_event_benchmark.cpp b/statsd/benchmark/on_log_event_benchmark.cpp new file mode 100644 index 00000000..d3e5709a --- /dev/null +++ b/statsd/benchmark/on_log_event_benchmark.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "benchmark/benchmark.h" +#include "tests/statsd_test_util.h" + +using namespace std; +namespace android { +namespace os { +namespace statsd { + +static void BM_OnLogEvent(benchmark::State& state) { + StatsdConfig config; + auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher(); + *config.add_atom_matcher() = wakelockAcquireMatcher; + + *config.add_event_metric() = + createEventMetric("Event", wakelockAcquireMatcher.id(), /* condition */ nullopt); + + for (int atomId = 1000; atomId < 2000; atomId++) { + auto matcher = CreateSimpleAtomMatcher("name" + to_string(atomId), atomId); + *config.add_atom_matcher() = CreateSimpleAtomMatcher("name" + to_string(atomId), atomId); + *config.add_event_metric() = createEventMetric("Event" + to_string(atomId), matcher.id(), + /* condition */ nullopt); + } + + ConfigKey cfgKey; + std::vector<std::unique_ptr<LogEvent>> events; + vector<int> attributionUids = {111}; + vector<string> attributionTags = {"App1"}; + for (int i = 1; i <= 10; i++) { + events.push_back(CreateAcquireWakelockEvent(2 + i, attributionUids, attributionTags, + "wl" + to_string(i))); + } + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey); + + for (auto _ : state) { + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + } +} +BENCHMARK(BM_OnLogEvent); + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/statsd/benchmark/stats_write_benchmark.cpp b/statsd/benchmark/stats_write_benchmark.cpp index d817b122..b84b0cde 100644 --- a/statsd/benchmark/stats_write_benchmark.cpp +++ b/statsd/benchmark/stats_write_benchmark.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include <statslog.h> +#include <statslog_statsdtest.h> #include "benchmark/benchmark.h" @@ -31,16 +31,11 @@ static void BM_StatsEventObtain(benchmark::State& state) { BENCHMARK(BM_StatsEventObtain); static void BM_StatsWrite(benchmark::State& state) { - const char* reason = "test"; - int64_t boot_end_time = 1234567; - int64_t total_duration = 100; - int64_t bootloader_duration = 10; - int64_t time_since_last_boot = 99999999; + int32_t parent_uid = 0; + int32_t isolated_uid = 100; + int32_t event = 1; while (state.KeepRunning()) { - android::util::stats_write( - android::util::BOOT_SEQUENCE_REPORTED, reason, reason, - boot_end_time, total_duration, bootloader_duration, time_since_last_boot); - total_duration++; + util::stats_write(util::ISOLATED_UID_CHANGED, parent_uid, isolated_uid, event++); } } BENCHMARK(BM_StatsWrite); @@ -50,10 +45,9 @@ static void BM_StatsWriteViaQueue(benchmark::State& state) { int32_t uid = 0; int32_t label = 100; int32_t a_state = 1; - // TODO: choose atom with a same structure as used in BM_StatsWrite while (state.KeepRunning()) { - benchmark::DoNotOptimize(android::util::stats_write(android::util::APP_BREADCRUMB_REPORTED, - uid, label, a_state++)); + benchmark::DoNotOptimize( + util::stats_write(util::APP_BREADCRUMB_REPORTED, uid, label, a_state++)); } } BENCHMARK(BM_StatsWriteViaQueue); diff --git a/statsd/fuzzers/statsd_service_fuzzer.cpp b/statsd/fuzzers/statsd_service_fuzzer.cpp new file mode 100644 index 00000000..7baca73a --- /dev/null +++ b/statsd/fuzzers/statsd_service_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "Log.h" + +#include <android/binder_interface_utils.h> +#include <fuzzbinder/libbinder_ndk_driver.h> + +#include "StatsService.h" +#include "packages/UidMap.h" + +using namespace android; +using namespace android::os::statsd; +using ndk::SharedRefBase; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + std::shared_ptr<LogEventFilter> logEventFilter = std::make_shared<LogEventFilter>(); + std::shared_ptr<LogEventQueue> eventQueue = + std::make_shared<LogEventQueue>(8000 /*buffer limit. Same as StatsD binary*/); + sp<UidMap> uidMap = UidMap::getInstance(); + shared_ptr<StatsService> binder = + SharedRefBase::make<StatsService>(uidMap, eventQueue, logEventFilter); + fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size)); + return 0; +} diff --git a/statsd/lib/stats_regex.cpp b/statsd/lib/stats_regex.cpp new file mode 100644 index 00000000..b041f66b --- /dev/null +++ b/statsd/lib/stats_regex.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stats_regex.h" + +#include <log/log.h> + +namespace android { +namespace os { +namespace statsd { + +using std::regex; +using std::regex_error; +using std::regex_replace; +using std::string; +using std::unique_ptr; + +unique_ptr<regex> createRegex(const string& pattern) { + try { + return std::make_unique<regex>(pattern); + } catch (regex_error& e) { + ALOGE("regex_error: %s, pattern: %s", e.what(), pattern.c_str()); + return nullptr; + } +} + +string regexReplace(const string& input, const regex& re, const string& format) { + try { + return regex_replace(input, re, format); + } catch (regex_error& e) { + ALOGE("regex_error: %s, input: %s, format: %s", e.what(), input.c_str(), format.c_str()); + return input; + } +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/statsd/lib/stats_regex.h b/statsd/lib/stats_regex.h new file mode 100644 index 00000000..99e76b2d --- /dev/null +++ b/statsd/lib/stats_regex.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <regex> + +namespace android { +namespace os { +namespace statsd { + +std::unique_ptr<std::regex> createRegex(const std::string& pattern); + +std::string regexReplace(const std::string& input, const std::regex& re, const std::string& format); + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/statsd/src/HashableDimensionKey.h b/statsd/src/HashableDimensionKey.h index b5df4561..5753d98c 100644 --- a/statsd/src/HashableDimensionKey.h +++ b/statsd/src/HashableDimensionKey.h @@ -142,7 +142,7 @@ private: class AtomDimensionKey { public: - explicit AtomDimensionKey(const int32_t atomTag, const HashableDimensionKey& atomFieldValues) + explicit AtomDimensionKey(int32_t atomTag, const HashableDimensionKey& atomFieldValues) : mAtomTag(atomTag), mAtomFieldValues(atomFieldValues){}; AtomDimensionKey(){}; @@ -269,22 +269,16 @@ bool linked(const std::vector<Metric2State>& stateLinks, const int32_t stateAtom } // namespace os } // namespace android -namespace std { - -using android::os::statsd::AtomDimensionKey; -using android::os::statsd::HashableDimensionKey; -using android::os::statsd::MetricDimensionKey; - template <> -struct hash<HashableDimensionKey> { - std::size_t operator()(const HashableDimensionKey& key) const { +struct std::hash<android::os::statsd::HashableDimensionKey> { + std::size_t operator()(const android::os::statsd::HashableDimensionKey& key) const { return hashDimension(key); } }; template <> -struct hash<MetricDimensionKey> { - std::size_t operator()(const MetricDimensionKey& key) const { +struct std::hash<android::os::statsd::MetricDimensionKey> { + std::size_t operator()(const android::os::statsd::MetricDimensionKey& key) const { android::hash_t hash = hashDimension(key.getDimensionKeyInWhat()); hash = android::JenkinsHashMix(hash, hashDimension(key.getStateValuesKey())); return android::JenkinsHashWhiten(hash); @@ -292,11 +286,10 @@ struct hash<MetricDimensionKey> { }; template <> -struct hash<AtomDimensionKey> { - std::size_t operator()(const AtomDimensionKey& key) const { +struct std::hash<android::os::statsd::AtomDimensionKey> { + std::size_t operator()(const android::os::statsd::AtomDimensionKey& key) const { android::hash_t hash = hashDimension(key.getAtomFieldValues()); hash = android::JenkinsHashMix(hash, key.getAtomTag()); return android::JenkinsHashWhiten(hash); } }; -} // namespace std diff --git a/statsd/src/StatsLogProcessor.cpp b/statsd/src/StatsLogProcessor.cpp index 841c5c1a..e2b3efa2 100644 --- a/statsd/src/StatsLogProcessor.cpp +++ b/statsd/src/StatsLogProcessor.cpp @@ -134,14 +134,14 @@ static void flushProtoToBuffer(ProtoOutputStream& proto, vector<uint8_t>* outDat } void StatsLogProcessor::processFiredAnomalyAlarmsLocked( - const int64_t& timestampNs, + const int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet) { for (const auto& itr : mMetricsManagers) { itr.second->onAnomalyAlarmFired(timestampNs, alarmSet); } } void StatsLogProcessor::onPeriodicAlarmFired( - const int64_t& timestampNs, + const int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet) { std::lock_guard<std::mutex> lock(mMetricsMutex); for (const auto& itr : mMetricsManagers) { @@ -1415,7 +1415,7 @@ int64_t StatsLogProcessor::getLastReportTimeNs(const ConfigKey& key) { } } -void StatsLogProcessor::notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, +void StatsLogProcessor::notifyAppUpgrade(const int64_t eventTimeNs, const string& apk, const int uid, const int64_t version) { std::lock_guard<std::mutex> lock(mMetricsMutex); VLOG("Received app upgrade"); @@ -1425,7 +1425,7 @@ void StatsLogProcessor::notifyAppUpgrade(const int64_t& eventTimeNs, const strin } } -void StatsLogProcessor::notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, +void StatsLogProcessor::notifyAppRemoved(const int64_t eventTimeNs, const string& apk, const int uid) { std::lock_guard<std::mutex> lock(mMetricsMutex); VLOG("Received app removed"); @@ -1435,7 +1435,7 @@ void StatsLogProcessor::notifyAppRemoved(const int64_t& eventTimeNs, const strin } } -void StatsLogProcessor::onUidMapReceived(const int64_t& eventTimeNs) { +void StatsLogProcessor::onUidMapReceived(const int64_t eventTimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); VLOG("Received uid map"); StateManager::getInstance().updateLogSources(mUidMap); @@ -1444,7 +1444,7 @@ void StatsLogProcessor::onUidMapReceived(const int64_t& eventTimeNs) { } } -void StatsLogProcessor::onStatsdInitCompleted(const int64_t& elapsedTimeNs) { +void StatsLogProcessor::onStatsdInitCompleted(const int64_t elapsedTimeNs) { std::lock_guard<std::mutex> lock(mMetricsMutex); VLOG("Received boot completed signal"); for (const auto& it : mMetricsManagers) { diff --git a/statsd/src/StatsLogProcessor.h b/statsd/src/StatsLogProcessor.h index 1449911e..a0b25e72 100644 --- a/statsd/src/StatsLogProcessor.h +++ b/statsd/src/StatsLogProcessor.h @@ -40,7 +40,7 @@ public: StatsLogProcessor( const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor, - const sp<AlarmMonitor>& subscriberTriggerAlarmMonitor, const int64_t timeBaseNs, + const sp<AlarmMonitor>& subscriberTriggerAlarmMonitor, int64_t timeBaseNs, const std::function<bool(const ConfigKey&)>& sendBroadcast, const std::function<bool(const int&, const vector<int64_t>&)>& sendActivationBroadcast, const std::function<void(const ConfigKey&, const string&, const vector<int64_t>&)>& @@ -51,7 +51,7 @@ public: void OnLogEvent(LogEvent* event); - void OnConfigUpdated(const int64_t timestampNs, const int64_t wallClockNs, const ConfigKey& key, + void OnConfigUpdated(const int64_t timestampNs, int64_t wallClockNs, const ConfigKey& key, const StatsdConfig& config, bool modularUpdate = true); // For testing only. void OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key, @@ -62,28 +62,28 @@ public: void GetActiveConfigs(const int uid, vector<int64_t>& outActiveConfigs); - void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs, const int64_t wallClockNs, + void onDumpReport(const ConfigKey& key, int64_t dumpTimeNs, int64_t wallClockNs, const bool include_current_partial_bucket, const bool erase_data, const DumpReportReason dumpReportReason, const DumpLatency dumpLatency, vector<uint8_t>* outData); - void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs, const int64_t wallClockNs, + void onDumpReport(const ConfigKey& key, int64_t dumpTimeNs, int64_t wallClockNs, const bool include_current_partial_bucket, const bool erase_data, const DumpReportReason dumpReportReason, const DumpLatency dumpLatency, ProtoOutputStream* proto); // For testing only. - void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs, + void onDumpReport(const ConfigKey& key, int64_t dumpTimeNs, const bool include_current_partial_bucket, const bool erase_data, const DumpReportReason dumpReportReason, const DumpLatency dumpLatency, vector<uint8_t>* outData); /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */ void onPeriodicAlarmFired( - const int64_t& timestampNs, + int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet); /* Flushes data to disk. Data on memory will be gone after written to disk. */ void WriteDataToDisk(const DumpReportReason dumpReportReason, const DumpLatency dumpLatency, - const int64_t elapsedRealtimeNs, const int64_t wallClockNs); + const int64_t elapsedRealtimeNs, int64_t wallClockNs); /* Persist configs containing metrics with active activations to disk. */ void SaveActiveConfigsToDisk(int64_t currentTimeNs); @@ -113,25 +113,25 @@ public: int64_t systemElapsedTimeNs); /* Enforces ttls for restricted metrics */ - void EnforceDataTtls(const int64_t wallClockNs, const int64_t elapsedRealtimeNs); + void EnforceDataTtls(const int64_t wallClockNs, int64_t elapsedRealtimeNs); /* Sets the active status/ttl for all configs and metrics to the status in ActiveConfigList. */ void SetConfigsActiveState(const ActiveConfigList& activeConfigList, int64_t currentTimeNs); /* Notify all MetricsManagers of app upgrades */ - void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid, - const int64_t version) override; + void notifyAppUpgrade(int64_t eventTimeNs, const string& apk, int uid, + int64_t version) override; /* Notify all MetricsManagers of app removals */ - void notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, const int uid) override; + void notifyAppRemoved(int64_t eventTimeNs, const string& apk, int uid) override; /* Notify all MetricsManagers of uid map snapshots received */ - void onUidMapReceived(const int64_t& eventTimeNs) override; + void onUidMapReceived(int64_t eventTimeNs) override; /* Notify all metrics managers of boot completed * This will force a bucket split when the boot is finished. */ - void onStatsdInitCompleted(const int64_t& elapsedTimeNs); + void onStatsdInitCompleted(int64_t elapsedTimeNs); // Reset all configs. void resetConfigs(); @@ -248,15 +248,15 @@ private: metadata::StatsMetadataList* metadataList); void WriteDataToDiskLocked(const DumpReportReason dumpReportReason, - const DumpLatency dumpLatency, const int64_t elapsedRealtimeNs, + const DumpLatency dumpLatency, int64_t elapsedRealtimeNs, const int64_t wallClockNs); - void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs, - const int64_t wallClockNs, const DumpReportReason dumpReportReason, + void WriteDataToDiskLocked(const ConfigKey& key, int64_t timestampNs, const int64_t wallClockNs, + const DumpReportReason dumpReportReason, const DumpLatency dumpLatency); void onConfigMetricsReportLocked( - const ConfigKey& key, const int64_t dumpTimeStampNs, const int64_t wallClockNs, + const ConfigKey& key, int64_t dumpTimeStampNs, int64_t wallClockNs, const bool include_current_partial_bucket, const bool erase_data, const DumpReportReason dumpReportReason, const DumpLatency dumpLatency, /*if dataSavedToDisk is true, it indicates the caller will write the data to disk @@ -269,7 +269,7 @@ private: const int64_t elapsedRealtimeNs); // Enforces ttls on all restricted metrics. - void enforceDataTtlsLocked(const int64_t wallClockNs, const int64_t elapsedRealtimeNs); + void enforceDataTtlsLocked(const int64_t wallClockNs, int64_t elapsedRealtimeNs); // Enforces that dbs are within guardrail parameters. void enforceDbGuardrailsIfNecessaryLocked(const int64_t wallClockNs, @@ -279,8 +279,7 @@ private: * actually delete the data. */ void flushIfNecessaryLocked(const ConfigKey& key, MetricsManager& metricsManager); - set<ConfigKey> getRestrictedConfigKeysToQueryLocked(const int32_t callingUid, - const int64_t configId, + set<ConfigKey> getRestrictedConfigKeysToQueryLocked(int32_t callingUid, const int64_t configId, const set<int32_t>& configPackageUids, string& err, InvalidQueryReason& invalidQueryReason); @@ -304,8 +303,8 @@ private: // Gets experiment ids on disk for associated train and updates them // depending on rollback type. Then writes them back to disk and returns // them. - std::vector<int64_t> processWatchdogRollbackOccurred(const int32_t rollbackTypeIn, - const string& packageName); + std::vector<int64_t> processWatchdogRollbackOccurred(int32_t rollbackTypeIn, + const string& packageName); // Reset all configs. void resetConfigsLocked(const int64_t timestampNs); @@ -318,7 +317,7 @@ private: /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */ void processFiredAnomalyAlarmsLocked( - const int64_t& timestampNs, + int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet); void flushRestrictedDataLocked(const int64_t elapsedRealtimeNs); @@ -488,6 +487,10 @@ private: FRIEND_TEST(KllMetricE2eTest, TestInitWithKllFieldPositionALL); FRIEND_TEST(StatsServiceStatsdInitTest, StatsServiceStatsdInitTest); + + FRIEND_TEST(StringReplaceE2eTest, TestPulledDimension); + FRIEND_TEST(StringReplaceE2eTest, TestPulledWhat); + FRIEND_TEST(StringReplaceE2eTest, TestMultipleMatchersForAtom); }; } // namespace statsd diff --git a/statsd/src/StatsService.cpp b/statsd/src/StatsService.cpp index 8b2c218c..f0c13cd3 100644 --- a/statsd/src/StatsService.cpp +++ b/statsd/src/StatsService.cpp @@ -1514,9 +1514,8 @@ void StatsService::stopReadingLogs() { mIsStopRequested = true; // Push this event so that readLogs will process and break out of the loop // after the stop is requested. - int64_t timeStamp; std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0); - mEventQueue->push(std::move(logEvent), &timeStamp); + mEventQueue->push(std::move(logEvent)); } } // namespace statsd diff --git a/statsd/src/StatsService.h b/statsd/src/StatsService.h index c170e003..3c34492b 100644 --- a/statsd/src/StatsService.h +++ b/statsd/src/StatsService.h @@ -146,7 +146,7 @@ public: /** * Binder call to remove the active configs changed operation for the specified package.. */ - virtual Status removeActiveConfigsChangedOperation(const int32_t callingUid) override; + virtual Status removeActiveConfigsChangedOperation(int32_t callingUid) override; /** * Binder call to allow clients to remove the specified configuration. */ diff --git a/statsd/src/anomaly/AlarmMonitor.cpp b/statsd/src/anomaly/AlarmMonitor.cpp index 4822b541..6359c5f5 100644 --- a/statsd/src/anomaly/AlarmMonitor.cpp +++ b/statsd/src/anomaly/AlarmMonitor.cpp @@ -36,7 +36,7 @@ AlarmMonitor::AlarmMonitor( AlarmMonitor::~AlarmMonitor() {} void AlarmMonitor::setStatsCompanionService( - shared_ptr<IStatsCompanionService> statsCompanionService) { + const shared_ptr<IStatsCompanionService>& statsCompanionService) { std::lock_guard<std::mutex> lock(mLock); shared_ptr<IStatsCompanionService> tmpForLock = mStatsCompanionService; mStatsCompanionService = statsCompanionService; @@ -51,7 +51,7 @@ void AlarmMonitor::setStatsCompanionService( } } -void AlarmMonitor::add(sp<const InternalAlarm> alarm) { +void AlarmMonitor::add(const sp<const InternalAlarm>& alarm) { std::lock_guard<std::mutex> lock(mLock); if (alarm == nullptr) { ALOGW("Asked to add a null alarm."); @@ -71,7 +71,7 @@ void AlarmMonitor::add(sp<const InternalAlarm> alarm) { } } -void AlarmMonitor::remove(sp<const InternalAlarm> alarm) { +void AlarmMonitor::remove(const sp<const InternalAlarm>& alarm) { std::lock_guard<std::mutex> lock(mLock); if (alarm == nullptr) { ALOGW("Asked to remove a null alarm."); diff --git a/statsd/src/anomaly/AlarmMonitor.h b/statsd/src/anomaly/AlarmMonitor.h index 5c34e381..ee955c97 100644 --- a/statsd/src/anomaly/AlarmMonitor.h +++ b/statsd/src/anomaly/AlarmMonitor.h @@ -49,7 +49,7 @@ struct InternalAlarm : public RefBase { /** InternalAlarm a is smaller (higher priority) than b if its timestamp is sooner. */ struct SmallerTimestamp { - bool operator()(sp<const InternalAlarm> a, sp<const InternalAlarm> b) const { + bool operator()(const sp<const InternalAlarm>& a, const sp<const InternalAlarm>& b) const { return (a->timestampSec < b->timestampSec); } }; @@ -77,19 +77,19 @@ public: * If nullptr, AnomalyMonitor will continue to add/remove alarms, but won't * update IStatsCompanionService (until such time as it is set non-null). */ - void setStatsCompanionService(shared_ptr<IStatsCompanionService> statsCompanionService); + void setStatsCompanionService(const shared_ptr<IStatsCompanionService>& statsCompanionService); /** * Adds the given alarm (reference) to the queue. */ - void add(sp<const InternalAlarm> alarm); + void add(const sp<const InternalAlarm>& alarm); /** * Removes the given alarm (reference) from the queue. * Note that alarm comparison is reference-based; if another alarm exists * with the same timestampSec, that alarm will still remain in the queue. */ - void remove(sp<const InternalAlarm> alarm); + void remove(const sp<const InternalAlarm>& alarm); /** * Returns and removes all alarms whose timestamp <= the given timestampSec. diff --git a/statsd/src/anomaly/AlarmTracker.cpp b/statsd/src/anomaly/AlarmTracker.cpp index 8e311d4b..9d1aa106 100644 --- a/statsd/src/anomaly/AlarmTracker.cpp +++ b/statsd/src/anomaly/AlarmTracker.cpp @@ -69,7 +69,7 @@ int64_t AlarmTracker::findNextAlarmSec(int64_t currentTimeSec) { } void AlarmTracker::informAlarmsFired( - const int64_t& timestampNs, + const int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) { if (firedAlarms.empty() || mInternalAlarm == nullptr || firedAlarms.find(mInternalAlarm) == firedAlarms.end()) { diff --git a/statsd/src/anomaly/AlarmTracker.h b/statsd/src/anomaly/AlarmTracker.h index 4b8fab36..c89099f9 100644 --- a/statsd/src/anomaly/AlarmTracker.h +++ b/statsd/src/anomaly/AlarmTracker.h @@ -42,7 +42,8 @@ public: void addSubscription(const Subscription& subscription); - void informAlarmsFired(const int64_t& timestampNs, + void informAlarmsFired( + int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms); protected: diff --git a/statsd/src/anomaly/AnomalyTracker.cpp b/statsd/src/anomaly/AnomalyTracker.cpp index 2e0d2382..2829bff0 100644 --- a/statsd/src/anomaly/AnomalyTracker.cpp +++ b/statsd/src/anomaly/AnomalyTracker.cpp @@ -63,7 +63,7 @@ size_t AnomalyTracker::index(int64_t bucketNum) const { return bucketNum % mNumOfPastBuckets; } -void AnomalyTracker::advanceMostRecentBucketTo(const int64_t& bucketNum) { +void AnomalyTracker::advanceMostRecentBucketTo(const int64_t bucketNum) { VLOG("advanceMostRecentBucketTo() called."); if (mNumOfPastBuckets <= 0) { return; @@ -89,9 +89,8 @@ void AnomalyTracker::advanceMostRecentBucketTo(const int64_t& bucketNum) { mMostRecentBucketNum = bucketNum; } -void AnomalyTracker::addPastBucket(const MetricDimensionKey& key, - const int64_t& bucketValue, - const int64_t& bucketNum) { +void AnomalyTracker::addPastBucket(const MetricDimensionKey& key, const int64_t bucketValue, + const int64_t bucketNum) { VLOG("addPastBucket(bucketValue) called."); if (mNumOfPastBuckets == 0 || bucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets) { @@ -119,8 +118,8 @@ void AnomalyTracker::addPastBucket(const MetricDimensionKey& key, } } -void AnomalyTracker::addPastBucket(std::shared_ptr<DimToValMap> bucket, - const int64_t& bucketNum) { +void AnomalyTracker::addPastBucket(const std::shared_ptr<DimToValMap>& bucket, + const int64_t bucketNum) { VLOG("addPastBucket(bucket) called."); if (mNumOfPastBuckets == 0 || bucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets) { @@ -147,9 +146,8 @@ void AnomalyTracker::subtractBucketFromSum(const shared_ptr<DimToValMap>& bucket } } - void AnomalyTracker::subtractValueFromSum(const MetricDimensionKey& key, - const int64_t& bucketValue) { + const int64_t bucketValue) { auto itr = mSumOverPastBuckets.find(key); if (itr == mSumOverPastBuckets.end()) { return; @@ -171,7 +169,7 @@ void AnomalyTracker::addBucketToSum(const shared_ptr<DimToValMap>& bucket) { } int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key, - const int64_t& bucketNum) const { + const int64_t bucketNum) const { if (bucketNum < 0 || mMostRecentBucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets || bucketNum > mMostRecentBucketNum) { @@ -194,10 +192,8 @@ int64_t AnomalyTracker::getSumOverPastBuckets(const MetricDimensionKey& key) con return 0; } -bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, - const MetricDimensionKey& key, - const int64_t& currentBucketValue) { - +bool AnomalyTracker::detectAnomaly(const int64_t currentBucketNum, const MetricDimensionKey& key, + const int64_t currentBucketValue) { // currentBucketNum should be the next bucket after pastBuckets. If not, advance so that it is. if (currentBucketNum > mMostRecentBucketNum + 1) { advanceMostRecentBucketTo(currentBucketNum - 1); @@ -206,7 +202,7 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); } -void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, int64_t metricId, +void AnomalyTracker::declareAnomaly(const int64_t timestampNs, int64_t metricId, const MetricDimensionKey& key, int64_t metricValue) { // TODO(b/110563466): Why receive timestamp? RefractoryPeriod should always be based on // real time right now. @@ -246,16 +242,15 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, int64_t metricId StatsdStats::getInstance().noteAnomalyDeclared(mConfigKey, mAlert.id()); } -void AnomalyTracker::detectAndDeclareAnomaly(const int64_t& timestampNs, - const int64_t& currBucketNum, int64_t metricId, - const MetricDimensionKey& key, - const int64_t& currentBucketValue) { +void AnomalyTracker::detectAndDeclareAnomaly(const int64_t timestampNs, const int64_t currBucketNum, + int64_t metricId, const MetricDimensionKey& key, + const int64_t currentBucketValue) { if (detectAnomaly(currBucketNum, key, currentBucketValue)) { declareAnomaly(timestampNs, metricId, key, currentBucketValue); } } -bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs, +bool AnomalyTracker::isInRefractoryPeriod(const int64_t timestampNs, const MetricDimensionKey& key) const { const auto& it = mRefractoryPeriodEndsSec.find(key); if (it != mRefractoryPeriodEndsSec.end()) { diff --git a/statsd/src/anomaly/AnomalyTracker.h b/statsd/src/anomaly/AnomalyTracker.h index 92a7173d..4a4f7ffc 100644 --- a/statsd/src/anomaly/AnomalyTracker.h +++ b/statsd/src/anomaly/AnomalyTracker.h @@ -55,32 +55,30 @@ public: // If a bucket for bucketNum already exists, it will be replaced. // Also, advances to bucketNum (if not in the past), effectively filling any intervening // buckets with 0s. - void addPastBucket(std::shared_ptr<DimToValMap> bucket, const int64_t& bucketNum); + void addPastBucket(const std::shared_ptr<DimToValMap>& bucket, const int64_t bucketNum); // Inserts (or replaces) the bucket entry for the given bucketNum at the given key to be the // given bucketValue. If the bucket does not exist, it will be created. // Also, advances to bucketNum (if not in the past), effectively filling any intervening // buckets with 0s. - void addPastBucket(const MetricDimensionKey& key, const int64_t& bucketValue, - const int64_t& bucketNum); + void addPastBucket(const MetricDimensionKey& key, int64_t bucketValue, int64_t bucketNum); // Returns true if, based on past buckets plus the new currentBucketValue (which generally // represents the partially-filled current bucket), an anomaly has happened. // Also advances to currBucketNum-1. - bool detectAnomaly(const int64_t& currBucketNum, const MetricDimensionKey& key, - const int64_t& currentBucketValue); + bool detectAnomaly(int64_t currBucketNum, const MetricDimensionKey& key, + int64_t currentBucketValue); // Informs incidentd about the detected alert. - void declareAnomaly(const int64_t& timestampNs, int64_t metricId, const MetricDimensionKey& key, + void declareAnomaly(int64_t timestampNs, int64_t metricId, const MetricDimensionKey& key, int64_t metricValue); // Detects if, based on past buckets plus the new currentBucketValue (which generally // represents the partially-filled current bucket), an anomaly has happened, and if so, // declares an anomaly and informs relevant subscribers. // Also advances to currBucketNum-1. - void detectAndDeclareAnomaly(const int64_t& timestampNs, const int64_t& currBucketNum, - int64_t metricId, const MetricDimensionKey& key, - const int64_t& currentBucketValue); + void detectAndDeclareAnomaly(int64_t timestampNs, int64_t currBucketNum, int64_t metricId, + const MetricDimensionKey& key, int64_t currentBucketValue); // Init the AlarmMonitor which is shared across anomaly trackers. virtual void setAlarmMonitor(const sp<AlarmMonitor>& alarmMonitor) { @@ -91,7 +89,7 @@ public: int64_t getSumOverPastBuckets(const MetricDimensionKey& key) const; // Returns the value for a past bucket, or 0 if that bucket doesn't exist. - int64_t getPastBucketValue(const MetricDimensionKey& key, const int64_t& bucketNum) const; + int64_t getPastBucketValue(const MetricDimensionKey& key, int64_t bucketNum) const; // Returns the anomaly threshold set in the configuration. inline int64_t getAnomalyThreshold() const { @@ -115,14 +113,14 @@ public: // Sets an alarm for the given timestamp. // Replaces previous alarm if one already exists. - virtual void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime) { + virtual void startAlarm(const MetricDimensionKey& dimensionKey, int64_t eventTime) { return; // The base AnomalyTracker class doesn't have alarms. } // Stops the alarm. // If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed), // declare the anomaly now. - virtual void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs) { + virtual void stopAlarm(const MetricDimensionKey& dimensionKey, int64_t timestampNs) { return; // The base AnomalyTracker class doesn't have alarms. } @@ -133,7 +131,8 @@ public: // Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker, // and removes it from firedAlarms. Does NOT remove the alarm from the AlarmMonitor. - virtual void informAlarmsFired(const int64_t& timestampNs, + virtual void informAlarmsFired( + int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) { return; // The base AnomalyTracker class doesn't have alarms. } @@ -190,7 +189,7 @@ protected: // Advances mMostRecentBucketNum to bucketNum, deleting any data that is now too old. // Specifically, since it is now too old, removes the data for // [mMostRecentBucketNum - mNumOfPastBuckets + 1, bucketNum - mNumOfPastBuckets]. - void advanceMostRecentBucketTo(const int64_t& bucketNum); + void advanceMostRecentBucketTo(int64_t bucketNum); // Add the information in the given bucket to mSumOverPastBuckets. void addBucketToSum(const shared_ptr<DimToValMap>& bucket); @@ -200,10 +199,10 @@ protected: void subtractBucketFromSum(const shared_ptr<DimToValMap>& bucket); // From mSumOverPastBuckets[key], subtracts bucketValue, removing it if it is now 0. - void subtractValueFromSum(const MetricDimensionKey& key, const int64_t& bucketValue); + void subtractValueFromSum(const MetricDimensionKey& key, int64_t bucketValue); // Returns true if in the refractory period, else false. - bool isInRefractoryPeriod(const int64_t& timestampNs, const MetricDimensionKey& key) const; + bool isInRefractoryPeriod(int64_t timestampNs, const MetricDimensionKey& key) const; // Calculates the corresponding bucket index within the circular array. // Requires bucketNum >= 0. diff --git a/statsd/src/anomaly/DurationAnomalyTracker.cpp b/statsd/src/anomaly/DurationAnomalyTracker.cpp index 66c71ad5..f3bfc056 100644 --- a/statsd/src/anomaly/DurationAnomalyTracker.cpp +++ b/statsd/src/anomaly/DurationAnomalyTracker.cpp @@ -36,7 +36,7 @@ DurationAnomalyTracker::~DurationAnomalyTracker() { } void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, - const int64_t& timestampNs) { + const int64_t timestampNs) { // Alarms are stored in secs. Must round up, since if it fires early, it is ignored completely. uint32_t timestampSec = static_cast<uint32_t>((timestampNs -1) / NS_PER_SEC) + 1; // round up if (isInRefractoryPeriod(timestampNs, dimensionKey)) { @@ -57,7 +57,7 @@ void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, } void DurationAnomalyTracker::stopAlarm(const MetricDimensionKey& dimensionKey, - const int64_t& timestampNs) { + const int64_t timestampNs) { const auto itr = mAlarms.find(dimensionKey); if (itr == mAlarms.end()) { return; @@ -84,9 +84,9 @@ void DurationAnomalyTracker::cancelAllAlarms() { mAlarms.clear(); } -void DurationAnomalyTracker::informAlarmsFired(const int64_t& timestampNs, +void DurationAnomalyTracker::informAlarmsFired( + const int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) { - if (firedAlarms.empty() || mAlarms.empty()) return; // Find the intersection of firedAlarms and mAlarms. // The for loop is inefficient, since it loops over all keys, but that's okay since it is very diff --git a/statsd/src/anomaly/DurationAnomalyTracker.h b/statsd/src/anomaly/DurationAnomalyTracker.h index a5237829..ce06df02 100644 --- a/statsd/src/anomaly/DurationAnomalyTracker.h +++ b/statsd/src/anomaly/DurationAnomalyTracker.h @@ -34,12 +34,12 @@ public: // Sets an alarm for the given timestamp. // Replaces previous alarm if one already exists. - void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime) override; + void startAlarm(const MetricDimensionKey& dimensionKey, int64_t eventTime) override; // Stops the alarm. // If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed), // declare the anomaly now. - void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs) override; + void stopAlarm(const MetricDimensionKey& dimensionKey, int64_t timestampNs) override; // Stop all the alarms owned by this tracker. Does not declare any anomalies. void cancelAllAlarms() override; @@ -48,7 +48,8 @@ public: // and removes it from firedAlarms. The AlarmMonitor is not informed. // Note that this will generally be called from a different thread from the other functions; // the caller is responsible for thread safety. - void informAlarmsFired(const int64_t& timestampNs, + void informAlarmsFired( + int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) override; protected: diff --git a/statsd/src/anomaly/subscriber_util.h b/statsd/src/anomaly/subscriber_util.h index 4d4c83b8..d55581d8 100644 --- a/statsd/src/anomaly/subscriber_util.h +++ b/statsd/src/anomaly/subscriber_util.h @@ -24,7 +24,7 @@ namespace android { namespace os { namespace statsd { -void triggerSubscribers(const int64_t ruleId, const int64_t metricId, +void triggerSubscribers(const int64_t ruleId, int64_t metricId, const MetricDimensionKey& dimensionKey, int64_t metricValue, const ConfigKey& configKey, const std::vector<Subscription>& subscriptions); diff --git a/statsd/src/condition/CombinationConditionTracker.cpp b/statsd/src/condition/CombinationConditionTracker.cpp index 829ae06f..af4a18a0 100644 --- a/statsd/src/condition/CombinationConditionTracker.cpp +++ b/statsd/src/condition/CombinationConditionTracker.cpp @@ -25,7 +25,7 @@ namespace statsd { using std::unordered_map; using std::vector; -CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index, +CombinationConditionTracker::CombinationConditionTracker(const int64_t id, const int index, const uint64_t protoHash) : ConditionTracker(id, index, protoHash) { VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId); @@ -38,7 +38,7 @@ CombinationConditionTracker::~CombinationConditionTracker() { optional<InvalidConfigReason> CombinationConditionTracker::init( const vector<Predicate>& allConditionConfig, const vector<sp<ConditionTracker>>& allConditionTrackers, - const unordered_map<int64_t, int>& conditionIdIndexMap, vector<bool>& stack, + const unordered_map<int64_t, int>& conditionIdIndexMap, vector<uint8_t>& stack, vector<ConditionState>& conditionCache) { VLOG("Combination predicate init() %lld", (long long)mConditionId); if (mInitialized) { @@ -203,7 +203,7 @@ void CombinationConditionTracker::evaluateCondition( const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues, const std::vector<sp<ConditionTracker>>& mAllConditions, std::vector<ConditionState>& nonSlicedConditionCache, - std::vector<bool>& conditionChangedCache) { + std::vector<uint8_t>& conditionChangedCache) { // value is up to date. if (nonSlicedConditionCache[mIndex] != ConditionState::kNotEvaluated) { return; diff --git a/statsd/src/condition/CombinationConditionTracker.h b/statsd/src/condition/CombinationConditionTracker.h index 82463f07..3ed4a83d 100644 --- a/statsd/src/condition/CombinationConditionTracker.h +++ b/statsd/src/condition/CombinationConditionTracker.h @@ -26,18 +26,18 @@ namespace statsd { class CombinationConditionTracker : public ConditionTracker { public: - CombinationConditionTracker(const int64_t& id, const int index, const uint64_t protoHash); + CombinationConditionTracker(int64_t id, int index, const uint64_t protoHash); ~CombinationConditionTracker(); optional<InvalidConfigReason> init( const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, - const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, - std::vector<ConditionState>& conditionCache) override; + const std::unordered_map<int64_t, int>& conditionIdIndexMap, + std::vector<uint8_t>& stack, std::vector<ConditionState>& conditionCache) override; optional<InvalidConfigReason> onConfigUpdated( - const std::vector<Predicate>& allConditionProtos, const int index, + const std::vector<Predicate>& allConditionProtos, int index, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, const std::unordered_map<int64_t, int>& conditionTrackerMap) override; @@ -46,7 +46,7 @@ public: const std::vector<MatchingState>& eventMatcherValues, const std::vector<sp<ConditionTracker>>& mAllConditions, std::vector<ConditionState>& conditionCache, - std::vector<bool>& changedCache) override; + std::vector<uint8_t>& changedCache) override; void isConditionMet(const ConditionKey& conditionParameters, const std::vector<sp<ConditionTracker>>& allConditions, diff --git a/statsd/src/condition/ConditionTracker.h b/statsd/src/condition/ConditionTracker.h index 2aa3ff06..b09d3503 100644 --- a/statsd/src/condition/ConditionTracker.h +++ b/statsd/src/condition/ConditionTracker.h @@ -31,7 +31,7 @@ namespace statsd { class ConditionTracker : public virtual RefBase { public: - ConditionTracker(const int64_t& id, const int index, const uint64_t protoHash) + ConditionTracker(int64_t id, int index, const uint64_t protoHash) : mConditionId(id), mIndex(index), mInitialized(false), @@ -57,8 +57,8 @@ public: virtual optional<InvalidConfigReason> init( const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, - const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, - std::vector<ConditionState>& conditionCache) = 0; + const std::unordered_map<int64_t, int>& conditionIdIndexMap, + std::vector<uint8_t>& stack, std::vector<ConditionState>& conditionCache) = 0; // Update appropriate state on config updates. Primarily, all indices need to be updated. // This predicate and all of its children are guaranteed to be preserved across the update. @@ -73,7 +73,7 @@ public: // conditionTrackerMap: map of condition tracker id to index after the config update. // returns whether or not the update is successful. virtual optional<InvalidConfigReason> onConfigUpdated( - const std::vector<Predicate>& allConditionProtos, const int index, + const std::vector<Predicate>& allConditionProtos, int index, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, const std::unordered_map<int64_t, int>& conditionTrackerMap) { @@ -95,7 +95,7 @@ public: const std::vector<MatchingState>& eventMatcherValues, const std::vector<sp<ConditionTracker>>& mAllConditions, std::vector<ConditionState>& conditionCache, - std::vector<bool>& conditionChanged) = 0; + std::vector<uint8_t>& conditionChanged) = 0; // Query the condition with parameters. // [conditionParameters]: a map from condition name to the HashableDimensionKey to query the diff --git a/statsd/src/condition/SimpleConditionTracker.cpp b/statsd/src/condition/SimpleConditionTracker.cpp index a7a04bf4..5b87f13d 100644 --- a/statsd/src/condition/SimpleConditionTracker.cpp +++ b/statsd/src/condition/SimpleConditionTracker.cpp @@ -27,7 +27,7 @@ namespace statsd { using std::unordered_map; SimpleConditionTracker::SimpleConditionTracker( - const ConfigKey& key, const int64_t& id, const uint64_t protoHash, const int index, + const ConfigKey& key, const int64_t id, const uint64_t protoHash, const int index, const SimplePredicate& simplePredicate, const unordered_map<int64_t, int>& atomMatchingTrackerMap) : ConditionTracker(id, index, protoHash), @@ -59,7 +59,7 @@ SimpleConditionTracker::~SimpleConditionTracker() { optional<InvalidConfigReason> SimpleConditionTracker::init( const vector<Predicate>& allConditionConfig, const vector<sp<ConditionTracker>>& allConditionTrackers, - const unordered_map<int64_t, int>& conditionIdIndexMap, vector<bool>& stack, + const unordered_map<int64_t, int>& conditionIdIndexMap, vector<uint8_t>& stack, vector<ConditionState>& conditionCache) { // SimpleConditionTracker does not have dependency on other conditions, thus we just return // if the initialization was successful. @@ -145,7 +145,7 @@ void SimpleConditionTracker::dumpState() { } void SimpleConditionTracker::handleStopAll(std::vector<ConditionState>& conditionCache, - std::vector<bool>& conditionChangedCache) { + std::vector<uint8_t>& conditionChangedCache) { // Unless the default condition is false, and there was nothing started, otherwise we have // triggered a condition change. conditionChangedCache[mIndex] = @@ -265,12 +265,11 @@ void SimpleConditionTracker::handleConditionEvent(const HashableDimensionKey& ou *conditionChangedCache); } -void SimpleConditionTracker::evaluateCondition( - const LogEvent& event, - const vector<MatchingState>& eventMatcherValues, - const vector<sp<ConditionTracker>>& mAllConditions, - vector<ConditionState>& conditionCache, - vector<bool>& conditionChangedCache) { +void SimpleConditionTracker::evaluateCondition(const LogEvent& event, + const vector<MatchingState>& eventMatcherValues, + const vector<sp<ConditionTracker>>& mAllConditions, + vector<ConditionState>& conditionCache, + vector<uint8_t>& conditionChangedCache) { if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { // it has been evaluated. VLOG("Yes, already evaluated, %lld %d", diff --git a/statsd/src/condition/SimpleConditionTracker.h b/statsd/src/condition/SimpleConditionTracker.h index 895072dd..8af89cbe 100644 --- a/statsd/src/condition/SimpleConditionTracker.h +++ b/statsd/src/condition/SimpleConditionTracker.h @@ -29,7 +29,7 @@ namespace statsd { class SimpleConditionTracker : public ConditionTracker { public: - SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const uint64_t protoHash, + SimpleConditionTracker(const ConfigKey& key, int64_t id, const uint64_t protoHash, const int index, const SimplePredicate& simplePredicate, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap); @@ -38,11 +38,11 @@ public: optional<InvalidConfigReason> init( const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, - const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, - std::vector<ConditionState>& conditionCache) override; + const std::unordered_map<int64_t, int>& conditionIdIndexMap, + std::vector<uint8_t>& stack, std::vector<ConditionState>& conditionCache) override; optional<InvalidConfigReason> onConfigUpdated( - const std::vector<Predicate>& allConditionProtos, const int index, + const std::vector<Predicate>& allConditionProtos, int index, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, const std::unordered_map<int64_t, int>& conditionTrackerMap) override; @@ -51,7 +51,7 @@ public: const std::vector<MatchingState>& eventMatcherValues, const std::vector<sp<ConditionTracker>>& mAllConditions, std::vector<ConditionState>& conditionCache, - std::vector<bool>& changedCache) override; + std::vector<uint8_t>& changedCache) override; void isConditionMet(const ConditionKey& conditionParameters, const std::vector<sp<ConditionTracker>>& allConditions, @@ -120,7 +120,7 @@ private: const std::unordered_map<int64_t, int>& logTrackerMap); void handleStopAll(std::vector<ConditionState>& conditionCache, - std::vector<bool>& changedCache); + std::vector<uint8_t>& changedCache); void handleConditionEvent(const HashableDimensionKey& outputKey, bool matchStart, ConditionState* conditionCache, bool* changedCache); diff --git a/statsd/src/config/ConfigKey.cpp b/statsd/src/config/ConfigKey.cpp index 4a2bd279..3b0b8357 100644 --- a/statsd/src/config/ConfigKey.cpp +++ b/statsd/src/config/ConfigKey.cpp @@ -26,7 +26,7 @@ ConfigKey::ConfigKey() { ConfigKey::ConfigKey(const ConfigKey& that) : mId(that.mId), mUid(that.mUid) { } -ConfigKey::ConfigKey(int uid, const int64_t& id) : mId(id), mUid(uid) { +ConfigKey::ConfigKey(int uid, const int64_t id) : mId(id), mUid(uid) { } ConfigKey::~ConfigKey() { diff --git a/statsd/src/config/ConfigKey.h b/statsd/src/config/ConfigKey.h index 0e5a7e3a..e8df3554 100644 --- a/statsd/src/config/ConfigKey.h +++ b/statsd/src/config/ConfigKey.h @@ -34,13 +34,13 @@ class ConfigKey { public: ConfigKey(); ConfigKey(const ConfigKey& that); - ConfigKey(int uid, const int64_t& id); + ConfigKey(int uid, int64_t id); ~ConfigKey(); inline int GetUid() const { return mUid; } - inline const int64_t& GetId() const { + inline int64_t GetId() const { return mId; } @@ -73,17 +73,10 @@ int64_t StrToInt64(const string& str); /** * A hash function for ConfigKey so it can be used for unordered_map/set. - * Unfortunately this has to go in std namespace because C++ is fun! */ -namespace std { - -using android::os::statsd::ConfigKey; - template <> -struct hash<ConfigKey> { - std::size_t operator()(const ConfigKey& key) const { +struct std::hash<android::os::statsd::ConfigKey> { + std::size_t operator()(const android::os::statsd::ConfigKey& key) const { return (7 * key.GetUid()) ^ ((hash<long long>()(key.GetId()))); } }; - -} // namespace std diff --git a/statsd/src/config/ConfigKeyWithPackage.h b/statsd/src/config/ConfigKeyWithPackage.h index 85e95d58..9cf507b7 100644 --- a/statsd/src/config/ConfigKeyWithPackage.h +++ b/statsd/src/config/ConfigKeyWithPackage.h @@ -31,7 +31,7 @@ using std::string; */ class ConfigKeyWithPackage { public: - ConfigKeyWithPackage(const string& package, const int64_t id) : mPackage(package), mId(id) { + ConfigKeyWithPackage(const string& package, int64_t id) : mPackage(package), mId(id) { } inline string GetPackage() const { diff --git a/statsd/src/config/ConfigManager.h b/statsd/src/config/ConfigManager.h index dd7d5bbb..e8819494 100644 --- a/statsd/src/config/ConfigManager.h +++ b/statsd/src/config/ConfigManager.h @@ -116,14 +116,14 @@ public: /** * Sets the pending intent that is notified whenever the list of restricted metrics changes */ - void SetRestrictedMetricsChangedReceiver(const string& configPackage, const int64_t configId, + void SetRestrictedMetricsChangedReceiver(const string& configPackage, int64_t configId, const int32_t callingUid, const shared_ptr<IPendingIntentRef>& pir); /** * Erase any restricted metrics changed pending intents associated with this config key & uid. */ - void RemoveRestrictedMetricsChangedReceiver(const string& configPackage, const int64_t configId, + void RemoveRestrictedMetricsChangedReceiver(const string& configPackage, int64_t configId, const int32_t callingUid); /** diff --git a/statsd/src/external/PullResultReceiver.h b/statsd/src/external/PullResultReceiver.h index ceaae801..f2d0a4ef 100644 --- a/statsd/src/external/PullResultReceiver.h +++ b/statsd/src/external/PullResultReceiver.h @@ -29,8 +29,8 @@ namespace statsd { class PullResultReceiver : public BnPullAtomResultReceiver { public: - PullResultReceiver(function<void(int32_t, bool, const vector<StatsEventParcel>&)> - pullFinishCallback); + PullResultReceiver( + function<void(int32_t, bool, const vector<StatsEventParcel>&)> pullFinishCallback); ~PullResultReceiver(); /** diff --git a/statsd/src/external/StatsCallbackPuller.cpp b/statsd/src/external/StatsCallbackPuller.cpp index 7d5d04b1..a1c8df2e 100644 --- a/statsd/src/external/StatsCallbackPuller.cpp +++ b/statsd/src/external/StatsCallbackPuller.cpp @@ -37,7 +37,7 @@ namespace statsd { StatsCallbackPuller::StatsCallbackPuller(int tagId, const shared_ptr<IPullAtomCallback>& callback, const int64_t coolDownNs, int64_t timeoutNs, - const vector<int> additiveFields) + const vector<int>& additiveFields) : StatsPuller(tagId, coolDownNs, timeoutNs, additiveFields), mCallback(callback) { VLOG("StatsCallbackPuller created for tag %d", tagId); } diff --git a/statsd/src/external/StatsCallbackPuller.h b/statsd/src/external/StatsCallbackPuller.h index 43d35fc1..65acb004 100644 --- a/statsd/src/external/StatsCallbackPuller.h +++ b/statsd/src/external/StatsCallbackPuller.h @@ -29,8 +29,8 @@ namespace statsd { class StatsCallbackPuller : public StatsPuller { public: explicit StatsCallbackPuller(int tagId, const shared_ptr<IPullAtomCallback>& callback, - const int64_t coolDownNs, const int64_t timeoutNs, - const std::vector<int> additiveFields); + const int64_t coolDownNs, int64_t timeoutNs, + const std::vector<int>& additiveFields); private: PullErrorCode PullInternal(vector<std::shared_ptr<LogEvent>>* data) override; diff --git a/statsd/src/external/StatsPuller.cpp b/statsd/src/external/StatsPuller.cpp index 395e660e..0051b0c3 100644 --- a/statsd/src/external/StatsPuller.cpp +++ b/statsd/src/external/StatsPuller.cpp @@ -33,7 +33,7 @@ sp<UidMap> StatsPuller::mUidMap = nullptr; void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; } StatsPuller::StatsPuller(const int tagId, const int64_t coolDownNs, const int64_t pullTimeoutNs, - const std::vector<int> additiveFields) + const std::vector<int>& additiveFields) : mTagId(tagId), mPullTimeoutNs(pullTimeoutNs), mCoolDownNs(coolDownNs), diff --git a/statsd/src/external/StatsPuller.h b/statsd/src/external/StatsPuller.h index d8c7eb3b..4a383821 100644 --- a/statsd/src/external/StatsPuller.h +++ b/statsd/src/external/StatsPuller.h @@ -41,10 +41,9 @@ enum PullErrorCode { class StatsPuller : public virtual RefBase { public: - explicit StatsPuller(const int tagId, - const int64_t coolDownNs = NS_PER_SEC, + explicit StatsPuller(const int tagId, int64_t coolDownNs = NS_PER_SEC, const int64_t pullTimeoutNs = StatsdStats::kPullMaxDelayNs, - const std::vector<int> additiveFields = std::vector<int>()); + const std::vector<int>& additiveFields = std::vector<int>()); virtual ~StatsPuller() {} @@ -69,7 +68,7 @@ public: static void SetUidMap(const sp<UidMap>& uidMap); virtual void SetStatsCompanionService( - shared_ptr<IStatsCompanionService> statsCompanionService) {}; + const shared_ptr<IStatsCompanionService>& statsCompanionService){}; protected: const int mTagId; diff --git a/statsd/src/external/StatsPullerManager.cpp b/statsd/src/external/StatsPullerManager.cpp index 8fabcad5..4fb63a66 100644 --- a/statsd/src/external/StatsPullerManager.cpp +++ b/statsd/src/external/StatsPullerManager.cpp @@ -135,7 +135,7 @@ void StatsPullerManager::updateAlarmLocked() { } void StatsPullerManager::SetStatsCompanionService( - shared_ptr<IStatsCompanionService> statsCompanionService) { + const shared_ptr<IStatsCompanionService>& statsCompanionService) { std::lock_guard<std::mutex> _l(mLock); shared_ptr<IStatsCompanionService> tmpForLock = mStatsCompanionService; mStatsCompanionService = statsCompanionService; @@ -148,8 +148,8 @@ void StatsPullerManager::SetStatsCompanionService( } void StatsPullerManager::RegisterReceiver(int tagId, const ConfigKey& configKey, - wp<PullDataReceiver> receiver, int64_t nextPullTimeNs, - int64_t intervalNs) { + const wp<PullDataReceiver>& receiver, + int64_t nextPullTimeNs, int64_t intervalNs) { std::lock_guard<std::mutex> _l(mLock); auto& receivers = mReceivers[{.atomTag = tagId, .configKey = configKey}]; for (auto it = receivers.begin(); it != receivers.end(); it++) { @@ -184,7 +184,7 @@ void StatsPullerManager::RegisterReceiver(int tagId, const ConfigKey& configKey, } void StatsPullerManager::UnRegisterReceiver(int tagId, const ConfigKey& configKey, - wp<PullDataReceiver> receiver) { + const wp<PullDataReceiver>& receiver) { std::lock_guard<std::mutex> _l(mLock); auto receiversIt = mReceivers.find({.atomTag = tagId, .configKey = configKey}); if (receiversIt == mReceivers.end()) { @@ -202,13 +202,13 @@ void StatsPullerManager::UnRegisterReceiver(int tagId, const ConfigKey& configKe } void StatsPullerManager::RegisterPullUidProvider(const ConfigKey& configKey, - wp<PullUidProvider> provider) { + const wp<PullUidProvider>& provider) { std::lock_guard<std::mutex> _l(mLock); mPullUidProviders[configKey] = provider; } void StatsPullerManager::UnregisterPullUidProvider(const ConfigKey& configKey, - wp<PullUidProvider> provider) { + const wp<PullUidProvider>& provider) { std::lock_guard<std::mutex> _l(mLock); const auto& it = mPullUidProviders.find(configKey); if (it != mPullUidProviders.end() && it->second == provider) { diff --git a/statsd/src/external/StatsPullerManager.h b/statsd/src/external/StatsPullerManager.h index 80a13312..9f5a41c8 100644 --- a/statsd/src/external/StatsPullerManager.h +++ b/statsd/src/external/StatsPullerManager.h @@ -70,20 +70,21 @@ public: // Registers a receiver for tagId. It will be pulled on the nextPullTimeNs // and then every intervalNs thereafter. virtual void RegisterReceiver(int tagId, const ConfigKey& configKey, - wp<PullDataReceiver> receiver, int64_t nextPullTimeNs, + const wp<PullDataReceiver>& receiver, int64_t nextPullTimeNs, int64_t intervalNs); // Stop listening on a tagId. virtual void UnRegisterReceiver(int tagId, const ConfigKey& configKey, - wp<PullDataReceiver> receiver); + const wp<PullDataReceiver>& receiver); // Registers a pull uid provider for the config key. When pulling atoms, it will be used to // determine which uids to pull from. - virtual void RegisterPullUidProvider(const ConfigKey& configKey, wp<PullUidProvider> provider); + virtual void RegisterPullUidProvider(const ConfigKey& configKey, + const wp<PullUidProvider>& provider); // Unregister a pull uid provider. virtual void UnregisterPullUidProvider(const ConfigKey& configKey, - wp<PullUidProvider> provider); + const wp<PullUidProvider>& provider); // Verify if we know how to pull for this matcher bool PullerForMatcherExists(int tagId) const; @@ -101,11 +102,11 @@ public: // registered for any of the uids for this atom. // If the metric wants to make any change to the data, like timestamps, they // should make a copy as this data may be shared with multiple metrics. - virtual bool Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs, + virtual bool Pull(int tagId, const ConfigKey& configKey, int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data); // Same as above, but directly specify the allowed uids to pull from. - virtual bool Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs, + virtual bool Pull(int tagId, const vector<int32_t>& uids, int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data); // Clear pull data cache immediately. @@ -114,9 +115,9 @@ public: // Clear pull data cache if it is beyond respective cool down time. int ClearPullerCacheIfNecessary(int64_t timestampNs); - void SetStatsCompanionService(shared_ptr<IStatsCompanionService> statsCompanionService); + void SetStatsCompanionService(const shared_ptr<IStatsCompanionService>& statsCompanionService); - void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs, + void RegisterPullAtomCallback(const int uid, const int32_t atomTag, int64_t coolDownNs, const int64_t timeoutNs, const vector<int32_t>& additiveFields, const shared_ptr<IPullAtomCallback>& callback); @@ -151,10 +152,10 @@ private: // mapping from Config Key to the PullUidProvider for that config std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders; - bool PullLocked(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs, + bool PullLocked(int tagId, const ConfigKey& configKey, int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data); - bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs, + bool PullLocked(int tagId, const vector<int32_t>& uids, int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data); // locks for data receiver and StatsCompanionService changes diff --git a/statsd/src/guardrail/StatsdStats.cpp b/statsd/src/guardrail/StatsdStats.cpp index 939d39fa..191ea3fa 100644 --- a/statsd/src/guardrail/StatsdStats.cpp +++ b/statsd/src/guardrail/StatsdStats.cpp @@ -62,6 +62,7 @@ const int FIELD_ID_SHARD_OFFSET = 21; const int FIELD_ID_STATSD_STATS_ID = 22; const int FIELD_ID_SUBSCRIPTION_STATS = 23; const int FIELD_ID_SOCKET_LOSS_STATS = 24; +const int FIELD_ID_QUEUE_STATS = 25; const int FIELD_ID_RESTRICTED_METRIC_QUERY_STATS_CALLING_UID = 1; const int FIELD_ID_RESTRICTED_METRIC_QUERY_STATS_CONFIG_ID = 2; @@ -93,6 +94,9 @@ const int FIELD_ID_OVERFLOW_COUNT = 1; const int FIELD_ID_OVERFLOW_MAX_HISTORY = 2; const int FIELD_ID_OVERFLOW_MIN_HISTORY = 3; +const int FIELD_ID_QUEUE_MAX_SIZE_OBSERVED = 1; +const int FIELD_ID_QUEUE_MAX_SIZE_OBSERVED_ELAPSED_NANOS = 2; + const int FIELD_ID_CONFIG_STATS_UID = 1; const int FIELD_ID_CONFIG_STATS_ID = 2; const int FIELD_ID_CONFIG_STATS_CREATION = 3; @@ -361,6 +365,15 @@ void StatsdStats::noteEventQueueOverflow(int64_t oldestEventTimestampNs, int32_t noteAtomDroppedLocked(atomId); } +void StatsdStats::noteEventQueueSize(int32_t size, int64_t eventTimestampNs) { + lock_guard<std::mutex> lock(mLock); + + if (mEventQueueMaxSizeObserved < size) { + mEventQueueMaxSizeObserved = size; + mEventQueueMaxSizeObservedElapsedNanos = eventTimestampNs; + } +} + void StatsdStats::noteAtomDroppedLocked(int32_t atomId) { constexpr int kMaxPushedAtomDroppedStatsSize = kMaxPushedAtomId + kMaxNonPlatformPushedAtoms; if (mPushedAtomDropsStats.size() < kMaxPushedAtomDroppedStatsSize || @@ -532,7 +545,7 @@ void StatsdStats::setCurrentUidMapMemory(int bytes) { mUidMapStats.bytes_used = bytes; } -void StatsdStats::noteConditionDimensionSize(const ConfigKey& key, const int64_t& id, int size) { +void StatsdStats::noteConditionDimensionSize(const ConfigKey& key, const int64_t id, int size) { lock_guard<std::mutex> lock(mLock); // if name doesn't exist before, it will create the key with count 0. auto statsIt = mConfigStats.find(key); @@ -546,7 +559,7 @@ void StatsdStats::noteConditionDimensionSize(const ConfigKey& key, const int64_t } } -void StatsdStats::noteMetricDimensionSize(const ConfigKey& key, const int64_t& id, int size) { +void StatsdStats::noteMetricDimensionSize(const ConfigKey& key, const int64_t id, int size) { lock_guard<std::mutex> lock(mLock); // if name doesn't exist before, it will create the key with count 0. auto statsIt = mConfigStats.find(key); @@ -559,8 +572,8 @@ void StatsdStats::noteMetricDimensionSize(const ConfigKey& key, const int64_t& i } } -void StatsdStats::noteMetricDimensionInConditionSize( - const ConfigKey& key, const int64_t& id, int size) { +void StatsdStats::noteMetricDimensionInConditionSize(const ConfigKey& key, const int64_t id, + int size) { lock_guard<std::mutex> lock(mLock); // if name doesn't exist before, it will create the key with count 0. auto statsIt = mConfigStats.find(key); @@ -573,7 +586,7 @@ void StatsdStats::noteMetricDimensionInConditionSize( } } -void StatsdStats::noteMatcherMatched(const ConfigKey& key, const int64_t& id) { +void StatsdStats::noteMatcherMatched(const ConfigKey& key, const int64_t id) { lock_guard<std::mutex> lock(mLock); auto statsIt = mConfigStats.find(key); @@ -583,7 +596,7 @@ void StatsdStats::noteMatcherMatched(const ConfigKey& key, const int64_t& id) { statsIt->second->matcher_stats[id]++; } -void StatsdStats::noteAnomalyDeclared(const ConfigKey& key, const int64_t& id) { +void StatsdStats::noteAnomalyDeclared(const ConfigKey& key, const int64_t id) { lock_guard<std::mutex> lock(mLock); auto statsIt = mConfigStats.find(key); if (statsIt == mConfigStats.end()) { @@ -1029,6 +1042,8 @@ void StatsdStats::resetInternalLocked() { mOverflowCount = 0; mMinQueueHistoryNs = kInt64Max; mMaxQueueHistoryNs = 0; + mEventQueueMaxSizeObserved = 0; + mEventQueueMaxSizeObservedElapsedNanos = 0; for (auto& config : mConfigStats) { config.second->broadcast_sent_time_sec.clear(); config.second->activation_time_sec.clear(); @@ -1124,7 +1139,7 @@ int StatsdStats::getPushedAtomDropsLocked(int atomId) const { } } -bool StatsdStats::hasRestrictedConfigErrors(std::shared_ptr<ConfigStats> configStats) const { +bool StatsdStats::hasRestrictedConfigErrors(const std::shared_ptr<ConfigStats>& configStats) const { return configStats->device_info_table_creation_failed || configStats->db_corrupted_count || configStats->db_deletion_size_exceeded_limit || configStats->db_deletion_stat_failed || configStats->db_deletion_config_invalid || configStats->db_deletion_too_old || @@ -1428,6 +1443,8 @@ void StatsdStats::dumpStats(int out) const { dprintf(out, "********EventQueueOverflow stats***********\n"); dprintf(out, "Event queue overflow: %d; MaxHistoryNs: %lld; MinHistoryNs: %lld\n", mOverflowCount, (long long)mMaxQueueHistoryNs, (long long)mMinQueueHistoryNs); + dprintf(out, "Event queue max size: %d; Observed at : %lld\n", mEventQueueMaxSizeObserved, + (long long)mEventQueueMaxSizeObservedElapsedNanos); if (mActivationBroadcastGuardrailStats.size() > 0) { dprintf(out, "********mActivationBroadcastGuardrail stats***********\n"); @@ -1783,6 +1800,13 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) { proto.end(token); } + uint64_t queueStatsToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_QUEUE_STATS); + proto.write(FIELD_TYPE_INT32 | FIELD_ID_QUEUE_MAX_SIZE_OBSERVED, + (int32_t)mEventQueueMaxSizeObserved); + proto.write(FIELD_TYPE_INT64 | FIELD_ID_QUEUE_MAX_SIZE_OBSERVED_ELAPSED_NANOS, + (long long)mEventQueueMaxSizeObservedElapsedNanos); + proto.end(queueStatsToken); + for (const auto& restart : mSystemServerRestartSec) { proto.write(FIELD_TYPE_INT32 | FIELD_ID_SYSTEM_SERVER_RESTART | FIELD_COUNT_REPEATED, restart); diff --git a/statsd/src/guardrail/StatsdStats.h b/statsd/src/guardrail/StatsdStats.h index c7ca8d0c..e3ab443c 100644 --- a/statsd/src/guardrail/StatsdStats.h +++ b/statsd/src/guardrail/StatsdStats.h @@ -395,7 +395,7 @@ public: * [id]: The id of the condition. * [size]: The output tuple size. */ - void noteConditionDimensionSize(const ConfigKey& key, const int64_t& id, int size); + void noteConditionDimensionSize(const ConfigKey& key, int64_t id, int size); /** * Report the size of output tuple of a metric. @@ -407,7 +407,7 @@ public: * [id]: The id of the metric. * [size]: The output tuple size. */ - void noteMetricDimensionSize(const ConfigKey& key, const int64_t& id, int size); + void noteMetricDimensionSize(const ConfigKey& key, int64_t id, int size); /** * Report the max size of output tuple of dimension in condition across dimensions in what. @@ -419,7 +419,7 @@ public: * [id]: The id of the metric. * [size]: The output tuple size. */ - void noteMetricDimensionInConditionSize(const ConfigKey& key, const int64_t& id, int size); + void noteMetricDimensionInConditionSize(const ConfigKey& key, int64_t id, int size); /** * Report a matcher has been matched. @@ -427,7 +427,7 @@ public: * [key]: The config key that this matcher belongs to. * [id]: The id of the matcher. */ - void noteMatcherMatched(const ConfigKey& key, const int64_t& id); + void noteMatcherMatched(const ConfigKey& key, int64_t id); /** * Report that an anomaly detection alert has been declared. @@ -435,7 +435,7 @@ public: * [key]: The config key that this alert belongs to. * [id]: The id of the alert. */ - void noteAnomalyDeclared(const ConfigKey& key, const int64_t& id); + void noteAnomalyDeclared(const ConfigKey& key, int64_t id); /** * Report an atom event has been logged. @@ -614,6 +614,9 @@ public: * in the queue */ void noteEventQueueOverflow(int64_t oldestEventTimestampNs, int32_t atomId, bool isSkipped); + /* Notes queue max size seen so far and associated timestamp */ + void noteEventQueueSize(int32_t size, int64_t eventTimestampNs); + /** * Reports that the activation broadcast guardrail was hit for this uid. Namely, the broadcast * should have been sent, but instead was skipped due to hitting the guardrail. @@ -633,7 +636,7 @@ public: /** Report query of restricted metric succeed **/ void noteQueryRestrictedMetricSucceed(const int64_t configId, const string& configPackage, const std::optional<int32_t> configUid, - const int32_t callingUid, const int64_t queryLatencyNs); + const int32_t callingUid, int64_t queryLatencyNs); /** Report query of restricted metric failed **/ void noteQueryRestrictedMetricFailed(const int64_t configId, const string& configPackage, @@ -650,24 +653,24 @@ public: void noteRestrictedMetricInsertError(const ConfigKey& configKey, int64_t metricId); // Reports that a restricted metric fails to create table in database. - void noteRestrictedMetricTableCreationError(const ConfigKey& configKey, const int64_t metricId); + void noteRestrictedMetricTableCreationError(const ConfigKey& configKey, int64_t metricId); // Reports that a restricted metric fails to delete table in database. - void noteRestrictedMetricTableDeletionError(const ConfigKey& configKey, const int64_t metricId); + void noteRestrictedMetricTableDeletionError(const ConfigKey& configKey, int64_t metricId); // Reports the time it takes for a restricted metric to flush the data to the database. - void noteRestrictedMetricFlushLatency(const ConfigKey& configKey, const int64_t metricId, + void noteRestrictedMetricFlushLatency(const ConfigKey& configKey, int64_t metricId, const int64_t flushLatencyNs); // Reports that a restricted metric had a category change. - void noteRestrictedMetricCategoryChanged(const ConfigKey& configKey, const int64_t metricId); + void noteRestrictedMetricCategoryChanged(const ConfigKey& configKey, int64_t metricId); // Reports the time is takes to flush a restricted config to the database. void noteRestrictedConfigFlushLatency(const ConfigKey& configKey, const int64_t totalFlushLatencyNs); // Reports the size of the internal sqlite db. - void noteRestrictedConfigDbSize(const ConfigKey& configKey, const int64_t elapsedTimeNs, + void noteRestrictedConfigDbSize(const ConfigKey& configKey, int64_t elapsedTimeNs, const int64_t dbSize); /** @@ -824,7 +827,7 @@ private: // Stores the stats for the configs that are no longer in use. // The size of the vector is capped by kMaxIceBoxSize. - std::list<const std::shared_ptr<ConfigStats>> mIceBox; + std::list<std::shared_ptr<ConfigStats>> mIceBox; // Stores the number of times a pushed atom is logged and skipped (if skipped). // The size of the vector is the largest pushed atom id in atoms.proto + 1. Atoms @@ -922,6 +925,12 @@ private: // Total number of events that are lost due to queue overflow. int32_t mOverflowCount = 0; + // Max number of events stored into the queue seen so far. + int32_t mEventQueueMaxSizeObserved = 0; + + // Event timestamp for associated max size hit. + int64_t mEventQueueMaxSizeObservedElapsedNanos = 0; + // Timestamps when we detect log loss, and the number of logs lost. std::list<LogLossStats> mLogLossStats; @@ -1001,7 +1010,7 @@ private: int getPushedAtomDropsLocked(int atomId) const; - bool hasRestrictedConfigErrors(std::shared_ptr<ConfigStats> configStats) const; + bool hasRestrictedConfigErrors(const std::shared_ptr<ConfigStats>& configStats) const; /** * Get a reference to AtomMetricStats for a metric. If none exists, create it. The reference @@ -1009,40 +1018,42 @@ private: */ StatsdStats::AtomMetricStats& getAtomMetricStats(int64_t metricId); - FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd); + FRIEND_TEST(LogEventQueue_test, TestQueueMaxSize); + FRIEND_TEST(SocketParseMessageTest, TestProcessMessage); + FRIEND_TEST(StatsLogProcessorTest, InvalidConfigRemoved); + FRIEND_TEST(StatsdStatsTest, TestActivationBroadcastGuardrailHit); + FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor); + FRIEND_TEST(StatsdStatsTest, TestAtomDroppedStats); + FRIEND_TEST(StatsdStatsTest, TestAtomErrorStats); + FRIEND_TEST(StatsdStatsTest, TestAtomLog); + FRIEND_TEST(StatsdStatsTest, TestAtomLoggedAndDroppedAndSkippedStats); + FRIEND_TEST(StatsdStatsTest, TestAtomLoggedAndDroppedStats); + FRIEND_TEST(StatsdStatsTest, TestAtomMetricsStats); + FRIEND_TEST(StatsdStatsTest, TestAtomSkippedStats); + FRIEND_TEST(StatsdStatsTest, TestConfigRemove); + FRIEND_TEST(StatsdStatsTest, TestHasHitDimensionGuardrail); FRIEND_TEST(StatsdStatsTest, TestInvalidConfigAdd); FRIEND_TEST(StatsdStatsTest, TestInvalidConfigMissingMetricId); FRIEND_TEST(StatsdStatsTest, TestInvalidConfigOnlyMetricId); - FRIEND_TEST(StatsdStatsTest, TestConfigRemove); - FRIEND_TEST(StatsdStatsTest, TestSubStats); - FRIEND_TEST(StatsdStatsTest, TestAtomLog); FRIEND_TEST(StatsdStatsTest, TestNonPlatformAtomLog); - FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold); - FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor); - FRIEND_TEST(StatsdStatsTest, TestSystemServerCrash); FRIEND_TEST(StatsdStatsTest, TestPullAtomStats); - FRIEND_TEST(StatsdStatsTest, TestAtomMetricsStats); - FRIEND_TEST(StatsdStatsTest, TestActivationBroadcastGuardrailHit); - FRIEND_TEST(StatsdStatsTest, TestAtomErrorStats); - FRIEND_TEST(StatsdStatsTest, TestAtomSkippedStats); - FRIEND_TEST(StatsdStatsTest, TestRestrictedMetricsStats); + FRIEND_TEST(StatsdStatsTest, TestQueueStats); FRIEND_TEST(StatsdStatsTest, TestRestrictedMetricsQueryStats); - FRIEND_TEST(StatsdStatsTest, TestAtomDroppedStats); - FRIEND_TEST(StatsdStatsTest, TestAtomLoggedAndDroppedStats); - FRIEND_TEST(StatsdStatsTest, TestAtomLoggedAndDroppedAndSkippedStats); + FRIEND_TEST(StatsdStatsTest, TestRestrictedMetricsStats); FRIEND_TEST(StatsdStatsTest, TestShardOffsetProvider); - FRIEND_TEST(StatsdStatsTest, TestHasHitDimensionGuardrail); - FRIEND_TEST(StatsdStatsTest, TestSubscriptionStarted); - FRIEND_TEST(StatsdStatsTest, TestSubscriptionFlushed); - FRIEND_TEST(StatsdStatsTest, TestSubscriptionEnded); + FRIEND_TEST(StatsdStatsTest, TestSocketLossStats); + FRIEND_TEST(StatsdStatsTest, TestSocketLossStatsOverflowCounter); + FRIEND_TEST(StatsdStatsTest, TestSubStats); FRIEND_TEST(StatsdStatsTest, TestSubscriptionAtomPulled); + FRIEND_TEST(StatsdStatsTest, TestSubscriptionEnded); + FRIEND_TEST(StatsdStatsTest, TestSubscriptionFlushed); FRIEND_TEST(StatsdStatsTest, TestSubscriptionPullThreadWakeup); + FRIEND_TEST(StatsdStatsTest, TestSubscriptionStarted); FRIEND_TEST(StatsdStatsTest, TestSubscriptionStartedMaxActiveSubscriptions); FRIEND_TEST(StatsdStatsTest, TestSubscriptionStartedRemoveFinishedSubscription); - FRIEND_TEST(StatsdStatsTest, TestSocketLossStats); - FRIEND_TEST(StatsdStatsTest, TestSocketLossStatsOverflowCounter); - - FRIEND_TEST(StatsLogProcessorTest, InvalidConfigRemoved); + FRIEND_TEST(StatsdStatsTest, TestSystemServerCrash); + FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold); + FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd); }; InvalidConfigReason createInvalidConfigReasonWithMatcher(const InvalidConfigReasonEnum reason, @@ -1077,10 +1088,10 @@ InvalidConfigReason createInvalidConfigReasonWithSubscription(const InvalidConfi const int64_t subscriptionId); InvalidConfigReason createInvalidConfigReasonWithSubscriptionAndAlarm( - const InvalidConfigReasonEnum reason, const int64_t subscriptionId, const int64_t alarmId); + const InvalidConfigReasonEnum reason, int64_t subscriptionId, int64_t alarmId); InvalidConfigReason createInvalidConfigReasonWithSubscriptionAndAlert( - const InvalidConfigReasonEnum reason, const int64_t subscriptionId, const int64_t alertId); + const InvalidConfigReasonEnum reason, int64_t subscriptionId, int64_t alertId); } // namespace statsd } // namespace os diff --git a/statsd/src/guardrail/stats_log_enums.proto b/statsd/src/guardrail/stats_log_enums.proto index 3db1e088..d47bc80b 100644 --- a/statsd/src/guardrail/stats_log_enums.proto +++ b/statsd/src/guardrail/stats_log_enums.proto @@ -142,6 +142,12 @@ enum InvalidConfigReasonEnum { INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_ENABLED = 84; INVALID_CONFIG_REASON_RESTRICTED_METRIC_NOT_SUPPORTED = 85; INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE = 86; + INVALID_CONFIG_REASON_GAUGE_METRIC_PULLED_WITH_SAMPLING = 87; + INVALID_CONFIG_REASON_MATCHER_NO_VALUE_MATCHER_NOR_STRING_REPLACER = 88; + INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL = 89; + INVALID_CONFIG_REASON_MATCHER_INVALID_VALUE_MATCHER_WITH_STRING_REPLACE = 90; + INVALID_CONFIG_REASON_MATCHER_COMBINATION_WITH_STRING_REPLACE = 91; + INVALID_CONFIG_REASON_MATCHER_STRING_REPLACE_WITH_NO_VALUE_MATCHER_WITH_POSITION_ANY = 92; }; enum InvalidQueryReason { diff --git a/statsd/src/logd/LogEventQueue.cpp b/statsd/src/logd/LogEventQueue.cpp index 96b7f015..a83fcf81 100644 --- a/statsd/src/logd/LogEventQueue.cpp +++ b/statsd/src/logd/LogEventQueue.cpp @@ -39,22 +39,23 @@ unique_ptr<LogEvent> LogEventQueue::waitPop() { return item; } -bool LogEventQueue::push(unique_ptr<LogEvent> item, int64_t* oldestTimestampNs) { - bool success; +LogEventQueue::Result LogEventQueue::push(unique_ptr<LogEvent> item) { + Result result; { std::unique_lock<std::mutex> lock(mMutex); if (mQueue.size() < mQueueLimit) { mQueue.push(std::move(item)); - success = true; + result.success = true; } else { // safe operation as queue must not be empty. - *oldestTimestampNs = mQueue.front()->GetElapsedTimestampNs(); - success = false; + result.oldestTimestampNs = mQueue.front()->GetElapsedTimestampNs(); + result.success = false; } + result.size = mQueue.size(); } mCondition.notify_one(); - return success; + return result; } } // namespace statsd diff --git a/statsd/src/logd/LogEventQueue.h b/statsd/src/logd/LogEventQueue.h index 53f2adf2..d01f3a94 100644 --- a/statsd/src/logd/LogEventQueue.h +++ b/statsd/src/logd/LogEventQueue.h @@ -40,12 +40,18 @@ public: */ std::unique_ptr<LogEvent> waitPop(); + struct Result { + bool success = false; + int64_t oldestTimestampNs = 0; + int32_t size = 0; + }; + /** * Puts a LogEvent ptr to the end of the queue. * Returns false on failure when the queue is full, and output the oldest event timestamp - * in the queue. + * in the queue. Returns true on success and new queue size. */ - bool push(std::unique_ptr<LogEvent> event, int64_t* oldestTimestampNs); + Result push(std::unique_ptr<LogEvent> event); private: const size_t mQueueLimit; diff --git a/statsd/src/matchers/AtomMatchingTracker.h b/statsd/src/matchers/AtomMatchingTracker.h index 3e35d9bf..49c35b27 100644 --- a/statsd/src/matchers/AtomMatchingTracker.h +++ b/statsd/src/matchers/AtomMatchingTracker.h @@ -32,14 +32,20 @@ namespace android { namespace os { namespace statsd { +struct MatcherInitResult { + optional<InvalidConfigReason> invalidConfigReason; + bool hasStringTransformation; +}; + class AtomMatchingTracker : public virtual RefBase { public: - AtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash) - : mId(id), mIndex(index), mInitialized(false), mProtoHash(protoHash){}; + AtomMatchingTracker(const int64_t id, const uint64_t protoHash) + : mId(id), mInitialized(false), mProtoHash(protoHash){}; virtual ~AtomMatchingTracker(){}; // Initialize this AtomMatchingTracker. + // matcherIndex: index of this AtomMatchingTracker in allAtomMatchingTrackers. // allAtomMatchers: the list of the AtomMatcher proto config. This is needed because we don't // store the proto object in memory. We only need it during initilization. // allAtomMatchingTrackers: the list of the AtomMatchingTracker objects. It's a one-to-one @@ -48,30 +54,32 @@ public: // CombinationAtomMatchingTrackers using DFS. // stack: a bit map to record which matcher has been visited on the stack. This is for detecting // circle dependency. - virtual optional<InvalidConfigReason> init( - const std::vector<AtomMatcher>& allAtomMatchers, + virtual MatcherInitResult init( + int matcherIndex, const std::vector<AtomMatcher>& allAtomMatchers, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack) = 0; + const std::unordered_map<int64_t, int>& matcherMap, std::vector<uint8_t>& stack) = 0; // Update appropriate state on config updates. Primarily, all indices need to be updated. // This matcher and all of its children are guaranteed to be preserved across the update. // matcher: the AtomMatcher proto from the config. - // index: the index of this matcher in mAllAtomMatchingTrackers. // atomMatchingTrackerMap: map from matcher id to index in mAllAtomMatchingTrackers virtual optional<InvalidConfigReason> onConfigUpdated( - const AtomMatcher& matcher, const int index, + const AtomMatcher& matcher, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) = 0; // Called when a log event comes. // event: the log event. + // matcherIndex: index of this AtomMatchingTracker in allAtomMatchingTrackers. // allAtomMatchingTrackers: the list of all AtomMatchingTrackers. This is needed because the log // processing is done recursively. // matcherResults: The cached results for all matchers for this event. Parent matchers can // directly access the children's matching results if they have been evaluated. // Otherwise, call children matchers' onLogEvent. - virtual void onLogEvent(const LogEvent& event, + // matcherTransformations: the cached transformations for all matchers for this event. + virtual void onLogEvent(const LogEvent& event, int matcherIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - std::vector<MatchingState>& matcherResults) = 0; + std::vector<MatchingState>& matcherResults, + std::vector<std::shared_ptr<LogEvent>>& matcherTransformations) = 0; // Get the tagIds that this matcher cares about. The combined collection is stored // in MetricMananger, so that we can pass any LogEvents that are not interest of us. It uses @@ -96,9 +104,6 @@ protected: // Name of this matching. We don't really need the name, but it makes log message easy to debug. const int64_t mId; - // Index of this AtomMatchingTracker in MetricsManager's container. - int mIndex; - // Whether this AtomMatchingTracker has been properly initialized. bool mInitialized; diff --git a/statsd/src/matchers/CombinationAtomMatchingTracker.cpp b/statsd/src/matchers/CombinationAtomMatchingTracker.cpp index 846a5308..bc75eef6 100644 --- a/statsd/src/matchers/CombinationAtomMatchingTracker.cpp +++ b/statsd/src/matchers/CombinationAtomMatchingTracker.cpp @@ -25,52 +25,58 @@ namespace os { namespace statsd { using std::set; +using std::shared_ptr; using std::unordered_map; using std::vector; -CombinationAtomMatchingTracker::CombinationAtomMatchingTracker(const int64_t& id, const int index, +CombinationAtomMatchingTracker::CombinationAtomMatchingTracker(const int64_t id, const uint64_t protoHash) - : AtomMatchingTracker(id, index, protoHash) { + : AtomMatchingTracker(id, protoHash) { } CombinationAtomMatchingTracker::~CombinationAtomMatchingTracker() { } -optional<InvalidConfigReason> CombinationAtomMatchingTracker::init( - const vector<AtomMatcher>& allAtomMatchers, +MatcherInitResult CombinationAtomMatchingTracker::init( + int matcherIndex, const vector<AtomMatcher>& allAtomMatchers, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - const unordered_map<int64_t, int>& matcherMap, vector<bool>& stack) { + const unordered_map<int64_t, int>& matcherMap, vector<uint8_t>& stack) { + MatcherInitResult result{nullopt /* invalidConfigReason */, + false /* hasStringTransformation */}; if (mInitialized) { - return nullopt; + // CombinationMatchers do not support string transformations so if mInitialized = true, + // we know that there is no string transformation and we do not need to check for it again. + return result; } // mark this node as visited in the recursion stack. - stack[mIndex] = true; + stack[matcherIndex] = true; - AtomMatcher_Combination matcher = allAtomMatchers[mIndex].combination(); + AtomMatcher_Combination matcher = allAtomMatchers[matcherIndex].combination(); // LogicalOperation is missing in the config if (!matcher.has_operation()) { - return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_NO_OPERATION, - mId); + result.invalidConfigReason = createInvalidConfigReasonWithMatcher( + INVALID_CONFIG_REASON_MATCHER_NO_OPERATION, mId); + return result; } mLogicalOperation = matcher.operation(); if (mLogicalOperation == LogicalOperation::NOT && matcher.matcher_size() != 1) { - return createInvalidConfigReasonWithMatcher( + result.invalidConfigReason = createInvalidConfigReasonWithMatcher( INVALID_CONFIG_REASON_MATCHER_NOT_OPERATION_IS_NOT_UNARY, mId); + return result; } for (const auto& child : matcher.matcher()) { auto pair = matcherMap.find(child); if (pair == matcherMap.end()) { ALOGW("Matcher %lld not found in the config", (long long)child); - optional<InvalidConfigReason> invalidConfigReason = - createInvalidConfigReasonWithMatcher( - INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND, mId); - invalidConfigReason->matcherIds.push_back(child); - return invalidConfigReason; + result.invalidConfigReason = createInvalidConfigReasonWithMatcher( + INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND, mId); + result.invalidConfigReason->matcherIds.push_back(child); + return result; } int childIndex = pair->second; @@ -78,18 +84,27 @@ optional<InvalidConfigReason> CombinationAtomMatchingTracker::init( // if the child is a visited node in the recursion -> circle detected. if (stack[childIndex]) { ALOGE("Circle detected in matcher config"); - optional<InvalidConfigReason> invalidConfigReason = + result.invalidConfigReason = createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_CYCLE, mId); - invalidConfigReason->matcherIds.push_back(child); - return invalidConfigReason; + result.invalidConfigReason->matcherIds.push_back(child); + return result; + } + auto [invalidConfigReason, hasStringTransformation] = + allAtomMatchingTrackers[childIndex]->init( + childIndex, allAtomMatchers, allAtomMatchingTrackers, matcherMap, stack); + if (hasStringTransformation) { + ALOGE("String transformation detected in CombinationMatcher"); + result.invalidConfigReason = createInvalidConfigReasonWithMatcher( + INVALID_CONFIG_REASON_MATCHER_COMBINATION_WITH_STRING_REPLACE, mId); + result.hasStringTransformation = true; + return result; } - optional<InvalidConfigReason> invalidConfigReason = - allAtomMatchingTrackers[childIndex]->init(allAtomMatchers, allAtomMatchingTrackers, - matcherMap, stack); + if (invalidConfigReason.has_value()) { ALOGW("child matcher init failed %lld", (long long)child); invalidConfigReason->matcherIds.push_back(mId); - return invalidConfigReason; + result.invalidConfigReason = invalidConfigReason; + return result; } mChildren.push_back(childIndex); @@ -100,14 +115,12 @@ optional<InvalidConfigReason> CombinationAtomMatchingTracker::init( mInitialized = true; // unmark this node in the recursion stack. - stack[mIndex] = false; - return nullopt; + stack[matcherIndex] = false; + return result; } optional<InvalidConfigReason> CombinationAtomMatchingTracker::onConfigUpdated( - const AtomMatcher& matcher, const int index, - const unordered_map<int64_t, int>& atomMatchingTrackerMap) { - mIndex = index; + const AtomMatcher& matcher, const unordered_map<int64_t, int>& atomMatchingTrackerMap) { mChildren.clear(); AtomMatcher_Combination combinationMatcher = matcher.combination(); for (const int64_t child : combinationMatcher.matcher()) { @@ -126,15 +139,17 @@ optional<InvalidConfigReason> CombinationAtomMatchingTracker::onConfigUpdated( } void CombinationAtomMatchingTracker::onLogEvent( - const LogEvent& event, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - vector<MatchingState>& matcherResults) { + const LogEvent& event, int matcherIndex, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + vector<MatchingState>& matcherResults, + vector<shared_ptr<LogEvent>>& matcherTransformations) { // this event has been processed. - if (matcherResults[mIndex] != MatchingState::kNotComputed) { + if (matcherResults[matcherIndex] != MatchingState::kNotComputed) { return; } if (mAtomIds.find(event.GetTagId()) == mAtomIds.end()) { - matcherResults[mIndex] = MatchingState::kNotMatched; + matcherResults[matcherIndex] = MatchingState::kNotMatched; return; } @@ -142,12 +157,13 @@ void CombinationAtomMatchingTracker::onLogEvent( for (const int childIndex : mChildren) { if (matcherResults[childIndex] == MatchingState::kNotComputed) { const sp<AtomMatchingTracker>& child = allAtomMatchingTrackers[childIndex]; - child->onLogEvent(event, allAtomMatchingTrackers, matcherResults); + child->onLogEvent(event, childIndex, allAtomMatchingTrackers, matcherResults, + matcherTransformations); } } bool matched = combinationMatch(mChildren, mLogicalOperation, matcherResults); - matcherResults[mIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched; + matcherResults[matcherIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched; } } // namespace statsd diff --git a/statsd/src/matchers/CombinationAtomMatchingTracker.h b/statsd/src/matchers/CombinationAtomMatchingTracker.h index edcbb49c..9e065330 100644 --- a/statsd/src/matchers/CombinationAtomMatchingTracker.h +++ b/statsd/src/matchers/CombinationAtomMatchingTracker.h @@ -29,22 +29,23 @@ namespace statsd { // Represents a AtomMatcher_Combination in the StatsdConfig. class CombinationAtomMatchingTracker : public AtomMatchingTracker { public: - CombinationAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash); + CombinationAtomMatchingTracker(const int64_t id, const uint64_t protoHash); - optional<InvalidConfigReason> init( - const std::vector<AtomMatcher>& allAtomMatchers, - const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack); + MatcherInitResult init(int matcherIndex, const std::vector<AtomMatcher>& allAtomMatchers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const std::unordered_map<int64_t, int>& matcherMap, + std::vector<uint8_t>& stack); optional<InvalidConfigReason> onConfigUpdated( - const AtomMatcher& matcher, const int index, + const AtomMatcher& matcher, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override; ~CombinationAtomMatchingTracker(); - void onLogEvent(const LogEvent& event, + void onLogEvent(const LogEvent& event, int matcherIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - std::vector<MatchingState>& matcherResults) override; + std::vector<MatchingState>& matcherResults, + std::vector<std::shared_ptr<LogEvent>>& matcherTransformations) override; private: LogicalOperation mLogicalOperation; diff --git a/statsd/src/matchers/EventMatcherWizard.cpp b/statsd/src/matchers/EventMatcherWizard.cpp index 30a40a33..1dbe5e02 100644 --- a/statsd/src/matchers/EventMatcherWizard.cpp +++ b/statsd/src/matchers/EventMatcherWizard.cpp @@ -21,15 +21,18 @@ namespace statsd { using std::vector; -MatchingState EventMatcherWizard::matchLogEvent(const LogEvent& event, int matcher_index) { - if (matcher_index < 0 || matcher_index >= (int)mAllEventMatchers.size()) { - return MatchingState::kNotComputed; +MatchLogEventResult EventMatcherWizard::matchLogEvent(const LogEvent& event, int matcherIndex) { + if (matcherIndex < 0 || matcherIndex >= (int)mAllEventMatchers.size()) { + return {MatchingState::kNotComputed, nullptr}; } std::fill(mMatcherCache.begin(), mMatcherCache.end(), MatchingState::kNotComputed); - mAllEventMatchers[matcher_index]->onLogEvent(event, mAllEventMatchers, mMatcherCache); - return mMatcherCache[matcher_index]; + std::fill(mMatcherTransformations.begin(), mMatcherTransformations.end(), nullptr); + mAllEventMatchers[matcherIndex]->onLogEvent(event, matcherIndex, mAllEventMatchers, + mMatcherCache, mMatcherTransformations); + + return {mMatcherCache[matcherIndex], mMatcherTransformations[matcherIndex]}; } } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/statsd/src/matchers/EventMatcherWizard.h b/statsd/src/matchers/EventMatcherWizard.h index 7bd4529c..b2ef311d 100644 --- a/statsd/src/matchers/EventMatcherWizard.h +++ b/statsd/src/matchers/EventMatcherWizard.h @@ -22,20 +22,27 @@ namespace android { namespace os { namespace statsd { +struct MatchLogEventResult { + MatchingState matchingState; + std::shared_ptr<LogEvent> transformedEvent; +}; + class EventMatcherWizard : public virtual RefBase { public: EventMatcherWizard(){}; // for testing EventMatcherWizard(const std::vector<sp<AtomMatchingTracker>>& eventTrackers) : mAllEventMatchers(eventTrackers), - mMatcherCache(eventTrackers.size(), MatchingState::kNotComputed){}; + mMatcherCache(eventTrackers.size(), MatchingState::kNotComputed), + mMatcherTransformations(eventTrackers.size(), nullptr){}; virtual ~EventMatcherWizard(){}; - MatchingState matchLogEvent(const LogEvent& event, int matcher_index); + MatchLogEventResult matchLogEvent(const LogEvent& event, int matcherIndex); private: std::vector<sp<AtomMatchingTracker>> mAllEventMatchers; std::vector<MatchingState> mMatcherCache; + std::vector<std::shared_ptr<LogEvent>> mMatcherTransformations; }; } // namespace statsd diff --git a/statsd/src/matchers/SimpleAtomMatchingTracker.cpp b/statsd/src/matchers/SimpleAtomMatchingTracker.cpp index a0e30b24..db45560a 100644 --- a/statsd/src/matchers/SimpleAtomMatchingTracker.cpp +++ b/statsd/src/matchers/SimpleAtomMatchingTracker.cpp @@ -23,14 +23,14 @@ namespace android { namespace os { namespace statsd { +using std::shared_ptr; using std::unordered_map; using std::vector; -SimpleAtomMatchingTracker::SimpleAtomMatchingTracker(const int64_t& id, const int index, - const uint64_t protoHash, +SimpleAtomMatchingTracker::SimpleAtomMatchingTracker(const int64_t id, const uint64_t protoHash, const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap) - : AtomMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) { + : AtomMatchingTracker(id, protoHash), mMatcher(matcher), mUidMap(uidMap) { if (!matcher.has_atom_id()) { mInitialized = false; } else { @@ -42,22 +42,31 @@ SimpleAtomMatchingTracker::SimpleAtomMatchingTracker(const int64_t& id, const in SimpleAtomMatchingTracker::~SimpleAtomMatchingTracker() { } -optional<InvalidConfigReason> SimpleAtomMatchingTracker::init( - const vector<AtomMatcher>& allAtomMatchers, +MatcherInitResult SimpleAtomMatchingTracker::init( + int matcherIndex, const vector<AtomMatcher>& allAtomMatchers, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - const unordered_map<int64_t, int>& matcherMap, vector<bool>& stack) { + const unordered_map<int64_t, int>& matcherMap, vector<uint8_t>& stack) { + MatcherInitResult result{nullopt /* invalidConfigReason */, + false /* hasStringTransformation */}; // no need to do anything. if (!mInitialized) { - return createInvalidConfigReasonWithMatcher( + result.invalidConfigReason = createInvalidConfigReasonWithMatcher( INVALID_CONFIG_REASON_MATCHER_TRACKER_NOT_INITIALIZED, mId); + return result; } - return nullopt; + + for (const FieldValueMatcher& fvm : mMatcher.field_value_matcher()) { + if (fvm.has_replace_string()) { + result.hasStringTransformation = true; + break; + } + } + + return result; } optional<InvalidConfigReason> SimpleAtomMatchingTracker::onConfigUpdated( - const AtomMatcher& matcher, const int index, - const unordered_map<int64_t, int>& atomMatchingTrackerMap) { - mIndex = index; + const AtomMatcher& matcher, const unordered_map<int64_t, int>& atomMatchingTrackerMap) { // Do not need to update mMatcher since the matcher must be identical across the update. if (!mInitialized) { return createInvalidConfigReasonWithMatcher( @@ -67,21 +76,27 @@ optional<InvalidConfigReason> SimpleAtomMatchingTracker::onConfigUpdated( } void SimpleAtomMatchingTracker::onLogEvent( - const LogEvent& event, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - vector<MatchingState>& matcherResults) { - if (matcherResults[mIndex] != MatchingState::kNotComputed) { + const LogEvent& event, int matcherIndex, + const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + vector<MatchingState>& matcherResults, + vector<shared_ptr<LogEvent>>& matcherTransformations) { + if (matcherResults[matcherIndex] != MatchingState::kNotComputed) { VLOG("Matcher %lld already evaluated ", (long long)mId); return; } if (mAtomIds.find(event.GetTagId()) == mAtomIds.end()) { - matcherResults[mIndex] = MatchingState::kNotMatched; + matcherResults[matcherIndex] = MatchingState::kNotMatched; return; } - bool matched = matchesSimple(mUidMap, mMatcher, event); - matcherResults[mIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched; + auto [matched, transformedEvent] = matchesSimple(mUidMap, mMatcher, event); + matcherResults[matcherIndex] = matched ? MatchingState::kMatched : MatchingState::kNotMatched; VLOG("Stats SimpleAtomMatcher %lld matched? %d", (long long)mId, matched); + + if (matched && transformedEvent != nullptr) { + matcherTransformations[matcherIndex] = std::move(transformedEvent); + } } } // namespace statsd diff --git a/statsd/src/matchers/SimpleAtomMatchingTracker.h b/statsd/src/matchers/SimpleAtomMatchingTracker.h index 70585f9b..641e9d85 100644 --- a/statsd/src/matchers/SimpleAtomMatchingTracker.h +++ b/statsd/src/matchers/SimpleAtomMatchingTracker.h @@ -30,23 +30,24 @@ namespace statsd { class SimpleAtomMatchingTracker : public AtomMatchingTracker { public: - SimpleAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash, + SimpleAtomMatchingTracker(const int64_t id, const uint64_t protoHash, const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap); ~SimpleAtomMatchingTracker(); - optional<InvalidConfigReason> init( - const std::vector<AtomMatcher>& allAtomMatchers, - const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack) override; + MatcherInitResult init(int matcherIndex, const std::vector<AtomMatcher>& allAtomMatchers, + const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, + const std::unordered_map<int64_t, int>& matcherMap, + std::vector<uint8_t>& stack) override; optional<InvalidConfigReason> onConfigUpdated( - const AtomMatcher& matcher, const int index, + const AtomMatcher& matcher, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override; - void onLogEvent(const LogEvent& event, + void onLogEvent(const LogEvent& event, int matcherIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, - std::vector<MatchingState>& matcherResults) override; + std::vector<MatchingState>& matcherResults, + std::vector<std::shared_ptr<LogEvent>>& matcherTransformations) override; private: const SimpleAtomMatcher mMatcher; diff --git a/statsd/src/matchers/matcher_util.cpp b/statsd/src/matchers/matcher_util.cpp index 20450ddd..347e4844 100644 --- a/statsd/src/matchers/matcher_util.cpp +++ b/statsd/src/matchers/matcher_util.cpp @@ -20,12 +20,15 @@ #include <fnmatch.h> +#include "lib/stats_regex.h" #include "matchers/AtomMatchingTracker.h" #include "src/statsd_config.pb.h" #include "stats_util.h" +using std::regex; using std::set; using std::string; +using std::unique_ptr; using std::vector; namespace android { @@ -84,8 +87,8 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera return matched; } -bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue, - const string& str_match) { +static bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue, + const string& str_match) { if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) { int uid = fieldValue.mValue.int_value; auto aidIt = UidMap::sAidToUidMapping.find(str_match); @@ -100,8 +103,8 @@ bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue, return false; } -bool tryMatchWildcardString(const sp<UidMap>& uidMap, const FieldValue& fieldValue, - const string& wildcardPattern) { +static bool tryMatchWildcardString(const sp<UidMap>& uidMap, const FieldValue& fieldValue, + const string& wildcardPattern) { if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) { int uid = fieldValue.mValue.int_value; // TODO(b/236886985): replace aid/uid mapping with efficient bidirectional container @@ -127,17 +130,42 @@ bool tryMatchWildcardString(const sp<UidMap>& uidMap, const FieldValue& fieldVal return false; } -bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, - const vector<FieldValue>& values, int start, int end, int depth) { - if (depth > 2) { - ALOGE("Depth > 3 not supported"); - return false; +static unique_ptr<LogEvent> getTransformedEvent(const FieldValueMatcher& matcher, + const LogEvent& event, int start, int end) { + if (!matcher.has_replace_string()) { + return nullptr; } - if (start >= end) { - return false; + unique_ptr<regex> re = createRegex(matcher.replace_string().regex()); + if (re == nullptr) { + return nullptr; } + const string& replacement = matcher.replace_string().replacement(); + unique_ptr<LogEvent> transformedEvent = nullptr; + for (int i = start; i < end; i++) { + const LogEvent& eventRef = transformedEvent == nullptr ? event : *transformedEvent; + const FieldValue& fieldValue = eventRef.getValues()[i]; + if (fieldValue.mValue.getType() != STRING) { + continue; + } + const string transformedString = + regexReplace(fieldValue.mValue.str_value, *re, replacement); + if (transformedString == fieldValue.mValue.str_value) { + continue; + } + + // String transformation occurred, update the FieldValue in transformedEvent. + if (transformedEvent == nullptr) { + transformedEvent = std::make_unique<LogEvent>(event); + } + (*transformedEvent->getMutableValues())[i].mValue.str_value = transformedString; + } + return transformedEvent; +} + +static pair<int, int> getStartEndAtDepth(int targetField, int start, int end, int depth, + const vector<FieldValue>& values) { // Filter by entry field first int newStart = -1; int newEnd = end; @@ -145,31 +173,45 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, // break when pos is larger than the one we are searching for. for (int i = start; i < end; i++) { int pos = values[i].mField.getPosAtDepth(depth); - if (pos == matcher.field()) { + if (pos == targetField) { if (newStart == -1) { newStart = i; } newEnd = i + 1; - } else if (pos > matcher.field()) { + } else if (pos > targetField) { break; } } + return {newStart, newEnd}; +} + +/* + * Returns pairs of start-end indices in vector<FieldValue> that pariticipate in matching. + * The returned vector is empty if an error was encountered. + * If Position is ANY and value_matcher is matches_tuple, the vector contains a start/end pair + * corresponding for each child FieldValueMatcher in matches_tuple. For all other cases, the + * returned vector is of size 1. + * + * Also updates the depth reference parameter if matcher has Position specified. + */ +static vector<pair<int, int>> computeRanges(const FieldValueMatcher& matcher, + const vector<FieldValue>& values, int start, int end, + int& depth) { // Now we have zoomed in to a new range - start = newStart; - end = newEnd; + std::tie(start, end) = getStartEndAtDepth(matcher.field(), start, end, depth, values); if (start == -1) { // No such field found. - return false; + return {}; } - vector<pair<int, int>> ranges; // the ranges are for matching ANY position + vector<pair<int, int>> ranges; if (matcher.has_position()) { // Repeated fields position is stored as a node in the path. depth++; if (depth > 2) { - return false; + return ranges; } switch (matcher.position()) { case Position::FIRST: { @@ -196,27 +238,42 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, ranges.push_back(std::make_pair(start, end)); break; } + case Position::ALL: + // ALL is only supported for string transformation. If a value_matcher other than + // matches_tuple is present, the matcher is invalid. This is enforced when + // the AtomMatchingTracker is initialized. + + // fallthrough case Position::ANY: { - // ANY means all the children matchers match in any of the sub trees, it's a match - newStart = start; - newEnd = end; - // Here start is guaranteed to be a valid index. - int currentPos = values[start].mField.getPosAtDepth(depth); - // Now find all sub trees ranges. - for (int i = start; i < end; i++) { - int newPos = values[i].mField.getPosAtDepth(depth); - if (newPos != currentPos) { - ranges.push_back(std::make_pair(newStart, i)); - newStart = i; - currentPos = newPos; + // For string transformation, this case is treated the same as Position:ALL. + // Given a matcher on attribution_node[ANY].tag with a matches_tuple containing a + // child FieldValueMatcher with eq_string: "foo" and regex_replace: "[\d]+$" --> "", + // an event with attribution tags: ["bar123", "foo12", "abc230"] will transform to + // have attribution tags ["bar", "foo", "abc"] and will be a successful match. + + // Note that if value_matcher is matches_tuple, there should be no string + // transformation on this matcher. However, child FieldValueMatchers in + // matches_tuple can have string transformations. This is enforced when + // AtomMatchingTracker is initialized. + + if (matcher.value_matcher_case() == FieldValueMatcher::kMatchesTuple) { + // For ANY with matches_tuple, if all the children matchers match in any of the + // sub trees, it's a match. + // Here start is guaranteed to be a valid index. + int currentPos = values[start].mField.getPosAtDepth(depth); + // Now find all sub trees ranges. + for (int i = start; i < end; i++) { + int newPos = values[i].mField.getPosAtDepth(depth); + if (newPos != currentPos) { + ranges.push_back(std::make_pair(start, i)); + start = i; + currentPos = newPos; + } } } - ranges.push_back(std::make_pair(newStart, end)); + ranges.push_back(std::make_pair(start, end)); break; } - case Position::ALL: - ALOGE("Not supported: field matcher with ALL position."); - break; case Position::POSITION_UNKNOWN: break; } @@ -224,23 +281,60 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, // No position ranges.push_back(std::make_pair(start, end)); } - // start and end are still pointing to the matched range. + + return ranges; +} + +static MatchResult matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, + const LogEvent& event, int start, int end, int depth) { + if (depth > 2) { + ALOGE("Depth >= 3 not supported"); + return {false, nullptr}; + } + + if (start >= end) { + return {false, nullptr}; + } + + const vector<pair<int, int>> ranges = + computeRanges(matcher, event.getValues(), start, end, depth); + + if (ranges.empty()) { + // No such field found. + return {false, nullptr}; + } + + // ranges should have exactly one start/end pair at this point unless position is ANY and + // value_matcher is matches_tuple. + std::tie(start, end) = ranges[0]; + + unique_ptr<LogEvent> transformedEvent = getTransformedEvent(matcher, event, start, end); + + const vector<FieldValue>& values = + transformedEvent == nullptr ? event.getValues() : transformedEvent->getValues(); + switch (matcher.value_matcher_case()) { case FieldValueMatcher::kMatchesTuple: { ++depth; // If any range matches all matchers, good. - for (const auto& range : ranges) { + bool matchResult = false; + for (const auto& [rangeStart, rangeEnd] : ranges) { bool matched = true; for (const auto& subMatcher : matcher.matches_tuple().field_value_matcher()) { - if (!matchesSimple(uidMap, subMatcher, values, range.first, range.second, - depth)) { + const LogEvent& eventRef = + transformedEvent == nullptr ? event : *transformedEvent; + auto [hasMatched, newTransformedEvent] = matchesSimple( + uidMap, subMatcher, eventRef, rangeStart, rangeEnd, depth); + if (newTransformedEvent != nullptr) { + transformedEvent = std::move(newTransformedEvent); + } + if (!hasMatched) { matched = false; - break; } } - if (matched) return true; + matchResult = matchResult || matched; } - return false; + return {matchResult, std::move(transformedEvent)}; } // Finally, we get to the point of real value matching. // If the field matcher ends with ANY, then we have [start, end) range > 1. @@ -251,18 +345,18 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, (values[i].mValue.int_value != 0) == matcher.eq_bool()) || (values[i].mValue.getType() == LONG && (values[i].mValue.long_value != 0) == matcher.eq_bool())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kEqString: { for (int i = start; i < end; i++) { if (tryMatchString(uidMap, values[i], matcher.eq_string())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kNeqAnyString: { const auto& str_list = matcher.neq_any_string(); @@ -275,40 +369,40 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, } } if (notEqAll) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kEqAnyString: { const auto& str_list = matcher.eq_any_string(); for (int i = start; i < end; i++) { for (const auto& str : str_list.str_value()) { if (tryMatchString(uidMap, values[i], str)) { - return true; + return {true, std::move(transformedEvent)}; } } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kEqWildcardString: { for (int i = start; i < end; i++) { if (tryMatchWildcardString(uidMap, values[i], matcher.eq_wildcard_string())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kEqAnyWildcardString: { const auto& str_list = matcher.eq_any_wildcard_string(); for (int i = start; i < end; i++) { for (const auto& str : str_list.str_value()) { if (tryMatchWildcardString(uidMap, values[i], str)) { - return true; + return {true, std::move(transformedEvent)}; } } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kNeqAnyWildcardString: { const auto& str_list = matcher.neq_any_wildcard_string(); @@ -321,24 +415,24 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, } } if (notEqAll) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kEqInt: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == INT && (matcher.eq_int() == values[i].mValue.int_value)) { - return true; + return {true, std::move(transformedEvent)}; } // eq_int covers both int and long. if (values[i].mValue.getType() == LONG && (matcher.eq_int() == values[i].mValue.long_value)) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kEqAnyInt: { const auto& int_list = matcher.eq_any_int(); @@ -346,16 +440,16 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, for (const int int_value : int_list.int_value()) { if (values[i].mValue.getType() == INT && (int_value == values[i].mValue.int_value)) { - return true; + return {true, std::move(transformedEvent)}; } // eq_any_int covers both int and long. if (values[i].mValue.getType() == LONG && (int_value == values[i].mValue.long_value)) { - return true; + return {true, std::move(transformedEvent)}; } } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kNeqAnyInt: { const auto& int_list = matcher.neq_any_int(); @@ -375,102 +469,113 @@ bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher, } } if (notEqAll) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kLtInt: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == INT && (values[i].mValue.int_value < matcher.lt_int())) { - return true; + return {true, std::move(transformedEvent)}; } // lt_int covers both int and long. if (values[i].mValue.getType() == LONG && (values[i].mValue.long_value < matcher.lt_int())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kGtInt: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == INT && (values[i].mValue.int_value > matcher.gt_int())) { - return true; + return {true, std::move(transformedEvent)}; } // gt_int covers both int and long. if (values[i].mValue.getType() == LONG && (values[i].mValue.long_value > matcher.gt_int())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kLtFloat: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == FLOAT && (values[i].mValue.float_value < matcher.lt_float())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kGtFloat: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == FLOAT && (values[i].mValue.float_value > matcher.gt_float())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kLteInt: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == INT && (values[i].mValue.int_value <= matcher.lte_int())) { - return true; + return {true, std::move(transformedEvent)}; } // lte_int covers both int and long. if (values[i].mValue.getType() == LONG && (values[i].mValue.long_value <= matcher.lte_int())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } case FieldValueMatcher::ValueMatcherCase::kGteInt: { for (int i = start; i < end; i++) { if (values[i].mValue.getType() == INT && (values[i].mValue.int_value >= matcher.gte_int())) { - return true; + return {true, std::move(transformedEvent)}; } // gte_int covers both int and long. if (values[i].mValue.getType() == LONG && (values[i].mValue.long_value >= matcher.gte_int())) { - return true; + return {true, std::move(transformedEvent)}; } } - return false; + return {false, std::move(transformedEvent)}; } default: - return false; + // This only happens if the matcher has a string transformation and no value_matcher. So + // the default match result is true. If there is no string transformation either then + // this matcher is invalid, which is enforced when the AtomMatchingTracker is + // initialized. + return {true, std::move(transformedEvent)}; } } -bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher, - const LogEvent& event) { +MatchResult matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher, + const LogEvent& event) { if (event.GetTagId() != simpleMatcher.atom_id()) { - return false; + return {false, nullptr}; } + unique_ptr<LogEvent> transformedEvent = nullptr; for (const auto& matcher : simpleMatcher.field_value_matcher()) { - if (!matchesSimple(uidMap, matcher, event.getValues(), 0, event.getValues().size(), 0)) { - return false; + const LogEvent& inputEvent = transformedEvent == nullptr ? event : *transformedEvent; + auto [hasMatched, newTransformedEvent] = + matchesSimple(uidMap, matcher, inputEvent, 0, inputEvent.getValues().size(), 0); + if (newTransformedEvent != nullptr) { + transformedEvent = std::move(newTransformedEvent); + } + if (!hasMatched) { + return {false, std::move(transformedEvent)}; } } - return true; + return {true, std::move(transformedEvent)}; } } // namespace statsd diff --git a/statsd/src/matchers/matcher_util.h b/statsd/src/matchers/matcher_util.h index 597b74f7..5fb7c426 100644 --- a/statsd/src/matchers/matcher_util.h +++ b/statsd/src/matchers/matcher_util.h @@ -33,11 +33,16 @@ enum MatchingState { kMatched = 1, }; +struct MatchResult { + bool matched; + std::unique_ptr<LogEvent> transformedEvent; +}; + bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation, const std::vector<MatchingState>& matcherResults); -bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher, - const LogEvent& wrapper); +MatchResult matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher, + const LogEvent& wrapper); } // namespace statsd } // namespace os diff --git a/statsd/src/metrics/CountMetricProducer.cpp b/statsd/src/metrics/CountMetricProducer.cpp index 9a4d9224..e7a331bb 100644 --- a/statsd/src/metrics/CountMetricProducer.cpp +++ b/statsd/src/metrics/CountMetricProducer.cpp @@ -400,7 +400,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked( // When a new matched event comes in, we check if event falls into the current // bucket. If not, flush the old counter to past buckets and initialize the new bucket. -void CountMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { +void CountMetricProducer::flushIfNeededLocked(const int64_t eventTimeNs) { int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs(); if (eventTimeNs < currentBucketEndTimeNs) { return; @@ -416,7 +416,7 @@ void CountMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { (long long)mCurrentBucketStartTimeNs); } -bool CountMetricProducer::countPassesThreshold(const int64_t& count) { +bool CountMetricProducer::countPassesThreshold(const int64_t count) { if (mUploadThreshold == nullopt) { return true; } @@ -436,8 +436,8 @@ bool CountMetricProducer::countPassesThreshold(const int64_t& count) { } } -void CountMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) { +void CountMetricProducer::flushCurrentBucketLocked(const int64_t eventTimeNs, + const int64_t nextBucketStartTimeNs) { int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs(); CountBucket info; info.mBucketStartNs = mCurrentBucketStartTimeNs; diff --git a/statsd/src/metrics/CountMetricProducer.h b/statsd/src/metrics/CountMetricProducer.h index 3f67a18a..7fa463f3 100644 --- a/statsd/src/metrics/CountMetricProducer.h +++ b/statsd/src/metrics/CountMetricProducer.h @@ -44,9 +44,9 @@ struct CountBucket { class CountMetricProducer : public MetricProducer { public: CountMetricProducer( - const ConfigKey& key, const CountMetric& countMetric, const int conditionIndex, + const ConfigKey& key, const CountMetric& countMetric, int conditionIndex, const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, - const uint64_t protoHash, const int64_t timeBaseNs, const int64_t startTimeNs, + const uint64_t protoHash, int64_t timeBaseNs, int64_t startTimeNs, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {}, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap = {}, @@ -81,10 +81,10 @@ private: void clearPastBucketsLocked(const int64_t dumpTimeNs) override; // Internal interface to handle condition change. - void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override; + void onConditionChangedLocked(const bool conditionMet, int64_t eventTime) override; // Internal interface to handle sliced condition change. - void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override; + void onSlicedConditionMayChangeLocked(bool overallCondition, int64_t eventTime) override; // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; @@ -94,15 +94,14 @@ private: void dropDataLocked(const int64_t dropTimeNs) override; // Util function to flush the old packet. - void flushIfNeededLocked(const int64_t& newEventTime) override; + void flushIfNeededLocked(int64_t newEventTime) override; - void flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) override; + void flushCurrentBucketLocked(int64_t eventTimeNs, int64_t nextBucketStartTimeNs) override; void onActiveStateChangedLocked(const int64_t eventTimeNs, const bool isActive) override; optional<InvalidConfigReason> onConfigUpdatedLocked( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -130,7 +129,7 @@ private: bool hitGuardRailLocked(const MetricDimensionKey& newKey); - bool countPassesThreshold(const int64_t& count); + bool countPassesThreshold(int64_t count); // Tracks if the dimension guardrail has been hit in the current report. bool mDimensionGuardrailHit; diff --git a/statsd/src/metrics/DurationMetricProducer.cpp b/statsd/src/metrics/DurationMetricProducer.cpp index a7b886dd..9973a9e2 100644 --- a/statsd/src/metrics/DurationMetricProducer.cpp +++ b/statsd/src/metrics/DurationMetricProducer.cpp @@ -603,7 +603,7 @@ void DurationMetricProducer::onDumpReportLocked( } } -void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { +void DurationMetricProducer::flushIfNeededLocked(const int64_t eventTimeNs) { int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs(); if (currentBucketEndTimeNs > eventTimeNs) { @@ -617,8 +617,8 @@ void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { mCurrentBucketNum += numBucketsForward; } -void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) { +void DurationMetricProducer::flushCurrentBucketLocked(const int64_t eventTimeNs, + const int64_t nextBucketStartTimeNs) { const auto [globalConditionTrueNs, globalConditionCorrectionNs] = mConditionTimer.newBucketStart(eventTimeNs, nextBucketStartTimeNs); diff --git a/statsd/src/metrics/DurationMetricProducer.h b/statsd/src/metrics/DurationMetricProducer.h index a3662921..2f3d8597 100644 --- a/statsd/src/metrics/DurationMetricProducer.h +++ b/statsd/src/metrics/DurationMetricProducer.h @@ -39,12 +39,11 @@ namespace statsd { class DurationMetricProducer : public MetricProducer { public: DurationMetricProducer( - const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex, - const vector<ConditionState>& initialConditionCache, const int whatIndex, - const int startIndex, const int stopIndex, const int stopAllIndex, const bool nesting, + const ConfigKey& key, const DurationMetric& durationMetric, int conditionIndex, + const vector<ConditionState>& initialConditionCache, int whatIndex, + const int startIndex, int stopIndex, int stopAllIndex, const bool nesting, const sp<ConditionWizard>& wizard, const uint64_t protoHash, - const FieldMatcher& internalDimensions, const int64_t timeBaseNs, - const int64_t startTimeNs, + const FieldMatcher& internalDimensions, int64_t timeBaseNs, const int64_t startTimeNs, const unordered_map<int, shared_ptr<Activation>>& eventActivationMap = {}, const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap = {}, const vector<int>& slicedStateAtoms = {}, @@ -57,7 +56,7 @@ public: const UpdateStatus& updateStatus, const int64_t updateTimeNs) override; - void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker, const int64_t updateTimeNs) override; + void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker, int64_t updateTimeNs) override; void onStateChanged(const int64_t eventTimeNs, const int32_t atomId, const HashableDimensionKey& primaryKey, const FieldValue& oldState, @@ -77,13 +76,13 @@ protected: private: // Initializes true dimensions of the 'what' predicate. Only to be called during initialization. - void initTrueDimensions(const int whatIndex, const int64_t startTimeNs); + void initTrueDimensions(const int whatIndex, int64_t startTimeNs); void handleMatchedLogEventValuesLocked(const size_t matcherIndex, const std::vector<FieldValue>& values, const int64_t eventTimeNs); void handleStartEvent(const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys, - bool condition, const int64_t eventTimeNs, + bool condition, int64_t eventTimeNs, const vector<FieldValue>& eventValues); void onDumpReportLocked(const int64_t dumpTimeNs, @@ -96,13 +95,13 @@ private: void clearPastBucketsLocked(const int64_t dumpTimeNs) override; // Internal interface to handle condition change. - void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override; + void onConditionChangedLocked(const bool conditionMet, int64_t eventTime) override; // Internal interface to handle active state change. void onActiveStateChangedLocked(const int64_t eventTimeNs, const bool isActive) override; // Internal interface to handle sliced condition change. - void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override; + void onSlicedConditionMayChangeLocked(bool overallCondition, int64_t eventTime) override; void onSlicedConditionMayChangeInternalLocked(const int64_t eventTimeNs); @@ -116,13 +115,12 @@ private: void dropDataLocked(const int64_t dropTimeNs) override; // Util function to flush the old packet. - void flushIfNeededLocked(const int64_t& eventTime); + void flushIfNeededLocked(int64_t eventTime); - void flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) override; + void flushCurrentBucketLocked(int64_t eventTimeNs, int64_t nextBucketStartTimeNs) override; optional<InvalidConfigReason> onConfigUpdatedLocked( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -138,7 +136,7 @@ private: std::vector<int>& metricsWithActivation) override; void addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker, - const UpdateStatus& updateStatus, const int64_t updateTimeNs); + const UpdateStatus& updateStatus, int64_t updateTimeNs); const DurationMetric_AggregationType mAggregationType; diff --git a/statsd/src/metrics/EventMetricProducer.h b/statsd/src/metrics/EventMetricProducer.h index f27f24bf..6e026597 100644 --- a/statsd/src/metrics/EventMetricProducer.h +++ b/statsd/src/metrics/EventMetricProducer.h @@ -35,9 +35,9 @@ namespace statsd { class EventMetricProducer : public MetricProducer { public: EventMetricProducer( - const ConfigKey& key, const EventMetric& eventMetric, const int conditionIndex, + const ConfigKey& key, const EventMetric& eventMetric, int conditionIndex, const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, - const uint64_t protoHash, const int64_t startTimeNs, + const uint64_t protoHash, int64_t startTimeNs, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {}, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap = {}, @@ -68,13 +68,13 @@ private: void clearPastBucketsLocked(const int64_t dumpTimeNs) override; // Internal interface to handle condition change. - void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override; + void onConditionChangedLocked(const bool conditionMet, int64_t eventTime) override; // Internal interface to handle sliced condition change. - void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override; + void onSlicedConditionMayChangeLocked(bool overallCondition, int64_t eventTime) override; optional<InvalidConfigReason> onConfigUpdatedLocked( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, diff --git a/statsd/src/metrics/GaugeMetricProducer.cpp b/statsd/src/metrics/GaugeMetricProducer.cpp index 66d8f45e..10a02d66 100644 --- a/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/statsd/src/metrics/GaugeMetricProducer.cpp @@ -100,7 +100,8 @@ GaugeMetricProducer::GaugeMetricProducer( mDimensionSoftLimit(dimensionSoftLimit), mDimensionHardLimit(dimensionHardLimit), mGaugeAtomsPerDimensionLimit(metric.max_num_gauge_atoms_per_bucket()), - mDimensionGuardrailHit(false) { + mDimensionGuardrailHit(false), + mSamplingPercentage(metric.sampling_percentage()) { mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>(); mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>(); int64_t bucketSizeMills = 0; @@ -409,9 +410,10 @@ void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) { return; } for (const auto& data : allData) { - if (mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex) == - MatchingState::kMatched) { - LogEvent localCopy = *data; + const auto [matchResult, transformedEvent] = + mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex); + if (matchResult == MatchingState::kMatched) { + LogEvent localCopy = transformedEvent == nullptr ? *data : *transformedEvent; localCopy.setElapsedTimestampNs(timestampNs); onMatchedLogEventLocked(mWhatMatcherIndex, localCopy); } @@ -501,9 +503,11 @@ void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven return; } for (const auto& data : allData) { - if (mEventMatcherWizard->matchLogEvent( - *data, mWhatMatcherIndex) == MatchingState::kMatched) { - onMatchedLogEventLocked(mWhatMatcherIndex, *data); + const auto [matchResult, transformedEvent] = + mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex); + if (matchResult == MatchingState::kMatched) { + onMatchedLogEventLocked(mWhatMatcherIndex, + transformedEvent == nullptr ? *data : *transformedEvent); } } } @@ -539,6 +543,12 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked( if (condition == false) { return; } + + if (mPullTagId == -1 && mSamplingPercentage < 100 && + !shouldKeepRandomSample(mSamplingPercentage)) { + return; + } + int64_t eventTimeNs = event.GetElapsedTimestampNs(); if (eventTimeNs < mCurrentBucketStartTimeNs) { VLOG("Gauge Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs, @@ -617,7 +627,7 @@ void GaugeMetricProducer::dropDataLocked(const int64_t dropTimeNs) { // bucket. // if data is pushed, onMatchedLogEvent will only be called through onConditionChanged() inside // the GaugeMetricProducer while holding the lock. -void GaugeMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { +void GaugeMetricProducer::flushIfNeededLocked(const int64_t eventTimeNs) { int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs(); if (eventTimeNs < currentBucketEndTimeNs) { @@ -636,8 +646,8 @@ void GaugeMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { (long long)mCurrentBucketStartTimeNs); } -void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) { +void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t eventTimeNs, + const int64_t nextBucketStartTimeNs) { int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs(); int64_t bucketEndTime = eventTimeNs < fullBucketEndTimeNs ? eventTimeNs : fullBucketEndTimeNs; diff --git a/statsd/src/metrics/GaugeMetricProducer.h b/statsd/src/metrics/GaugeMetricProducer.h index 51df9e65..7c737a41 100644 --- a/statsd/src/metrics/GaugeMetricProducer.h +++ b/statsd/src/metrics/GaugeMetricProducer.h @@ -34,7 +34,7 @@ namespace os { namespace statsd { struct GaugeAtom { - GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs) + GaugeAtom(const std::shared_ptr<vector<FieldValue>>& fields, int64_t elapsedTimeNs) : mFields(fields), mElapsedTimestampNs(elapsedTimeNs) { } std::shared_ptr<vector<FieldValue>> mFields; @@ -60,13 +60,12 @@ typedef std::unordered_map<MetricDimensionKey, std::vector<GaugeAtom>> class GaugeMetricProducer : public MetricProducer, public virtual PullDataReceiver { public: GaugeMetricProducer( - const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex, + const ConfigKey& key, const GaugeMetric& gaugeMetric, int conditionIndex, const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash, const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard, - const int pullTagId, const int triggerAtomId, const int atomId, - const int64_t timeBaseNs, const int64_t startTimeNs, - const sp<StatsPullerManager>& pullerManager, + const int pullTagId, int triggerAtomId, int atomId, const int64_t timeBaseNs, + int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {}, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap = {}, @@ -86,7 +85,7 @@ public: }; // GaugeMetric needs to immediately trigger another pull when we create the partial bucket. - void notifyAppUpgradeInternalLocked(const int64_t eventTimeNs) override { + void notifyAppUpgradeInternalLocked(int64_t eventTimeNs) override { flushLocked(eventTimeNs); if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE && mIsActive) { pullAndMatchEventsLocked(eventTimeNs); @@ -94,7 +93,7 @@ public: }; // GaugeMetric needs to immediately trigger another pull when we create the partial bucket. - void onStatsdInitCompleted(const int64_t& eventTimeNs) override { + void onStatsdInitCompleted(int64_t eventTimeNs) override { std::lock_guard<std::mutex> lock(mMutex); flushLocked(eventTimeNs); @@ -123,13 +122,13 @@ private: void clearPastBucketsLocked(const int64_t dumpTimeNs) override; // Internal interface to handle condition change. - void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override; + void onConditionChangedLocked(const bool conditionMet, int64_t eventTime) override; // Internal interface to handle active state change. void onActiveStateChangedLocked(const int64_t eventTimeNs, const bool isActive) override; // Internal interface to handle sliced condition change. - void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override; + void onSlicedConditionMayChangeLocked(bool overallCondition, int64_t eventTime) override; // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; @@ -139,10 +138,9 @@ private: void dropDataLocked(const int64_t dropTimeNs) override; // Util function to flush the old packet. - void flushIfNeededLocked(const int64_t& eventTime) override; + void flushIfNeededLocked(int64_t eventTime) override; - void flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) override; + void flushCurrentBucketLocked(int64_t eventTimeNs, int64_t nextBucketStartTimeNs) override; void prepareFirstBucketLocked() override; @@ -150,7 +148,7 @@ private: void pullAndMatchEventsLocked(const int64_t timestampNs); optional<InvalidConfigReason> onConfigUpdatedLocked( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -227,6 +225,8 @@ private: // Tracks if the dimension guardrail has been hit in the current report. bool mDimensionGuardrailHit; + const int mSamplingPercentage; + FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition); FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition); FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition); diff --git a/statsd/src/metrics/MetricProducer.cpp b/statsd/src/metrics/MetricProducer.cpp index bd697982..55c9adfc 100644 --- a/statsd/src/metrics/MetricProducer.cpp +++ b/statsd/src/metrics/MetricProducer.cpp @@ -45,9 +45,9 @@ const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS = 2; const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3; MetricProducer::MetricProducer( - const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs, - const int conditionIndex, const vector<ConditionState>& initialConditionCache, - const sp<ConditionWizard>& wizard, const uint64_t protoHash, + int64_t metricId, const ConfigKey& key, const int64_t timeBaseNs, const int conditionIndex, + const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, + const uint64_t protoHash, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap, @@ -243,7 +243,7 @@ void MetricProducer::cancelEventActivationLocked(int deactivationTrackerIndex) { if (it == mEventDeactivationMap.end()) { return; } - for (auto activationToCancelIt : it->second) { + for (auto& activationToCancelIt : it->second) { activationToCancelIt->state = ActivationState::kNotActive; } } @@ -319,7 +319,7 @@ void MetricProducer::writeActiveMetricToProtoOutputStream( } } -void MetricProducer::queryStateValue(const int32_t atomId, const HashableDimensionKey& queryKey, +void MetricProducer::queryStateValue(int32_t atomId, const HashableDimensionKey& queryKey, FieldValue* value) { if (!StateManager::getInstance().getStateValue(atomId, queryKey, value)) { value->mValue = Value(StateTracker::kStateUnknown); @@ -329,7 +329,7 @@ void MetricProducer::queryStateValue(const int32_t atomId, const HashableDimensi } } -void MetricProducer::mapStateValue(const int32_t atomId, FieldValue* value) { +void MetricProducer::mapStateValue(int32_t atomId, FieldValue* value) { // check if there is a state map for this atom auto atomIt = mStateGroupMap.find(atomId); if (atomIt == mStateGroupMap.end()) { diff --git a/statsd/src/metrics/MetricProducer.h b/statsd/src/metrics/MetricProducer.h index 24e761af..133aa323 100644 --- a/statsd/src/metrics/MetricProducer.h +++ b/statsd/src/metrics/MetricProducer.h @@ -73,11 +73,12 @@ enum MetricType { }; struct Activation { - Activation(const ActivationType& activationType, const int64_t ttlNs) + Activation(const ActivationType& activationType, int64_t ttlNs) : ttl_ns(ttlNs), start_ns(0), state(ActivationState::kNotActive), - activationType(activationType) {} + activationType(activationType) { + } const int64_t ttl_ns; int64_t start_ns; @@ -127,7 +128,7 @@ optional<bool> getAppUpgradeBucketSplit(const T& metric) { // be a no-op. class MetricProducer : public virtual RefBase, public virtual StateListener { public: - MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs, + MetricProducer(int64_t metricId, const ConfigKey& key, int64_t timeBaseNs, const int conditionIndex, const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, const uint64_t protoHash, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap, @@ -149,7 +150,7 @@ public: // This function also updates several maps used by metricsManager. // This function clears all anomaly trackers. All anomaly trackers need to be added again. optional<InvalidConfigReason> onConfigUpdated( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -175,7 +176,7 @@ public: /** * Force a partial bucket split on app upgrade */ - void notifyAppUpgrade(const int64_t& eventTimeNs) { + void notifyAppUpgrade(int64_t eventTimeNs) { std::lock_guard<std::mutex> lock(mMutex); const bool splitBucket = mSplitBucketForAppUpgrade ? mSplitBucketForAppUpgrade.value() : false; @@ -185,7 +186,7 @@ public: notifyAppUpgradeInternalLocked(eventTimeNs); }; - void notifyAppRemoved(const int64_t& eventTimeNs) { + void notifyAppRemoved(int64_t eventTimeNs) { // Force buckets to split on removal also. notifyAppUpgrade(eventTimeNs); }; @@ -193,7 +194,7 @@ public: /** * Force a partial bucket split on boot complete. */ - virtual void onStatsdInitCompleted(const int64_t& eventTimeNs) { + virtual void onStatsdInitCompleted(int64_t eventTimeNs) { std::lock_guard<std::mutex> lock(mMutex); flushLocked(eventTimeNs); } @@ -203,12 +204,12 @@ public: onMatchedLogEventLocked(matcherIndex, event); } - void onConditionChanged(const bool condition, const int64_t eventTime) { + void onConditionChanged(const bool condition, int64_t eventTime) { std::lock_guard<std::mutex> lock(mMutex); onConditionChangedLocked(condition, eventTime); } - void onSlicedConditionMayChange(bool overallCondition, const int64_t eventTime) { + void onSlicedConditionMayChange(bool overallCondition, int64_t eventTime) { std::lock_guard<std::mutex> lock(mMutex); onSlicedConditionMayChangeLocked(overallCondition, eventTime); } @@ -236,7 +237,7 @@ public: } virtual optional<InvalidConfigReason> onConfigUpdatedLocked( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -307,7 +308,7 @@ public: void writeActiveMetricToProtoOutputStream( int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto); - virtual void enforceRestrictedDataTtl(sqlite3* db, const int64_t wallClockNs){}; + virtual void enforceRestrictedDataTtl(sqlite3* db, int64_t wallClockNs){}; virtual bool writeMetricMetadataToProto(metadata::MetricMetadata* metricMetadata) { return false; @@ -364,7 +365,7 @@ public: } /* Adds an AnomalyTracker that has already been created */ - virtual void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker, const int64_t updateTimeNs) { + virtual void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker, int64_t updateTimeNs) { std::lock_guard<std::mutex> lock(mMutex); mAnomalyTrackers.push_back(anomalyTracker); } @@ -379,7 +380,7 @@ protected: /** * Flushes the current bucket if the eventTime is after the current bucket's end time. */ - virtual void flushIfNeededLocked(const int64_t& eventTime){}; + virtual void flushIfNeededLocked(int64_t eventTime){}; /** * For metrics that aggregate (ie, every metric producer except for EventMetricProducer), @@ -391,13 +392,12 @@ protected: * flushIfNeededLocked or flushLocked or the app upgrade handler; the caller MUST update the * bucket timestamp and bucket number as needed. */ - virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) {}; + virtual void flushCurrentBucketLocked(int64_t eventTimeNs, int64_t nextBucketStartTimeNs){}; /** * Flushes all the data including the current partial bucket. */ - void flushLocked(const int64_t& eventTimeNs) { + void flushLocked(int64_t eventTimeNs) { flushIfNeededLocked(eventTimeNs); flushCurrentBucketLocked(eventTimeNs, eventTimeNs); }; @@ -428,7 +428,7 @@ protected: // Consume the parsed stats log entry that already matched the "what" of the metric. virtual void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event); - virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0; + virtual void onConditionChangedLocked(const bool condition, int64_t eventTime) = 0; virtual void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) = 0; virtual void onDumpReportLocked(const int64_t dumpTimeNs, @@ -470,13 +470,12 @@ protected: // Query StateManager for original state value using the queryKey. // The field and value are output. - void queryStateValue(const int32_t atomId, const HashableDimensionKey& queryKey, - FieldValue* value); + void queryStateValue(int32_t atomId, const HashableDimensionKey& queryKey, FieldValue* value); // If a state map exists for the given atom, replace the original state // value with the group id mapped to the value. // If no state map exists, keep the original state value. - void mapStateValue(const int32_t atomId, FieldValue* value); + void mapStateValue(int32_t atomId, FieldValue* value); // Returns a HashableDimensionKey with unknown state value for each state // atom. diff --git a/statsd/src/metrics/MetricsManager.cpp b/statsd/src/metrics/MetricsManager.cpp index 03bed144..8a822d72 100644 --- a/statsd/src/metrics/MetricsManager.cpp +++ b/statsd/src/metrics/MetricsManager.cpp @@ -44,6 +44,7 @@ using android::util::ProtoOutputStream; using std::set; using std::string; +using std::unique_ptr; using std::vector; namespace android { @@ -364,7 +365,7 @@ bool MetricsManager::isConfigValid() const { return !mInvalidConfigReason.has_value(); } -void MetricsManager::notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid, +void MetricsManager::notifyAppUpgrade(const int64_t eventTimeNs, const string& apk, const int uid, const int64_t version) { // Inform all metric producers. for (const auto& it : mAllMetricProducers) { @@ -385,8 +386,7 @@ void MetricsManager::notifyAppUpgrade(const int64_t& eventTimeNs, const string& } } -void MetricsManager::notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, - const int uid) { +void MetricsManager::notifyAppRemoved(const int64_t eventTimeNs, const string& apk, const int uid) { // Inform all metric producers. for (const auto& it : mAllMetricProducers) { it->notifyAppRemoved(eventTimeNs); @@ -406,7 +406,7 @@ void MetricsManager::notifyAppRemoved(const int64_t& eventTimeNs, const string& } } -void MetricsManager::onUidMapReceived(const int64_t& eventTimeNs) { +void MetricsManager::onUidMapReceived(const int64_t eventTimeNs) { // Purposefully don't inform metric producers on a new snapshot // because we don't need to flush partial buckets. // This occurs if a new user is added/removed or statsd crashes. @@ -418,7 +418,7 @@ void MetricsManager::onUidMapReceived(const int64_t& eventTimeNs) { initAllowedLogSources(); } -void MetricsManager::onStatsdInitCompleted(const int64_t& eventTimeNs) { +void MetricsManager::onStatsdInitCompleted(const int64_t eventTimeNs) { // Inform all metric producers. for (const auto& it : mAllMetricProducers) { it->onStatsdInitCompleted(eventTimeNs); @@ -616,10 +616,12 @@ void MetricsManager::onLogEvent(const LogEvent& event) { vector<MatchingState> matcherCache(mAllAtomMatchingTrackers.size(), MatchingState::kNotComputed); + vector<shared_ptr<LogEvent>> matcherTransformations(matcherCache.size(), nullptr); for (const auto& matcherIndex : matchersIt->second) { - mAllAtomMatchingTrackers[matcherIndex]->onLogEvent(event, mAllAtomMatchingTrackers, - matcherCache); + mAllAtomMatchingTrackers[matcherIndex]->onLogEvent(event, matcherIndex, + mAllAtomMatchingTrackers, matcherCache, + matcherTransformations); } // Set of metrics that received an activation cancellation. @@ -660,13 +662,16 @@ void MetricsManager::onLogEvent(const LogEvent& event) { mIsActive = isActive; // A bitmap to see which ConditionTracker needs to be re-evaluated. - vector<bool> conditionToBeEvaluated(mAllConditionTrackers.size(), false); + vector<uint8_t> conditionToBeEvaluated(mAllConditionTrackers.size(), false); + vector<shared_ptr<LogEvent>> conditionToTransformedLogEvents(mAllConditionTrackers.size(), + nullptr); - for (const auto& pair : mTrackerToConditionMap) { - if (matcherCache[pair.first] == MatchingState::kMatched) { - const auto& conditionList = pair.second; + for (const auto& [matcherIndex, conditionList] : mTrackerToConditionMap) { + if (matcherCache[matcherIndex] == MatchingState::kMatched) { for (const int conditionIndex : conditionList) { conditionToBeEvaluated[conditionIndex] = true; + conditionToTransformedLogEvents[conditionIndex] = + matcherTransformations[matcherIndex]; } } } @@ -674,36 +679,40 @@ void MetricsManager::onLogEvent(const LogEvent& event) { vector<ConditionState> conditionCache(mAllConditionTrackers.size(), ConditionState::kNotEvaluated); // A bitmap to track if a condition has changed value. - vector<bool> changedCache(mAllConditionTrackers.size(), false); + vector<uint8_t> changedCache(mAllConditionTrackers.size(), false); for (size_t i = 0; i < mAllConditionTrackers.size(); i++) { - if (conditionToBeEvaluated[i] == false) { + if (!conditionToBeEvaluated[i]) { continue; } sp<ConditionTracker>& condition = mAllConditionTrackers[i]; - condition->evaluateCondition(event, matcherCache, mAllConditionTrackers, conditionCache, - changedCache); + const LogEvent& conditionEvent = conditionToTransformedLogEvents[i] == nullptr + ? event + : *conditionToTransformedLogEvents[i]; + condition->evaluateCondition(conditionEvent, matcherCache, mAllConditionTrackers, + conditionCache, changedCache); } for (size_t i = 0; i < mAllConditionTrackers.size(); i++) { - if (changedCache[i] == false) { + if (!changedCache[i]) { continue; } - auto pair = mConditionToMetricMap.find(i); - if (pair != mConditionToMetricMap.end()) { - auto& metricList = pair->second; - for (auto metricIndex : metricList) { - // Metric cares about non sliced condition, and it's changed. - // Push the new condition to it directly. - if (!mAllMetricProducers[metricIndex]->isConditionSliced()) { - mAllMetricProducers[metricIndex]->onConditionChanged(conditionCache[i], - eventTimeNs); - // Metric cares about sliced conditions, and it may have changed. Send - // notification, and the metric can query the sliced conditions that are - // interesting to it. - } else { - mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(conditionCache[i], - eventTimeNs); - } + auto it = mConditionToMetricMap.find(i); + if (it == mConditionToMetricMap.end()) { + continue; + } + auto& metricList = it->second; + for (auto metricIndex : metricList) { + // Metric cares about non sliced condition, and it's changed. + // Push the new condition to it directly. + if (!mAllMetricProducers[metricIndex]->isConditionSliced()) { + mAllMetricProducers[metricIndex]->onConditionChanged(conditionCache[i], + eventTimeNs); + // Metric cares about sliced conditions, and it may have changed. Send + // notification, and the metric can query the sliced conditions that are + // interesting to it. + } else { + mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(conditionCache[i], + eventTimeNs); } } } @@ -712,20 +721,23 @@ void MetricsManager::onLogEvent(const LogEvent& event) { if (matcherCache[i] == MatchingState::kMatched) { StatsdStats::getInstance().noteMatcherMatched(mConfigKey, mAllAtomMatchingTrackers[i]->getId()); - auto pair = mTrackerToMetricMap.find(i); - if (pair != mTrackerToMetricMap.end()) { - auto& metricList = pair->second; - for (const int metricIndex : metricList) { - // pushed metrics are never scheduled pulls - mAllMetricProducers[metricIndex]->onMatchedLogEvent(i, event); - } + auto it = mTrackerToMetricMap.find(i); + if (it == mTrackerToMetricMap.end()) { + continue; + } + auto& metricList = it->second; + const LogEvent& metricEvent = + matcherTransformations[i] == nullptr ? event : *matcherTransformations[i]; + for (const int metricIndex : metricList) { + // pushed metrics are never scheduled pulls + mAllMetricProducers[metricIndex]->onMatchedLogEvent(i, metricEvent); } } } } void MetricsManager::onAnomalyAlarmFired( - const int64_t& timestampNs, + const int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet) { for (const auto& itr : mAllAnomalyTrackers) { itr->informAlarmsFired(timestampNs, alarmSet); @@ -733,7 +745,7 @@ void MetricsManager::onAnomalyAlarmFired( } void MetricsManager::onPeriodicAlarmFired( - const int64_t& timestampNs, + const int64_t timestampNs, unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet) { for (const auto& itr : mAllPeriodicAlarmTrackers) { itr->informAlarmsFired(timestampNs, alarmSet); diff --git a/statsd/src/metrics/MetricsManager.h b/statsd/src/metrics/MetricsManager.h index 4674a85e..4721075b 100644 --- a/statsd/src/metrics/MetricsManager.h +++ b/statsd/src/metrics/MetricsManager.h @@ -39,7 +39,7 @@ namespace statsd { // A MetricsManager is responsible for managing metrics from one single config source. class MetricsManager : public virtual RefBase, public virtual PullUidProvider { public: - MetricsManager(const ConfigKey& configKey, const StatsdConfig& config, const int64_t timeBaseNs, + MetricsManager(const ConfigKey& configKey, const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs, const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor, @@ -47,8 +47,8 @@ public: virtual ~MetricsManager(); - bool updateConfig(const StatsdConfig& config, const int64_t timeBaseNs, - const int64_t currentTimeNs, const sp<AlarmMonitor>& anomalyAlarmMonitor, + bool updateConfig(const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs, + const sp<AlarmMonitor>& anomalyAlarmMonitor, const sp<AlarmMonitor>& periodicAlarmMonitor); // Return whether the configuration is valid. @@ -61,21 +61,20 @@ public: virtual void onLogEvent(const LogEvent& event); void onAnomalyAlarmFired( - const int64_t& timestampNs, - unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet); + int64_t timestampNs, + unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet); void onPeriodicAlarmFired( - const int64_t& timestampNs, - unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet); + int64_t timestampNs, + unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet); - void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid, - const int64_t version); + void notifyAppUpgrade(int64_t eventTimeNs, const string& apk, int uid, int64_t version); - void notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, const int uid); + void notifyAppRemoved(int64_t eventTimeNs, const string& apk, int uid); - void onUidMapReceived(const int64_t& eventTimeNs); + void onUidMapReceived(int64_t eventTimeNs); - void onStatsdInitCompleted(const int64_t& elapsedTimeNs); + void onStatsdInitCompleted(int64_t elapsedTimeNs); void init(); @@ -133,7 +132,7 @@ public: virtual void dropData(const int64_t dropTimeNs); - virtual void onDumpReport(const int64_t dumpTimeNs, const int64_t wallClockNs, + virtual void onDumpReport(const int64_t dumpTimeNs, int64_t wallClockNs, const bool include_current_partial_bucket, const bool erase_data, const DumpLatency dumpLatency, std::set<string>* str_set, android::util::ProtoOutputStream* protoOutput); @@ -176,7 +175,7 @@ public: void enforceRestrictedDataTtls(const int64_t wallClockNs); - bool validateRestrictedMetricsDelegate(const int32_t callingUid); + bool validateRestrictedMetricsDelegate(int32_t callingUid); virtual void flushRestrictedData(); diff --git a/statsd/src/metrics/NumericValueMetricProducer.cpp b/statsd/src/metrics/NumericValueMetricProducer.cpp index bc172090..88e09756 100644 --- a/statsd/src/metrics/NumericValueMetricProducer.cpp +++ b/statsd/src/metrics/NumericValueMetricProducer.cpp @@ -267,15 +267,17 @@ void NumericValueMetricProducer::accumulateEvents(const vector<shared_ptr<LogEve // before calculating the diff between sums of consecutive pulls. std::unordered_map<HashableDimensionKey, pair<LogEvent, vector<int>>> aggregateEvents; for (const auto& data : allData) { - if (mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex) != - MatchingState::kMatched) { + const auto [matchResult, transformedEvent] = + mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex); + if (matchResult != MatchingState::kMatched) { continue; } // Get dimensions_in_what key and value indices. HashableDimensionKey dimensionsInWhat; vector<int> valueIndices(mFieldMatchers.size(), -1); - if (!filterValues(mDimensionsInWhat, mFieldMatchers, data->getValues(), + const LogEvent& eventRef = transformedEvent == nullptr ? *data : *transformedEvent; + if (!filterValues(mDimensionsInWhat, mFieldMatchers, eventRef.getValues(), dimensionsInWhat, valueIndices)) { StatsdStats::getInstance().noteBadValueType(mMetricId); } @@ -285,9 +287,9 @@ void NumericValueMetricProducer::accumulateEvents(const vector<shared_ptr<LogEve if (it == aggregateEvents.end()) { aggregateEvents.emplace(std::piecewise_construct, std::forward_as_tuple(dimensionsInWhat), - std::forward_as_tuple(*data, valueIndices)); + std::forward_as_tuple(eventRef, valueIndices)); } else { - combineValueFields(it->second, *data, valueIndices); + combineValueFields(it->second, eventRef, valueIndices); } } @@ -297,9 +299,10 @@ void NumericValueMetricProducer::accumulateEvents(const vector<shared_ptr<LogEve } } else { for (const auto& data : allData) { - if (mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex) == - MatchingState::kMatched) { - LogEvent localCopy = *data; + const auto [matchResult, transformedEvent] = + mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex); + if (matchResult == MatchingState::kMatched) { + LogEvent localCopy = transformedEvent == nullptr ? *data : *transformedEvent; localCopy.setElapsedTimestampNs(eventElapsedTimeNs); onMatchedLogEventLocked(mWhatMatcherIndex, localCopy); } diff --git a/statsd/src/metrics/NumericValueMetricProducer.h b/statsd/src/metrics/NumericValueMetricProducer.h index 52eab1a5..775fc1af 100644 --- a/statsd/src/metrics/NumericValueMetricProducer.h +++ b/statsd/src/metrics/NumericValueMetricProducer.h @@ -118,7 +118,7 @@ private: bool hitFullBucketGuardRailLocked(const MetricDimensionKey& newKey); inline bool canSkipLogEventLocked( - const MetricDimensionKey& eventKey, const bool condition, const int64_t eventTimeNs, + const MetricDimensionKey& eventKey, const bool condition, int64_t eventTimeNs, const map<int, HashableDimensionKey>& statePrimaryKeys) const override { // For pushed metrics, can only skip if condition is false. // For pulled metrics, can only skip if metric is not diffed and condition is false or diff --git a/statsd/src/metrics/RestrictedEventMetricProducer.h b/statsd/src/metrics/RestrictedEventMetricProducer.h index 74b0b803..1f68387e 100644 --- a/statsd/src/metrics/RestrictedEventMetricProducer.h +++ b/statsd/src/metrics/RestrictedEventMetricProducer.h @@ -15,7 +15,7 @@ public: RestrictedEventMetricProducer( const ConfigKey& key, const EventMetric& eventMetric, const int conditionIndex, const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard, - const uint64_t protoHash, const int64_t startTimeNs, + const uint64_t protoHash, int64_t startTimeNs, const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {}, const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>& eventDeactivationMap = {}, @@ -24,7 +24,7 @@ public: void onMetricRemove() override; - void enforceRestrictedDataTtl(sqlite3* db, const int64_t wallClockNs); + void enforceRestrictedDataTtl(sqlite3* db, int64_t wallClockNs); void flushRestrictedData() override; diff --git a/statsd/src/metrics/ValueMetricProducer.cpp b/statsd/src/metrics/ValueMetricProducer.cpp index c61e1233..732cccc5 100644 --- a/statsd/src/metrics/ValueMetricProducer.cpp +++ b/statsd/src/metrics/ValueMetricProducer.cpp @@ -72,7 +72,7 @@ const int FIELD_ID_SLICE_BY_STATE = 6; template <typename AggregatedValue, typename DimExtras> ValueMetricProducer<AggregatedValue, DimExtras>::ValueMetricProducer( - const int64_t& metricId, const ConfigKey& key, const uint64_t protoHash, + const int64_t metricId, const ConfigKey& key, const uint64_t protoHash, const PullOptions& pullOptions, const BucketOptions& bucketOptions, const WhatOptions& whatOptions, const ConditionOptions& conditionOptions, const StateOptions& stateOptions, const ActivationOptions& activationOptions, @@ -154,7 +154,7 @@ ValueMetricProducer<AggregatedValue, DimExtras>::~ValueMetricProducer() { template <typename AggregatedValue, typename DimExtras> void ValueMetricProducer<AggregatedValue, DimExtras>::onStatsdInitCompleted( - const int64_t& eventTimeNs) { + const int64_t eventTimeNs) { lock_guard<mutex> lock(mMutex); if (isPulled() && mCondition == ConditionState::kTrue && mIsActive) { @@ -717,7 +717,7 @@ void ValueMetricProducer<AggregatedValue, DimExtras>::onMatchedLogEventInternalL // if mCondition and mIsActive are true! template <typename AggregatedValue, typename DimExtras> void ValueMetricProducer<AggregatedValue, DimExtras>::flushIfNeededLocked( - const int64_t& eventTimeNs) { + const int64_t eventTimeNs) { const int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs(); if (eventTimeNs < currentBucketEndTimeNs) { VLOG("eventTime is %lld, less than current bucket end time %lld", (long long)eventTimeNs, @@ -742,7 +742,7 @@ int64_t ValueMetricProducer<AggregatedValue, DimExtras>::calcBucketsForwardCount template <typename AggregatedValue, typename DimExtras> void ValueMetricProducer<AggregatedValue, DimExtras>::flushCurrentBucketLocked( - const int64_t& eventTimeNs, const int64_t& nextBucketStartTimeNs) { + const int64_t eventTimeNs, const int64_t nextBucketStartTimeNs) { if (mCondition == ConditionState::kUnknown) { StatsdStats::getInstance().noteBucketUnknownCondition(mMetricId); invalidateCurrentBucket(eventTimeNs, BucketDropReason::CONDITION_UNKNOWN); diff --git a/statsd/src/metrics/ValueMetricProducer.h b/statsd/src/metrics/ValueMetricProducer.h index 6bfc95dc..92541029 100644 --- a/statsd/src/metrics/ValueMetricProducer.h +++ b/statsd/src/metrics/ValueMetricProducer.h @@ -127,13 +127,13 @@ public: } // ValueMetric needs special logic if it's a pulled atom. - void onStatsdInitCompleted(const int64_t& eventTimeNs) override; + void onStatsdInitCompleted(int64_t eventTimeNs) override; void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey, const FieldValue& oldState, const FieldValue& newState) override; protected: - ValueMetricProducer(const int64_t& metricId, const ConfigKey& key, const uint64_t protoHash, + ValueMetricProducer(int64_t metricId, const ConfigKey& key, uint64_t protoHash, const PullOptions& pullOptions, const BucketOptions& bucketOptions, const WhatOptions& whatOptions, const ConditionOptions& conditionOptions, const StateOptions& stateOptions, @@ -178,7 +178,7 @@ protected: } // ValueMetricProducer internal interface to handle condition change. - void onConditionChangedLocked(const bool condition, const int64_t eventTimeNs) override; + void onConditionChangedLocked(const bool condition, int64_t eventTimeNs) override; // Only called when mIsActive, the event is NOT too late, and after pulling. virtual void onConditionChangedInternalLocked(const ConditionState oldCondition, @@ -187,7 +187,7 @@ protected: } // Internal interface to handle sliced condition change. - void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override; + void onSlicedConditionMayChangeLocked(bool overallCondition, int64_t eventTime) override; void dumpStatesLocked(int out, bool verbose) const override; @@ -195,12 +195,11 @@ protected: // For pulled metrics, this method should only be called if a pull has been done. Else we will // not have complete data for the bucket. - void flushIfNeededLocked(const int64_t& eventTime) override; + void flushIfNeededLocked(int64_t eventTime) override; // For pulled metrics, this method should only be called if a pulled has been done. Else we will // not have complete data for the bucket. - void flushCurrentBucketLocked(const int64_t& eventTimeNs, - const int64_t& nextBucketStartTimeNs) override; + void flushCurrentBucketLocked(int64_t eventTimeNs, int64_t nextBucketStartTimeNs) override; void dropDataLocked(const int64_t dropTimeNs) override; @@ -216,7 +215,7 @@ protected: void skipCurrentBucket(const int64_t dropTimeNs, const BucketDropReason reason); optional<InvalidConfigReason> onConfigUpdatedLocked( - const StatsdConfig& config, const int configIndex, const int metricIndex, + const StatsdConfig& config, int configIndex, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -332,7 +331,7 @@ protected: virtual PastBucket<AggregatedValue> buildPartialBucket(int64_t bucketEndTime, std::vector<Interval>& intervals) = 0; - virtual void closeCurrentBucket(const int64_t eventTimeNs, const int64_t nextBucketStartTimeNs); + virtual void closeCurrentBucket(const int64_t eventTimeNs, int64_t nextBucketStartTimeNs); virtual void initNextSlicedBucket(int64_t nextBucketStartTimeNs); diff --git a/statsd/src/metrics/duration_helper/DurationTracker.h b/statsd/src/metrics/duration_helper/DurationTracker.h index 5f2e6433..f86197a9 100644 --- a/statsd/src/metrics/duration_helper/DurationTracker.h +++ b/statsd/src/metrics/duration_helper/DurationTracker.h @@ -73,8 +73,8 @@ struct DurationValues { class DurationTracker { public: - DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, - sp<ConditionWizard> wizard, int conditionIndex, bool nesting, + DurationTracker(const ConfigKey& key, const int64_t id, const MetricDimensionKey& eventKey, + const sp<ConditionWizard>& wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, const std::vector<sp<AnomalyTracker>>& anomalyTrackers) @@ -95,21 +95,21 @@ public: virtual ~DurationTracker(){}; - void onConfigUpdated(const sp<ConditionWizard>& wizard, const int conditionTrackerIndex) { + void onConfigUpdated(const sp<ConditionWizard>& wizard, int conditionTrackerIndex) { sp<ConditionWizard> tmpWizard = mWizard; mWizard = wizard; mConditionTrackerIndex = conditionTrackerIndex; mAnomalyTrackers.clear(); }; - virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime, + virtual void noteStart(const HashableDimensionKey& key, bool condition, int64_t eventTime, const ConditionKey& conditionKey, size_t dimensionHardLimit) = 0; - virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime, + virtual void noteStop(const HashableDimensionKey& key, int64_t eventTime, const bool stopAll) = 0; virtual void noteStopAll(const int64_t eventTime) = 0; virtual void onSlicedConditionMayChange(const int64_t timestamp) = 0; - virtual void onConditionChanged(bool condition, const int64_t timestamp) = 0; + virtual void onConditionChanged(bool condition, int64_t timestamp) = 0; virtual void onStateChanged(const int64_t timestamp, const int32_t atomId, const FieldValue& newState) = 0; @@ -123,7 +123,7 @@ public: // Should only be called during an app upgrade or from this tracker's flushIfNeeded. If from // an app upgrade, we assume that we're trying to form a partial bucket. virtual bool flushCurrentBucket( - const int64_t& eventTimeNs, const optional<UploadThreshold>& uploadThreshold, + int64_t eventTimeNs, const optional<UploadThreshold>& uploadThreshold, const int64_t globalConditionTrueNs, std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0; @@ -138,7 +138,7 @@ public: virtual int64_t getCurrentStateKeyFullBucketDuration() const = 0; // Replace old value with new value for the given state atom. - virtual void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState) = 0; + virtual void updateCurrentStateKey(int32_t atomId, const FieldValue& newState) = 0; virtual bool hasAccumulatedDuration() const = 0; @@ -188,8 +188,8 @@ protected: } } - void addPastBucketToAnomalyTrackers(const MetricDimensionKey eventKey, - const int64_t& bucketValue, const int64_t& bucketNum) { + void addPastBucketToAnomalyTrackers(const MetricDimensionKey& eventKey, int64_t bucketValue, + int64_t bucketNum) { for (auto& anomalyTracker : mAnomalyTrackers) { if (anomalyTracker != nullptr) { anomalyTracker->addPastBucket(eventKey, bucketValue, bucketNum); @@ -197,8 +197,8 @@ protected: } } - void detectAndDeclareAnomaly(const int64_t& timestamp, const int64_t& currBucketNum, - const int64_t& currentBucketValue) { + void detectAndDeclareAnomaly(int64_t timestamp, int64_t currBucketNum, + int64_t currentBucketValue) { for (auto& anomalyTracker : mAnomalyTrackers) { if (anomalyTracker != nullptr) { anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mTrackerId, diff --git a/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp index a263bc56..8a253e26 100644 --- a/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp +++ b/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp @@ -24,12 +24,12 @@ namespace android { namespace os { namespace statsd { -MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id, +MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t id, const MetricDimensionKey& eventKey, - sp<ConditionWizard> wizard, int conditionIndex, bool nesting, - int64_t currentBucketStartNs, int64_t currentBucketNum, - int64_t startTimeNs, int64_t bucketSizeNs, - bool conditionSliced, bool fullLink, + const sp<ConditionWizard>& wizard, int conditionIndex, + bool nesting, int64_t currentBucketStartNs, + int64_t currentBucketNum, int64_t startTimeNs, + int64_t bucketSizeNs, bool conditionSliced, bool fullLink, const vector<sp<AnomalyTracker>>& anomalyTrackers) : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink, @@ -175,7 +175,7 @@ void MaxDurationTracker::noteStopAll(const int64_t eventTime) { } bool MaxDurationTracker::flushCurrentBucket( - const int64_t& eventTimeNs, const optional<UploadThreshold>& uploadThreshold, + const int64_t eventTimeNs, const optional<UploadThreshold>& uploadThreshold, const int64_t globalConditionTrueNs, std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) { VLOG("MaxDurationTracker flushing....."); diff --git a/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/statsd/src/metrics/duration_helper/MaxDurationTracker.h index cff3fb6a..27692326 100644 --- a/statsd/src/metrics/duration_helper/MaxDurationTracker.h +++ b/statsd/src/metrics/duration_helper/MaxDurationTracker.h @@ -28,30 +28,29 @@ namespace statsd { // they stop or bucket expires. class MaxDurationTracker : public DurationTracker { public: - MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, - sp<ConditionWizard> wizard, int conditionIndex, bool nesting, + MaxDurationTracker(const ConfigKey& key, const int64_t id, const MetricDimensionKey& eventKey, + const sp<ConditionWizard>& wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink, const std::vector<sp<AnomalyTracker>>& anomalyTrackers); MaxDurationTracker(const MaxDurationTracker& tracker) = default; - void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime, + void noteStart(const HashableDimensionKey& key, bool condition, int64_t eventTime, const ConditionKey& conditionKey, size_t dimensionHardLimit) override; - void noteStop(const HashableDimensionKey& key, const int64_t eventTime, - const bool stopAll) override; + void noteStop(const HashableDimensionKey& key, int64_t eventTime, const bool stopAll) override; void noteStopAll(const int64_t eventTime) override; bool flushIfNeeded( int64_t timestampNs, const optional<UploadThreshold>& uploadThreshold, std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override; bool flushCurrentBucket( - const int64_t& eventTimeNs, const optional<UploadThreshold>& uploadThreshold, + int64_t eventTimeNs, const optional<UploadThreshold>& uploadThreshold, const int64_t globalConditionTrueNs, std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>*) override; void onSlicedConditionMayChange(const int64_t timestamp) override; - void onConditionChanged(bool condition, const int64_t timestamp) override; + void onConditionChanged(bool condition, int64_t timestamp) override; void onStateChanged(const int64_t timestamp, const int32_t atomId, const FieldValue& newState) override; @@ -64,7 +63,7 @@ public: int64_t getCurrentStateKeyFullBucketDuration() const override; - void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState); + void updateCurrentStateKey(int32_t atomId, const FieldValue& newState); bool hasAccumulatedDuration() const override; diff --git a/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/statsd/src/metrics/duration_helper/OringDurationTracker.cpp index c1c66f85..3fab0e8d 100644 --- a/statsd/src/metrics/duration_helper/OringDurationTracker.cpp +++ b/statsd/src/metrics/duration_helper/OringDurationTracker.cpp @@ -24,11 +24,14 @@ namespace statsd { using std::pair; -OringDurationTracker::OringDurationTracker( - const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, - sp<ConditionWizard> wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs, - int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, - bool fullLink, const vector<sp<AnomalyTracker>>& anomalyTrackers) +OringDurationTracker::OringDurationTracker(const ConfigKey& key, const int64_t id, + const MetricDimensionKey& eventKey, + const sp<ConditionWizard>& wizard, int conditionIndex, + bool nesting, int64_t currentBucketStartNs, + int64_t currentBucketNum, int64_t startTimeNs, + int64_t bucketSizeNs, bool conditionSliced, + bool fullLink, + const vector<sp<AnomalyTracker>>& anomalyTrackers) : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink, anomalyTrackers), @@ -138,7 +141,7 @@ void OringDurationTracker::noteStopAll(const int64_t timestamp) { } bool OringDurationTracker::flushCurrentBucket( - const int64_t& eventTimeNs, const optional<UploadThreshold>& uploadThreshold, + const int64_t eventTimeNs, const optional<UploadThreshold>& uploadThreshold, const int64_t globalConditionTrueNs, std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) { VLOG("OringDurationTracker Flushing............."); diff --git a/statsd/src/metrics/duration_helper/OringDurationTracker.h b/statsd/src/metrics/duration_helper/OringDurationTracker.h index da9b7e3a..a50862b5 100644 --- a/statsd/src/metrics/duration_helper/OringDurationTracker.h +++ b/statsd/src/metrics/duration_helper/OringDurationTracker.h @@ -26,29 +26,27 @@ namespace statsd { // Tracks the "Or'd" duration -- if 2 durations are overlapping, they won't be double counted. class OringDurationTracker : public DurationTracker { public: - OringDurationTracker(const ConfigKey& key, const int64_t& id, - const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard, - int conditionIndex, bool nesting, int64_t currentBucketStartNs, - int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, - bool conditionSliced, bool fullLink, - const std::vector<sp<AnomalyTracker>>& anomalyTrackers); + OringDurationTracker(const ConfigKey& key, const int64_t id, const MetricDimensionKey& eventKey, + const sp<ConditionWizard>& wizard, int conditionIndex, bool nesting, + int64_t currentBucketStartNs, int64_t currentBucketNum, + int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, + bool fullLink, const std::vector<sp<AnomalyTracker>>& anomalyTrackers); OringDurationTracker(const OringDurationTracker& tracker) = default; - void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime, + void noteStart(const HashableDimensionKey& key, bool condition, int64_t eventTime, const ConditionKey& conditionKey, size_t dimensionHardLimit) override; - void noteStop(const HashableDimensionKey& key, const int64_t eventTime, - const bool stopAll) override; + void noteStop(const HashableDimensionKey& key, int64_t eventTime, const bool stopAll) override; void noteStopAll(const int64_t eventTime) override; void onSlicedConditionMayChange(const int64_t timestamp) override; - void onConditionChanged(bool condition, const int64_t timestamp) override; + void onConditionChanged(bool condition, int64_t timestamp) override; void onStateChanged(const int64_t timestamp, const int32_t atomId, const FieldValue& newState) override; bool flushCurrentBucket( - const int64_t& eventTimeNs, const optional<UploadThreshold>& uploadThreshold, + int64_t eventTimeNs, const optional<UploadThreshold>& uploadThreshold, const int64_t globalConditionTrueNs, std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override; bool flushIfNeeded( @@ -63,7 +61,7 @@ public: int64_t getCurrentStateKeyFullBucketDuration() const override; - void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState); + void updateCurrentStateKey(int32_t atomId, const FieldValue& newState); bool hasAccumulatedDuration() const override; diff --git a/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/statsd/src/metrics/parsing_utils/config_update_utils.cpp index e7f30bc1..18d7a329 100644 --- a/statsd/src/metrics/parsing_utils/config_update_utils.cpp +++ b/statsd/src/metrics/parsing_utils/config_update_utils.cpp @@ -37,7 +37,7 @@ optional<InvalidConfigReason> determineMatcherUpdateStatus( const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, const unordered_map<int64_t, int>& newAtomMatchingTrackerMap, - vector<UpdateStatus>& matchersToUpdate, vector<bool>& cycleTracker) { + vector<UpdateStatus>& matchersToUpdate, vector<uint8_t>& cycleTracker) { // Have already examined this matcher. if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) { return nullopt; @@ -145,7 +145,7 @@ optional<InvalidConfigReason> updateAtomMatchingTrackers( // For combination matchers, we need to determine if any children need to be updated. vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN); - vector<bool> cycleTracker(atomMatcherCount, false); + vector<uint8_t> cycleTracker(atomMatcherCount, false); for (int i = 0; i < atomMatcherCount; i++) { invalidConfigReason = determineMatcherUpdateStatus( config, i, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, @@ -171,7 +171,7 @@ optional<InvalidConfigReason> updateAtomMatchingTrackers( const sp<AtomMatchingTracker>& tracker = oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second]; invalidConfigReason = - tracker->onConfigUpdated(matcherProtos[i], i, newAtomMatchingTrackerMap); + tracker->onConfigUpdated(matcherProtos[i], newAtomMatchingTrackerMap); if (invalidConfigReason.has_value()) { ALOGW("Config update failed for matcher %lld", (long long)id); return invalidConfigReason; @@ -184,7 +184,7 @@ optional<InvalidConfigReason> updateAtomMatchingTrackers( [[fallthrough]]; // Intentionally fallthrough to create the new matcher. case UPDATE_NEW: { sp<AtomMatchingTracker> tracker = - createAtomMatchingTracker(matcher, i, uidMap, invalidConfigReason); + createAtomMatchingTracker(matcher, uidMap, invalidConfigReason); if (tracker == nullptr) { return invalidConfigReason; } @@ -203,8 +203,9 @@ optional<InvalidConfigReason> updateAtomMatchingTrackers( std::fill(cycleTracker.begin(), cycleTracker.end(), false); for (size_t matcherIndex = 0; matcherIndex < newAtomMatchingTrackers.size(); matcherIndex++) { auto& matcher = newAtomMatchingTrackers[matcherIndex]; - invalidConfigReason = matcher->init(matcherProtos, newAtomMatchingTrackers, - newAtomMatchingTrackerMap, cycleTracker); + const auto [invalidConfigReason, _] = + matcher->init(matcherIndex, matcherProtos, newAtomMatchingTrackers, + newAtomMatchingTrackerMap, cycleTracker); if (invalidConfigReason.has_value()) { return invalidConfigReason; } @@ -238,7 +239,7 @@ optional<InvalidConfigReason> determineConditionUpdateStatus( const vector<sp<ConditionTracker>>& oldConditionTrackers, const unordered_map<int64_t, int>& newConditionTrackerMap, const set<int64_t>& replacedMatchers, vector<UpdateStatus>& conditionsToUpdate, - vector<bool>& cycleTracker) { + vector<uint8_t>& cycleTracker) { // Have already examined this condition. if (conditionsToUpdate[conditionIdx] != UPDATE_UNKNOWN) { return nullopt; @@ -369,7 +370,7 @@ optional<InvalidConfigReason> updateConditions( } vector<UpdateStatus> conditionsToUpdate(conditionTrackerCount, UPDATE_UNKNOWN); - vector<bool> cycleTracker(conditionTrackerCount, false); + vector<uint8_t> cycleTracker(conditionTrackerCount, false); for (int i = 0; i < conditionTrackerCount; i++) { invalidConfigReason = determineConditionUpdateStatus( config, i, oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap, @@ -519,7 +520,7 @@ optional<InvalidConfigReason> determineMetricUpdateStatus( if (invalidConfigReason.has_value()) { return invalidConfigReason; } - const sp<MetricProducer> oldMetricProducer = oldMetricProducers[oldMetricProducerIt->second]; + const sp<MetricProducer>& oldMetricProducer = oldMetricProducers[oldMetricProducerIt->second]; if (oldMetricProducer->getMetricType() != metricType || oldMetricProducer->getProtoHash() != metricHash) { updateStatus = UPDATE_REPLACE; diff --git a/statsd/src/metrics/parsing_utils/config_update_utils.h b/statsd/src/metrics/parsing_utils/config_update_utils.h index 3bd1e800..8b6c7841 100644 --- a/statsd/src/metrics/parsing_utils/config_update_utils.h +++ b/statsd/src/metrics/parsing_utils/config_update_utils.h @@ -46,11 +46,11 @@ namespace statsd { // [cycleTracker]: intermediate param used during recursion. // Returns nullopt if successful and InvalidConfigReason if not. optional<InvalidConfigReason> determineMatcherUpdateStatus( - const StatsdConfig& config, const int matcherIdx, + const StatsdConfig& config, int matcherIdx, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, - std::vector<UpdateStatus>& matchersToUpdate, std::vector<bool>& cycleTracker); + std::vector<UpdateStatus>& matchersToUpdate, std::vector<uint8_t>& cycleTracker); // Updates the AtomMatchingTrackers. // input: @@ -86,12 +86,12 @@ optional<InvalidConfigReason> updateAtomMatchingTrackers( // [cycleTracker]: intermediate param used during recursion. // Returns nullopt if successful and InvalidConfigReason if not. optional<InvalidConfigReason> determineConditionUpdateStatus( - const StatsdConfig& config, const int conditionIdx, + const StatsdConfig& config, int conditionIdx, const std::unordered_map<int64_t, int>& oldConditionTrackerMap, const std::vector<sp<ConditionTracker>>& oldConditionTrackers, const std::unordered_map<int64_t, int>& newConditionTrackerMap, const std::set<int64_t>& replacedMatchers, std::vector<UpdateStatus>& conditionsToUpdate, - std::vector<bool>& cycleTracker); + std::vector<uint8_t>& cycleTracker); // Updates ConditionTrackers // input: @@ -164,7 +164,7 @@ optional<InvalidConfigReason> determineAllMetricUpdateStatuses( // [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index. // Returns nullopt if successful and InvalidConfigReason if not. optional<InvalidConfigReason> updateMetrics( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -219,7 +219,7 @@ optional<InvalidConfigReason> determineAlertUpdateStatus( // [newAnomalyTrackers]: contains the list of sp to the AnomalyTrackers created. // Returns nullopt if successful and InvalidConfigReason if not. optional<InvalidConfigReason> updateAlerts( - const StatsdConfig& config, const int64_t currentTimeNs, + const StatsdConfig& config, int64_t currentTimeNs, const std::unordered_map<int64_t, int>& metricProducerMap, const std::set<int64_t>& replacedMetrics, const std::unordered_map<int64_t, int>& oldAlertTrackerMap, @@ -234,7 +234,7 @@ optional<InvalidConfigReason> updateAlerts( optional<InvalidConfigReason> updateStatsdConfig( const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor, - const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, + const sp<AlarmMonitor>& periodicAlarmMonitor, int64_t timeBaseNs, const int64_t currentTimeNs, const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, diff --git a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp index cc8e5705..673ff45a 100644 --- a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp +++ b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp @@ -64,10 +64,75 @@ bool hasLeafNode(const FieldMatcher& matcher) { return true; } +// DFS for ensuring there is no +// 1. value matching in the FieldValueMatcher tree with Position::ALL. +// 2. string replacement in the FieldValueMatcher tree without a value matcher with Position::ANY. +// Using vector to keep track of visited FieldValueMatchers since we expect number of +// FieldValueMatchers to be low. +optional<InvalidConfigReasonEnum> validateFvmPositionAllAndAny( + const FieldValueMatcher& fvm, bool inPositionAll, bool inPositionAny, + vector<FieldValueMatcher const*>& visited) { + visited.push_back(&fvm); + inPositionAll = inPositionAll || fvm.position() == Position::ALL; + inPositionAny = inPositionAny || fvm.position() == Position::ANY; + if (fvm.value_matcher_case() == FieldValueMatcher::kMatchesTuple) { + for (const FieldValueMatcher& childFvm : fvm.matches_tuple().field_value_matcher()) { + if (std::find(visited.cbegin(), visited.cend(), &childFvm) != visited.cend()) { + continue; + } + const optional<InvalidConfigReasonEnum> reasonEnum = + validateFvmPositionAllAndAny(childFvm, inPositionAll, inPositionAny, visited); + if (reasonEnum != nullopt) { + return reasonEnum; + } + } + return nullopt; + } + if (inPositionAll && fvm.value_matcher_case() != FieldValueMatcher::VALUE_MATCHER_NOT_SET) { + // value_matcher is set to something other than matches_tuple with Position::ALL + return INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL; + } + if (inPositionAny && fvm.value_matcher_case() == FieldValueMatcher::VALUE_MATCHER_NOT_SET && + fvm.has_replace_string()) { + // value_matcher is not set and there is a string replacement with Position::ANY + return INVALID_CONFIG_REASON_MATCHER_STRING_REPLACE_WITH_NO_VALUE_MATCHER_WITH_POSITION_ANY; + } + return nullopt; +} + +optional<InvalidConfigReason> validateSimpleAtomMatcher(int64_t matcherId, + const SimpleAtomMatcher& simpleMatcher) { + for (const FieldValueMatcher& fvm : simpleMatcher.field_value_matcher()) { + if (fvm.value_matcher_case() == FieldValueMatcher::VALUE_MATCHER_NOT_SET && + !fvm.has_replace_string()) { + return createInvalidConfigReasonWithMatcher( + INVALID_CONFIG_REASON_MATCHER_NO_VALUE_MATCHER_NOR_STRING_REPLACER, matcherId); + } else if (fvm.has_replace_string() && + !(fvm.value_matcher_case() == FieldValueMatcher::VALUE_MATCHER_NOT_SET || + fvm.value_matcher_case() == FieldValueMatcher::kEqString || + fvm.value_matcher_case() == FieldValueMatcher::kEqAnyString || + fvm.value_matcher_case() == FieldValueMatcher::kNeqAnyString || + fvm.value_matcher_case() == FieldValueMatcher::kEqWildcardString || + fvm.value_matcher_case() == FieldValueMatcher::kEqAnyWildcardString || + fvm.value_matcher_case() == FieldValueMatcher::kNeqAnyWildcardString)) { + return createInvalidConfigReasonWithMatcher( + INVALID_CONFIG_REASON_MATCHER_INVALID_VALUE_MATCHER_WITH_STRING_REPLACE, + matcherId); + } + vector<FieldValueMatcher const*> visited; + const optional<InvalidConfigReasonEnum> reasonEnum = validateFvmPositionAllAndAny( + fvm, false /* inPositionAll */, false /* inPositionAny */, visited); + if (reasonEnum != nullopt) { + return createInvalidConfigReasonWithMatcher(*reasonEnum, matcherId); + } + } + return nullopt; +} + } // namespace sp<AtomMatchingTracker> createAtomMatchingTracker( - const AtomMatcher& logMatcher, const int index, const sp<UidMap>& uidMap, + const AtomMatcher& logMatcher, const sp<UidMap>& uidMap, optional<InvalidConfigReason>& invalidConfigReason) { string serializedMatcher; if (!logMatcher.SerializeToString(&serializedMatcher)) { @@ -79,12 +144,18 @@ sp<AtomMatchingTracker> createAtomMatchingTracker( uint64_t protoHash = Hash64(serializedMatcher); switch (logMatcher.contents_case()) { case AtomMatcher::ContentsCase::kSimpleAtomMatcher: { + invalidConfigReason = + validateSimpleAtomMatcher(logMatcher.id(), logMatcher.simple_atom_matcher()); + if (invalidConfigReason != nullopt) { + ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id()); + return nullptr; + } sp<AtomMatchingTracker> simpleAtomMatcher = new SimpleAtomMatchingTracker( - logMatcher.id(), index, protoHash, logMatcher.simple_atom_matcher(), uidMap); + logMatcher.id(), protoHash, logMatcher.simple_atom_matcher(), uidMap); return simpleAtomMatcher; } case AtomMatcher::ContentsCase::kCombination: - return new CombinationAtomMatchingTracker(logMatcher.id(), index, protoHash); + return new CombinationAtomMatchingTracker(logMatcher.id(), protoHash); default: ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id()); invalidConfigReason = createInvalidConfigReasonWithMatcher( @@ -620,7 +691,7 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata( } } - FieldMatcher internalDimensions = simplePredicate.dimensions(); + const FieldMatcher& internalDimensions = simplePredicate.dimensions(); int conditionIndex = -1; if (metric.has_condition()) { @@ -860,7 +931,7 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata( return nullopt; } - sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex); + const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex); int atomTagId = *(atomMatcher->getAtomIds().begin()); int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1; @@ -1089,7 +1160,7 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata( const bool containsAnyPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what()); const bool shouldUseNestedDimensions = ShouldUseNestedDimensions(metric.dimensions_in_what()); - sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex); + const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex); const int atomTagId = *(atomMatcher->getAtomIds().begin()); const auto [dimensionSoftLimit, dimensionHardLimit] = StatsdStats::getAtomDimensionKeySizeLimits( @@ -1167,7 +1238,7 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata( return nullopt; } - sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex); + const sp<AtomMatchingTracker>& atomMatcher = allAtomMatchingTrackers.at(trackerIndex); int atomTagId = *(atomMatcher->getAtomIds().begin()); int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1; @@ -1194,7 +1265,7 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata( if (invalidConfigReason.has_value()) { return nullopt; } - sp<AtomMatchingTracker> triggerAtomMatcher = + const sp<AtomMatchingTracker>& triggerAtomMatcher = allAtomMatchingTrackers.at(triggerTrackerIndex); triggerAtomId = *(triggerAtomMatcher->getAtomIds().begin()); } @@ -1216,6 +1287,18 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata( } } + if (pullTagId != -1 && metric.sampling_percentage() != 100) { + invalidConfigReason = InvalidConfigReason( + INVALID_CONFIG_REASON_GAUGE_METRIC_PULLED_WITH_SAMPLING, metric.id()); + return nullopt; + } + + if (metric.sampling_percentage() < 1 || metric.sampling_percentage() > 100) { + invalidConfigReason = InvalidConfigReason( + INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, metric.id()); + return nullopt; + } + unordered_map<int, shared_ptr<Activation>> eventActivationMap; unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap; invalidConfigReason = handleMetricActivation( @@ -1313,7 +1396,7 @@ optional<InvalidConfigReason> initAtomMatchingTrackers( for (int i = 0; i < atomMatcherCount; i++) { const AtomMatcher& logMatcher = config.atom_matcher(i); sp<AtomMatchingTracker> tracker = - createAtomMatchingTracker(logMatcher, i, uidMap, invalidConfigReason); + createAtomMatchingTracker(logMatcher, uidMap, invalidConfigReason); if (tracker == nullptr) { return invalidConfigReason; } @@ -1327,11 +1410,12 @@ optional<InvalidConfigReason> initAtomMatchingTrackers( matcherConfigs.push_back(logMatcher); } - vector<bool> stackTracker2(allAtomMatchingTrackers.size(), false); + vector<uint8_t> stackTracker2(allAtomMatchingTrackers.size(), false); for (size_t matcherIndex = 0; matcherIndex < allAtomMatchingTrackers.size(); matcherIndex++) { auto& matcher = allAtomMatchingTrackers[matcherIndex]; - invalidConfigReason = matcher->init(matcherConfigs, allAtomMatchingTrackers, - atomMatchingTrackerMap, stackTracker2); + const auto [invalidConfigReason, _] = + matcher->init(matcherIndex, matcherConfigs, allAtomMatchingTrackers, + atomMatchingTrackerMap, stackTracker2); if (invalidConfigReason.has_value()) { return invalidConfigReason; } @@ -1388,7 +1472,7 @@ optional<InvalidConfigReason> initConditions( conditionConfigs.push_back(condition); } - vector<bool> stackTracker(allConditionTrackers.size(), false); + vector<uint8_t> stackTracker(allConditionTrackers.size(), false); for (size_t i = 0; i < allConditionTrackers.size(); i++) { auto& conditionTracker = allConditionTrackers[i]; invalidConfigReason = @@ -1423,8 +1507,8 @@ optional<InvalidConfigReason> initStates( stateProtoHashes[stateId] = Hash64(serializedState); const StateMap& stateMap = state.map(); - for (auto group : stateMap.group()) { - for (auto value : group.value()) { + for (const auto& group : stateMap.group()) { + for (const auto& value : group.value()) { allStateGroupMaps[stateId][value] = group.group_id(); } } diff --git a/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/statsd/src/metrics/parsing_utils/metrics_manager_util.h index c4e231ab..41e8dc7e 100644 --- a/statsd/src/metrics/parsing_utils/metrics_manager_util.h +++ b/statsd/src/metrics/parsing_utils/metrics_manager_util.h @@ -36,12 +36,11 @@ namespace statsd { // Create a AtomMatchingTracker. // input: // [logMatcher]: the input AtomMatcher from the StatsdConfig -// [index]: the index of the matcher // [invalidConfigReason]: logging ids if config is invalid // output: // new AtomMatchingTracker, or null if the tracker is unable to be created sp<AtomMatchingTracker> createAtomMatchingTracker( - const AtomMatcher& logMatcher, const int index, const sp<UidMap>& uidMap, + const AtomMatcher& logMatcher, const sp<UidMap>& uidMap, optional<InvalidConfigReason>& invalidConfigReason); // Create a ConditionTracker. @@ -53,21 +52,20 @@ sp<AtomMatchingTracker> createAtomMatchingTracker( // output: // new ConditionTracker, or null if the tracker is unable to be created sp<ConditionTracker> createConditionTracker( - const ConfigKey& key, const Predicate& predicate, const int index, + const ConfigKey& key, const Predicate& predicate, int index, const unordered_map<int64_t, int>& atomMatchingTrackerMap, optional<InvalidConfigReason>& invalidConfigReason); // Get the hash of a metric, combining the activation if the metric has one. optional<InvalidConfigReason> getMetricProtoHash( - const StatsdConfig& config, const google::protobuf::MessageLite& metric, const int64_t id, + const StatsdConfig& config, const google::protobuf::MessageLite& metric, int64_t id, const std::unordered_map<int64_t, int>& metricToActivationMap, uint64_t& metricHash); // 1. Validates matcher existence // 2. Enforces matchers with dimensions and those used for trigger_event are about one atom // 3. Gets matcher index and updates tracker to metric map optional<InvalidConfigReason> handleMetricWithAtomMatchingTrackers( - const int64_t matcherId, const int64_t metricId, const int metricIndex, - const bool enforceOneAtom, + const int64_t matcherId, int64_t metricId, int metricIndex, const bool enforceOneAtom, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::unordered_map<int, std::vector<int>>& trackerToMetricMap, int& logTrackerIndex); @@ -75,7 +73,7 @@ optional<InvalidConfigReason> handleMetricWithAtomMatchingTrackers( // 1. Validates condition existence, including those in links // 2. Gets condition index and updates condition to metric map optional<InvalidConfigReason> handleMetricWithConditions( - const int64_t condition, const int64_t metricId, const int metricIndex, + const int64_t condition, int64_t metricId, int metricIndex, const std::unordered_map<int64_t, int>& conditionTrackerMap, const ::google::protobuf::RepeatedPtrField<MetricConditionLink>& links, const std::vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex, @@ -85,7 +83,7 @@ optional<InvalidConfigReason> handleMetricWithConditions( // Fills the new event activation/deactivation maps, preserving the existing activations. // Returns nullopt if successful and InvalidConfigReason if not. optional<InvalidConfigReason> handleMetricActivationOnConfigUpdate( - const StatsdConfig& config, const int64_t metricId, const int metricIndex, + const StatsdConfig& config, int64_t metricId, int metricIndex, const std::unordered_map<int64_t, int>& metricToActivationMap, const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap, @@ -99,8 +97,8 @@ optional<InvalidConfigReason> handleMetricActivationOnConfigUpdate( // Creates a CountMetricProducer and updates the vectors/maps used by MetricsManager with // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error. optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, - const int64_t currentTimeNs, const CountMetric& metric, const int metricIndex, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, + const int64_t currentTimeNs, const CountMetric& metric, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, @@ -119,8 +117,8 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata( // Creates a DurationMetricProducer and updates the vectors/maps used by MetricsManager with // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error. optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, - const int64_t currentTimeNs, const DurationMetric& metric, const int metricIndex, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, + const int64_t currentTimeNs, const DurationMetric& metric, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, @@ -139,8 +137,8 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata( // Creates an EventMetricProducer and updates the vectors/maps used by MetricsManager with // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error. optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, - const EventMetric& metric, const int metricIndex, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, + const EventMetric& metric, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, @@ -157,9 +155,9 @@ optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata( // Creates a NumericValueMetricProducer and updates the vectors/maps used by MetricsManager with // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error. optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, - const ValueMetric& metric, const int metricIndex, + const ValueMetric& metric, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, @@ -179,9 +177,9 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata( // Creates a GaugeMetricProducer and updates the vectors/maps used by MetricsManager with // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error. optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, - const GaugeMetric& metric, const int metricIndex, + const GaugeMetric& metric, int metricIndex, const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, std::vector<sp<ConditionTracker>>& allConditionTrackers, @@ -199,9 +197,9 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata( // Creates a KllMetricProducer and updates the vectors/maps used by MetricsManager with // the appropriate indices. Returns an sp to the producer, or nullopt if there was an error. optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, - const KllMetric& metric, const int metricIndex, + const KllMetric& metric, int metricIndex, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, const unordered_map<int64_t, int>& atomMatchingTrackerMap, vector<sp<ConditionTracker>>& allConditionTrackers, @@ -221,7 +219,7 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata( // Returns an sp to the AnomalyTracker, or nullopt if there was an error. optional<sp<AnomalyTracker>> createAnomalyTracker( const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor, - const UpdateStatus& updateStatus, const int64_t currentTimeNs, + const UpdateStatus& updateStatus, int64_t currentTimeNs, const std::unordered_map<int64_t, int>& metricProducerMap, std::vector<sp<MetricProducer>>& allMetricProducers, optional<InvalidConfigReason>& invalidConfigReason); @@ -340,7 +338,7 @@ optional<InvalidConfigReason> initStates( // [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index. // Returns nullopt if successful and InvalidConfigReason if not. optional<InvalidConfigReason> initMetrics( - const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs, + const ConfigKey& key, const StatsdConfig& config, int64_t timeBaseTimeNs, const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager, const std::unordered_map<int64_t, int>& atomMatchingTrackerMap, const std::unordered_map<int64_t, int>& conditionTrackerMap, @@ -361,7 +359,7 @@ optional<InvalidConfigReason> initMetrics( // Is called both on initialize new configs and config updates since alarms do not have any state. optional<InvalidConfigReason> initAlarms(const StatsdConfig& config, const ConfigKey& key, const sp<AlarmMonitor>& periodicAlarmMonitor, - const int64_t timeBaseNs, const int64_t currentTimeNs, + const int64_t timeBaseNs, int64_t currentTimeNs, std::vector<sp<AlarmTracker>>& allAlarmTrackers); // Initialize MetricsManager from StatsdConfig. @@ -369,7 +367,7 @@ optional<InvalidConfigReason> initAlarms(const StatsdConfig& config, const Confi optional<InvalidConfigReason> initStatsdConfig( const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerManager, const sp<AlarmMonitor>& anomalyAlarmMonitor, - const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs, + const sp<AlarmMonitor>& periodicAlarmMonitor, int64_t timeBaseNs, const int64_t currentTimeNs, std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap, std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, diff --git a/statsd/src/packages/PackageInfoListener.h b/statsd/src/packages/PackageInfoListener.h index 485f9fd4..d796774c 100644 --- a/statsd/src/packages/PackageInfoListener.h +++ b/statsd/src/packages/PackageInfoListener.h @@ -29,15 +29,14 @@ class PackageInfoListener : public virtual RefBase { public: // Uid map will notify this listener that the app with apk name and uid has been upgraded to // the specified version. - virtual void notifyAppUpgrade(const int64_t& eventTimeNs, const std::string& apk, - const int uid, const int64_t version) = 0; + virtual void notifyAppUpgrade(int64_t eventTimeNs, const std::string& apk, const int uid, + int64_t version) = 0; // Notify interested listeners that the given apk and uid combination no longer exits. - virtual void notifyAppRemoved(const int64_t& eventTimeNs, const std::string& apk, - const int uid) = 0; + virtual void notifyAppRemoved(int64_t eventTimeNs, const std::string& apk, const int uid) = 0; // Notify the listener that the UidMap snapshot is available. - virtual void onUidMapReceived(const int64_t& eventTimeNs) = 0; + virtual void onUidMapReceived(int64_t eventTimeNs) = 0; }; } // namespace statsd diff --git a/statsd/src/packages/UidMap.cpp b/statsd/src/packages/UidMap.cpp index aa43e8d2..bde1fffd 100644 --- a/statsd/src/packages/UidMap.cpp +++ b/statsd/src/packages/UidMap.cpp @@ -94,12 +94,12 @@ string UidMap::normalizeAppName(const string& appName) const { return normalizedName; } -std::set<string> UidMap::getAppNamesFromUid(const int32_t& uid, bool returnNormalized) const { +std::set<string> UidMap::getAppNamesFromUid(const int32_t uid, bool returnNormalized) const { lock_guard<mutex> lock(mMutex); return getAppNamesFromUidLocked(uid,returnNormalized); } -std::set<string> UidMap::getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const { +std::set<string> UidMap::getAppNamesFromUidLocked(const int32_t uid, bool returnNormalized) const { std::set<string> names; for (const auto& kv : mMap) { if (kv.first.first == uid && !kv.second.deleted) { @@ -119,7 +119,7 @@ int64_t UidMap::getAppVersion(int uid, const string& packageName) const { return it->second.versionCode; } -void UidMap::updateMap(const int64_t& timestamp, const UidData& uidData) { +void UidMap::updateMap(const int64_t timestamp, const UidData& uidData) { wp<PackageInfoListener> broadcast = NULL; { lock_guard<mutex> lock(mMutex); // Exclusively lock for updates. @@ -162,8 +162,8 @@ void UidMap::updateMap(const int64_t& timestamp, const UidData& uidData) { } } -void UidMap::updateApp(const int64_t& timestamp, const string& appName, const int32_t& uid, - const int64_t& versionCode, const string& versionString, +void UidMap::updateApp(const int64_t timestamp, const string& appName, const int32_t uid, + const int64_t versionCode, const string& versionString, const string& installer, const vector<uint8_t>& certificateHash) { wp<PackageInfoListener> broadcast = NULL; @@ -224,7 +224,7 @@ void UidMap::ensureBytesUsedBelowLimit() { } } -void UidMap::removeApp(const int64_t& timestamp, const string& app, const int32_t& uid) { +void UidMap::removeApp(const int64_t timestamp, const string& app, const int32_t uid) { wp<PackageInfoListener> broadcast = NULL; { lock_guard<mutex> lock(mMutex); @@ -260,7 +260,7 @@ void UidMap::removeApp(const int64_t& timestamp, const string& app, const int32_ } } -void UidMap::setListener(wp<PackageInfoListener> listener) { +void UidMap::setListener(const wp<PackageInfoListener>& listener) { lock_guard<mutex> lock(mMutex); // Lock for updates mSubscriber = listener; } @@ -409,7 +409,7 @@ void UidMap::writeUidMapSnapshotLocked(const int64_t timestamp, const bool inclu } } -void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, +void UidMap::appendUidMap(const int64_t timestamp, const ConfigKey& key, const bool includeVersionStrings, const bool includeInstaller, const uint8_t truncatedCertificateHashSize, std::set<string>* str_set, ProtoOutputStream* proto) { diff --git a/statsd/src/packages/UidMap.h b/statsd/src/packages/UidMap.h index d081803c..45429cb8 100644 --- a/statsd/src/packages/UidMap.h +++ b/statsd/src/packages/UidMap.h @@ -73,9 +73,9 @@ struct ChangeRecord { const string versionString; const string prevVersionString; - ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package, - const int32_t uid, const int64_t version, const string versionString, - const int64_t prevVersion, const string prevVersionString) + ChangeRecord(const bool isDeletion, int64_t timestampNs, const string& package, + const int32_t uid, int64_t version, const string& versionString, + const int64_t prevVersion, const string& prevVersionString) : deletion(isDeletion), timestampNs(timestampNs), package(package), @@ -99,18 +99,18 @@ public: static sp<UidMap> getInstance(); - void updateMap(const int64_t& timestamp, const UidData& uidData); + void updateMap(const int64_t timestamp, const UidData& uidData); - void updateApp(const int64_t& timestamp, const string& appName, const int32_t& uid, - const int64_t& versionCode, const string& versionString, const string& installer, + void updateApp(const int64_t timestamp, const string& appName, const int32_t uid, + const int64_t versionCode, const string& versionString, const string& installer, const vector<uint8_t>& certificateHash); - void removeApp(const int64_t& timestamp, const string& app, const int32_t& uid); + void removeApp(const int64_t timestamp, const string& app, const int32_t uid); // Returns true if the given uid contains the specified app (eg. com.google.android.gms). bool hasApp(int uid, const string& packageName) const; // Returns the app names from uid. - std::set<string> getAppNamesFromUid(const int32_t& uid, bool returnNormalized) const; + std::set<string> getAppNamesFromUid(int32_t uid, bool returnNormalized) const; int64_t getAppVersion(int uid, const string& packageName) const; @@ -121,7 +121,7 @@ public: // Command for indicating to the map that StatsLogProcessor should be notified if an app is // updated. This allows metric producers and managers to distinguish when the same uid or app // represents a different version of an app. - void setListener(wp<PackageInfoListener> listener); + void setListener(const wp<PackageInfoListener>& listener); // Informs uid map that a config is added/updated. Used for keeping mConfigKeys up to date. void OnConfigUpdated(const ConfigKey& key); @@ -138,10 +138,9 @@ public: // Gets all snapshots and changes that have occurred since the last output. // If every config key has received a change or snapshot record, then this // record is deleted. - void appendUidMap(const int64_t& timestamp, const ConfigKey& key, - const bool includeVersionStrings, const bool includeInstaller, - const uint8_t truncatedCertificateHashSize, std::set<string>* str_set, - ProtoOutputStream* proto); + void appendUidMap(int64_t timestamp, const ConfigKey& key, const bool includeVersionStrings, + const bool includeInstaller, const uint8_t truncatedCertificateHashSize, + std::set<string>* str_set, ProtoOutputStream* proto); // Forces the output to be cleared. We still generate a snapshot based on the current state. // This results in extra data uploaded but helps us reconstruct the uid mapping on the server @@ -165,7 +164,7 @@ public: ProtoOutputStream* proto) const; private: - std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const; + std::set<string> getAppNamesFromUidLocked(int32_t uid, bool returnNormalized) const; string normalizeAppName(const string& appName) const; void writeUidMapSnapshotLocked(const int64_t timestamp, const bool includeVersionStrings, @@ -179,7 +178,7 @@ private: mutable mutex mIsolatedMutex; struct PairHash { - size_t operator()(std::pair<int, string> p) const noexcept { + size_t operator()(const std::pair<int, string>& p) const noexcept { std::hash<std::string> hash_fn; return hash_fn(std::to_string(p.first) + p.second); } diff --git a/statsd/src/shell/ShellSubscriber.h b/statsd/src/shell/ShellSubscriber.h index 4ff88616..5e54fbf2 100644 --- a/statsd/src/shell/ShellSubscriber.h +++ b/statsd/src/shell/ShellSubscriber.h @@ -56,7 +56,7 @@ namespace statsd { */ class ShellSubscriber : public virtual RefBase { public: - ShellSubscriber(sp<UidMap> uidMap, sp<StatsPullerManager> pullerMgr, + ShellSubscriber(const sp<UidMap>& uidMap, const sp<StatsPullerManager>& pullerMgr, const std::shared_ptr<LogEventFilter>& logEventFilter) : mUidMap(uidMap), mPullerMgr(pullerMgr), mLogEventFilter(logEventFilter){}; diff --git a/statsd/src/shell/ShellSubscriberClient.cpp b/statsd/src/shell/ShellSubscriberClient.cpp index aaa41261..4ae8e93f 100644 --- a/statsd/src/shell/ShellSubscriberClient.cpp +++ b/statsd/src/shell/ShellSubscriberClient.cpp @@ -177,23 +177,25 @@ unique_ptr<ShellSubscriberClient> ShellSubscriberClient::create( bool ShellSubscriberClient::writeEventToProtoIfMatched(const LogEvent& event, const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap) { - if (!matchesSimple(uidMap, matcher, event)) { + auto [matched, transformedEvent] = matchesSimple(mUidMap, matcher, event); + if (!matched) { return false; } + const LogEvent& eventRef = transformedEvent == nullptr ? event : *transformedEvent; // Cache atom event in mProtoOut. uint64_t atomToken = mProtoOut.start(util::FIELD_TYPE_MESSAGE | util::FIELD_COUNT_REPEATED | FIELD_ID_SHELL_DATA__ATOM); - event.ToProto(mProtoOut); + eventRef.ToProto(mProtoOut); mProtoOut.end(atomToken); - const int64_t timestampNs = truncateTimestampIfNecessary(event); + const int64_t timestampNs = truncateTimestampIfNecessary(eventRef); mProtoOut.write(util::FIELD_TYPE_INT64 | util::FIELD_COUNT_REPEATED | FIELD_ID_SHELL_DATA__ELAPSED_TIMESTAMP_NANOS, static_cast<long long>(timestampNs)); // Update byte size of cached data. - mCacheSize += getSize(event.getValues()) + sizeof(timestampNs); + mCacheSize += getSize(eventRef.getValues()) + sizeof(timestampNs); return true; } diff --git a/statsd/src/socket/StatsSocketListener.cpp b/statsd/src/socket/StatsSocketListener.cpp index 3f360333..dd1013d4 100644 --- a/statsd/src/socket/StatsSocketListener.cpp +++ b/statsd/src/socket/StatsSocketListener.cpp @@ -38,10 +38,10 @@ namespace android { namespace os { namespace statsd { -StatsSocketListener::StatsSocketListener(std::shared_ptr<LogEventQueue> queue, +StatsSocketListener::StatsSocketListener(const std::shared_ptr<LogEventQueue>& queue, const std::shared_ptr<LogEventFilter>& logEventFilter) : SocketListener(getLogSocket(), false /*start listen*/), - mQueue(std::move(queue)), + mQueue(queue), mLogEventFilter(logEventFilter) { } @@ -148,6 +148,7 @@ void StatsSocketListener::processMessage(const uint8_t* msg, uint32_t len, uint3 const int32_t atomId = logEvent->GetTagId(); const bool isAtomSkipped = logEvent->isParsedHeaderOnly(); + const int64_t atomTimestamp = logEvent->GetElapsedTimestampNs(); if (atomId == util::STATS_SOCKET_LOSS_REPORTED) { if (isAtomSkipped) { @@ -164,8 +165,10 @@ void StatsSocketListener::processMessage(const uint8_t* msg, uint32_t len, uint3 } } - int64_t oldestTimestamp; - if (!queue->push(std::move(logEvent), &oldestTimestamp)) { + const auto [success, oldestTimestamp, queueSize] = queue->push(std::move(logEvent)); + if (success) { + StatsdStats::getInstance().noteEventQueueSize(queueSize, atomTimestamp); + } else { StatsdStats::getInstance().noteEventQueueOverflow(oldestTimestamp, atomId, isAtomSkipped); } } diff --git a/statsd/src/socket/StatsSocketListener.h b/statsd/src/socket/StatsSocketListener.h index 903eff39..fcff2c2b 100644 --- a/statsd/src/socket/StatsSocketListener.h +++ b/statsd/src/socket/StatsSocketListener.h @@ -38,7 +38,7 @@ namespace statsd { class StatsSocketListener : public SocketListener, public virtual RefBase { public: - explicit StatsSocketListener(std::shared_ptr<LogEventQueue> queue, + explicit StatsSocketListener(const std::shared_ptr<LogEventQueue>& queue, const std::shared_ptr<LogEventFilter>& logEventFilter); virtual ~StatsSocketListener() = default; @@ -81,6 +81,7 @@ private: FRIEND_TEST(SocketParseMessageTest, TestProcessMessageFilterCompleteSet); FRIEND_TEST(SocketParseMessageTest, TestProcessMessageFilterPartialSet); FRIEND_TEST(SocketParseMessageTest, TestProcessMessageFilterToggle); + FRIEND_TEST(LogEventQueue_test, TestQueueMaxSize); }; } // namespace statsd diff --git a/statsd/src/state/StateManager.cpp b/statsd/src/state/StateManager.cpp index 7841748f..1a324952 100644 --- a/statsd/src/state/StateManager.cpp +++ b/statsd/src/state/StateManager.cpp @@ -53,7 +53,7 @@ void StateManager::onLogEvent(const LogEvent& event) { } } -void StateManager::registerListener(const int32_t atomId, wp<StateListener> listener) { +void StateManager::registerListener(const int32_t atomId, const wp<StateListener>& listener) { // Check if state tracker already exists. if (mStateTrackers.find(atomId) == mStateTrackers.end()) { mStateTrackers[atomId] = new StateTracker(atomId); @@ -61,7 +61,7 @@ void StateManager::registerListener(const int32_t atomId, wp<StateListener> list mStateTrackers[atomId]->registerListener(listener); } -void StateManager::unregisterListener(const int32_t atomId, wp<StateListener> listener) { +void StateManager::unregisterListener(const int32_t atomId, const wp<StateListener>& listener) { std::unique_lock<std::mutex> lock(mMutex); // Hold the sp<> until the lock is released so that ~StateTracker() is diff --git a/statsd/src/state/StateManager.h b/statsd/src/state/StateManager.h index 68b5c906..2db206ec 100644 --- a/statsd/src/state/StateManager.h +++ b/statsd/src/state/StateManager.h @@ -55,17 +55,17 @@ public: // If the correct StateTracker does not exist, a new StateTracker is created. // Note: StateTrackers can be created for non-state atoms. They are essentially empty and // do not perform any actions. - void registerListener(const int32_t atomId, wp<StateListener> listener); + void registerListener(const int32_t atomId, const wp<StateListener>& listener); // Notifies the correct StateTracker to unregister a listener // and removes the tracker if it no longer has any listeners. - void unregisterListener(const int32_t atomId, wp<StateListener> listener); + void unregisterListener(const int32_t atomId, const wp<StateListener>& listener); // Returns true if the StateTracker exists and queries for the // original state value mapped to the given query key. The state value is // stored and output in a FieldValue class. // Returns false if the StateTracker doesn't exist. - bool getStateValue(const int32_t atomId, const HashableDimensionKey& queryKey, + bool getStateValue(int32_t atomId, const HashableDimensionKey& queryKey, FieldValue* output) const; // Updates mAllowedLogSources with the latest uids for the packages that are allowed to log. @@ -77,7 +77,7 @@ public: return mStateTrackers.size(); } - inline int getListenersCount(const int32_t atomId) const { + inline int getListenersCount(int32_t atomId) const { auto it = mStateTrackers.find(atomId); if (it != mStateTrackers.end()) { return it->second->getListenersCount(); diff --git a/statsd/src/state/StateTracker.cpp b/statsd/src/state/StateTracker.cpp index 250a65c0..d037e734 100644 --- a/statsd/src/state/StateTracker.cpp +++ b/statsd/src/state/StateTracker.cpp @@ -25,7 +25,7 @@ namespace android { namespace os { namespace statsd { -StateTracker::StateTracker(const int32_t atomId) : mField(atomId, 0) { +StateTracker::StateTracker(int32_t atomId) : mField(atomId, 0) { } void StateTracker::onLogEvent(const LogEvent& event) { @@ -62,11 +62,11 @@ void StateTracker::onLogEvent(const LogEvent& event) { updateStateForPrimaryKey(eventTimeNs, primaryKey, newState, nested, mStateMap[primaryKey]); } -void StateTracker::registerListener(wp<StateListener> listener) { +void StateTracker::registerListener(const wp<StateListener>& listener) { mListeners.insert(listener); } -void StateTracker::unregisterListener(wp<StateListener> listener) { +void StateTracker::unregisterListener(const wp<StateListener>& listener) { mListeners.erase(listener); } @@ -165,7 +165,7 @@ void StateTracker::updateStateForPrimaryKey(const int64_t eventTimeNs, void StateTracker::notifyListeners(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey, const FieldValue& oldState, const FieldValue& newState) { - for (auto l : mListeners) { + for (const auto& l : mListeners) { auto sl = l.promote(); if (sl != nullptr) { sl->onStateChanged(eventTimeNs, mField.getTag(), primaryKey, oldState, newState); diff --git a/statsd/src/state/StateTracker.h b/statsd/src/state/StateTracker.h index 2bef70ea..0fd504d3 100644 --- a/statsd/src/state/StateTracker.h +++ b/statsd/src/state/StateTracker.h @@ -29,7 +29,7 @@ namespace statsd { class StateTracker : public virtual RefBase { public: - StateTracker(const int32_t atomId); + StateTracker(int32_t atomId); virtual ~StateTracker(){}; @@ -40,9 +40,9 @@ public: // Adds new listeners to set of StateListeners. If a listener is already // registered, it is ignored. - void registerListener(wp<StateListener> listener); + void registerListener(const wp<StateListener>& listener); - void unregisterListener(wp<StateListener> listener); + void unregisterListener(const wp<StateListener>& listener); // The output is a FieldValue object that has mStateField as the field and // the original state value (found using the given query key) as the value. diff --git a/statsd/src/stats_log.proto b/statsd/src/stats_log.proto index b0955467..fdb031a9 100644 --- a/statsd/src/stats_log.proto +++ b/statsd/src/stats_log.proto @@ -682,6 +682,13 @@ message StatsdStatsReport { } optional SocketLossStats socket_loss_stats = 24; + + message EventQueueStats { + optional int32 max_size_observed = 1; + optional int64 max_size_observed_elapsed_nanos = 2; + } + + optional EventQueueStats event_queue_stats = 25; } message AlertTriggerDetails { diff --git a/statsd/src/stats_log_util.cpp b/statsd/src/stats_log_util.cpp index 1d9a43bd..77a3d4f6 100644 --- a/statsd/src/stats_log_util.cpp +++ b/statsd/src/stats_log_util.cpp @@ -617,7 +617,7 @@ bool checkPermissionForIds(const char* permission, pid_t pid, uid_t uid) { return success; } -void mapIsolatedUidsToHostUidInLogEvent(const sp<UidMap> uidMap, LogEvent& event) { +void mapIsolatedUidsToHostUidInLogEvent(const sp<UidMap>& uidMap, LogEvent& event) { uint8_t remainingUidCount = event.getNumUidFields(); vector<FieldValue>* fieldValues = event.getMutableValues(); auto it = fieldValues->begin(); diff --git a/statsd/src/stats_log_util.h b/statsd/src/stats_log_util.h index 68155e46..3ca94be6 100644 --- a/statsd/src/stats_log_util.h +++ b/statsd/src/stats_log_util.h @@ -79,7 +79,7 @@ int64_t NanoToMillis(const int64_t nano); int64_t MillisToNano(const int64_t millis); // Helper function to write a stats field to ProtoOutputStream if it's a non-zero value. -void writeNonZeroStatToStream(const uint64_t fieldId, const int64_t value, +void writeNonZeroStatToStream(const uint64_t fieldId, int64_t value, ProtoOutputStream* protoOutput); // Helper function to write PulledAtomStats to ProtoOutputStream @@ -117,7 +117,7 @@ inline bool isPulledAtom(int atomId) { return atomId >= StatsdStats::kPullAtomStartTag && atomId < StatsdStats::kVendorAtomStartTag; } -void mapIsolatedUidsToHostUidInLogEvent(const sp<UidMap> uidMap, LogEvent& event); +void mapIsolatedUidsToHostUidInLogEvent(const sp<UidMap>& uidMap, LogEvent& event); std::string toHexString(const string& bytes); diff --git a/statsd/src/statsd_config.proto b/statsd/src/statsd_config.proto index e8c1d99f..a7eef69a 100644 --- a/statsd/src/statsd_config.proto +++ b/statsd/src/statsd_config.proto @@ -56,6 +56,14 @@ message FieldMatcher { repeated FieldMatcher child = 3; } +message StringReplacer { + // Regex for matching the string. + optional string regex = 1; + + // String with which to replace the matched string. + optional string replacement = 2; +} + message FieldValueMatcher { optional int32 field = 1; @@ -85,6 +93,11 @@ message FieldValueMatcher { StringListMatcher eq_any_wildcard_string = 18; StringListMatcher neq_any_wildcard_string = 19; } + + // Can only be present if either: + // 1. value_matcher is not set. + // 2. value_matcher is set to one that is applicable to string fields. + optional StringReplacer replace_string = 20; } message MessageMatcher { @@ -343,6 +356,8 @@ message GaugeMetric { optional int32 max_dimensions_per_bucket = 16; + optional int32 sampling_percentage = 17 [default = 100]; + reserved 100; reserved 101; } diff --git a/statsd/src/storage/StorageManager.h b/statsd/src/storage/StorageManager.h index 9a25bf07..0a459a86 100644 --- a/statsd/src/storage/StorageManager.h +++ b/statsd/src/storage/StorageManager.h @@ -42,7 +42,7 @@ const uint32_t TRAIN_INFO_FILE_MAGIC = 0xfb7447bf; class StorageManager : public virtual RefBase { public: struct FileInfo { - FileInfo(std::string name, bool isHistory, int fileSize, long fileAge) + FileInfo(const std::string& name, bool isHistory, int fileSize, long fileAge) : mFileName(name), mIsHistory(isHistory), mFileSizeBytes(fileSize), @@ -162,8 +162,7 @@ public: static void sortFiles(vector<FileInfo>* fileNames); - static void enforceDbGuardrails(const char* path, const int64_t wallClockSec, - const int64_t maxBytes); + static void enforceDbGuardrails(const char* path, int64_t wallClockSec, int64_t maxBytes); static bool hasFile(const char* file); diff --git a/statsd/src/utils/DbUtils.h b/statsd/src/utils/DbUtils.h index 8a561e64..06d12929 100644 --- a/statsd/src/utils/DbUtils.h +++ b/statsd/src/utils/DbUtils.h @@ -39,15 +39,15 @@ string getDbName(const ConfigKey& key); string reformatMetricId(const int64_t metricId); /* Creates a new data table for a specified metric if one does not yet exist. */ -bool createTableIfNeeded(const ConfigKey& key, const int64_t metricId, const LogEvent& event); +bool createTableIfNeeded(const ConfigKey& key, int64_t metricId, const LogEvent& event); /* Checks whether the table schema for the given metric matches the event. * Returns true if the table has not yet been created. */ -bool isEventCompatible(const ConfigKey& key, const int64_t metricId, const LogEvent& event); +bool isEventCompatible(const ConfigKey& key, int64_t metricId, const LogEvent& event); /* Deletes a data table for the specified metric. */ -bool deleteTable(const ConfigKey& key, const int64_t metricId); +bool deleteTable(const ConfigKey& key, int64_t metricId); /* Deletes the SQLite db data file. */ void deleteDb(const ConfigKey& key); @@ -63,11 +63,10 @@ void closeDb(sqlite3* db); /* Inserts new data into the specified metric data table. * A temp sqlite handle is created using the ConfigKey. */ -bool insert(const ConfigKey& key, const int64_t metricId, const vector<LogEvent>& events, - string& error); +bool insert(const ConfigKey& key, int64_t metricId, const vector<LogEvent>& events, string& error); /* Inserts new data into the specified sqlite db handle. */ -bool insert(sqlite3* db, const int64_t metricId, const vector<LogEvent>& events, string& error); +bool insert(sqlite3* db, int64_t metricId, const vector<LogEvent>& events, string& error); /* Executes a sql query on the specified SQLite db. * A temp sqlite handle is created using the ConfigKey. @@ -75,7 +74,7 @@ bool insert(sqlite3* db, const int64_t metricId, const vector<LogEvent>& events, bool query(const ConfigKey& key, const string& zSql, vector<vector<string>>& rows, vector<int32_t>& columnTypes, vector<string>& columnNames, string& err); -bool flushTtl(sqlite3* db, const int64_t metricId, const int64_t ttlWallClockNs); +bool flushTtl(sqlite3* db, int64_t metricId, int64_t ttlWallClockNs); /* Checks for database corruption and deletes the db if it is corrupted. */ void verifyIntegrityAndDeleteIfNecessary(const ConfigKey& key); @@ -86,4 +85,4 @@ bool updateDeviceInfoTable(const ConfigKey& key, string& error); } // namespace dbutils } // namespace statsd } // namespace os -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/statsd/src/utils/MultiConditionTrigger.cpp b/statsd/src/utils/MultiConditionTrigger.cpp index 5ef50ee0..8ef064a8 100644 --- a/statsd/src/utils/MultiConditionTrigger.cpp +++ b/statsd/src/utils/MultiConditionTrigger.cpp @@ -28,7 +28,7 @@ namespace statsd { MultiConditionTrigger::MultiConditionTrigger(const set<string>& conditionNames, function<void()> trigger) : mRemainingConditionNames(conditionNames), - mTrigger(trigger), + mTrigger(std::move(trigger)), mCompleted(mRemainingConditionNames.empty()) { if (mCompleted) { thread executorThread([this] { mTrigger(); }); diff --git a/statsd/src/utils/ShardOffsetProvider.h b/statsd/src/utils/ShardOffsetProvider.h index 7facd98b..506e2306 100644 --- a/statsd/src/utils/ShardOffsetProvider.h +++ b/statsd/src/utils/ShardOffsetProvider.h @@ -51,6 +51,7 @@ private: FRIEND_TEST(CountMetricE2eTest, TestDimensionalSampling); FRIEND_TEST(DurationMetricE2eTest, TestDimensionalSampling); FRIEND_TEST(GaugeMetricE2ePushedTest, TestDimensionalSampling); + FRIEND_TEST(GaugeMetricE2ePushedTest, TestPushedGaugeMetricSamplingWithDimensionalSampling); FRIEND_TEST(GaugeMetricProducerTest, TestPullDimensionalSampling); FRIEND_TEST(KllMetricE2eTest, TestDimensionalSampling); FRIEND_TEST(NumericValueMetricProducerTest, TestDimensionalSampling); diff --git a/statsd/tests/FieldValue_test.cpp b/statsd/tests/FieldValue_test.cpp index 146d4b7d..3baf9f7b 100644 --- a/statsd/tests/FieldValue_test.cpp +++ b/statsd/tests/FieldValue_test.cpp @@ -739,7 +739,7 @@ TEST(AtomMatcherTest, TestWriteAtomWithRepeatedFieldsToProto) { bool boolArray[boolArrayLength]; boolArray[0] = 1; boolArray[1] = 0; - vector<bool> boolArrayVector = {1, 0}; + vector<uint8_t> boolArrayVector = {1, 0}; vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF}; unique_ptr<LogEvent> event = CreateTestAtomReportedEventVariableRepeatedFields( diff --git a/statsd/tests/LogEntryMatcher_test.cpp b/statsd/tests/LogEntryMatcher_test.cpp index 5c098c29..2a0be072 100644 --- a/statsd/tests/LogEntryMatcher_test.cpp +++ b/statsd/tests/LogEntryMatcher_test.cpp @@ -24,6 +24,7 @@ #include "statsd_test_util.h" using namespace android::os::statsd; +using std::shared_ptr; using std::unordered_map; using std::vector; @@ -31,7 +32,7 @@ const int32_t TAG_ID = 123; const int32_t TAG_ID_2 = 28; // hardcoded tag of atom with uid field const int FIELD_ID_1 = 1; const int FIELD_ID_2 = 2; -const int FIELD_ID_3 = 2; +const int FIELD_ID_3 = 3; const int ATTRIBUTION_UID_FIELD_ID = 1; const int ATTRIBUTION_TAG_FIELD_ID = 2; @@ -151,11 +152,11 @@ TEST(AtomMatcherTest, TestSimpleMatcher) { makeIntLogEvent(&event, TAG_ID, 0, 11); // Test - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Wrong tag id. simpleMatcher->set_atom_id(TAG_ID + 1); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestAttributionMatcher) { @@ -186,43 +187,43 @@ TEST(AtomMatcherTest, TestAttributionMatcher) { fieldMatcher->set_eq_string("some value"); // Tag not matched. - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location3"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last node. attributionMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any node. attributionMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location2"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location4"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Attribution match but primitive field not match. attributionMatcher->set_position(Position::ANY); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "location2"); fieldMatcher->set_eq_string("wrong value"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldMatcher->set_eq_string("some value"); @@ -232,7 +233,7 @@ TEST(AtomMatcherTest, TestAttributionMatcher) { ATTRIBUTION_UID_FIELD_ID); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg0"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); UidData uidData; *uidData.add_app_info() = createApplicationInfo(/*uid*/ 1111, /*version*/ 1, "v1", "pkg0"); @@ -243,47 +244,47 @@ TEST(AtomMatcherTest, TestAttributionMatcher) { uidMap->updateMap(1, uidData); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg0"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::FIRST); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg0"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::LAST); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg0"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Uid + tag. attributionMatcher->set_position(Position::ANY); @@ -293,96 +294,96 @@ TEST(AtomMatcherTest, TestAttributionMatcher) { "pkg0"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location2"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::FIRST); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg0"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location2"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location3"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location3"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::LAST); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg0"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg1"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location2"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string( "pkg3"); attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)->set_eq_string( "location1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestUidFieldMatcher) { @@ -407,7 +408,7 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) { // Make event without is_uid annotation. LogEvent event1(/*uid=*/0, /*pid=*/0); makeIntLogEvent(&event1, TAG_ID, 0, 1111); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); // Make event with is_uid annotation. LogEvent event2(/*uid=*/0, /*pid=*/0); @@ -416,12 +417,12 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) { // Event has is_uid annotation, so mapping from uid to package name occurs. simpleMatcher->set_atom_id(TAG_ID_2); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); // Event has is_uid annotation, but uid maps to different package name. simpleMatcher->mutable_field_value_matcher(0)->set_eq_string( "pkg2"); // package names are normalized - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2).matched); } TEST(AtomMatcherTest, TestRepeatedUidFieldMatcher) { @@ -450,35 +451,35 @@ TEST(AtomMatcherTest, TestRepeatedUidFieldMatcher) { fieldValueMatcher->set_position(Position::FIRST); fieldValueMatcher->set_eq_string("pkg0"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); fieldValueMatcher->set_position(Position::LAST); fieldValueMatcher->set_eq_string("pkg1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); fieldValueMatcher->set_position(Position::ANY); fieldValueMatcher->set_eq_string("pkg2"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); // is_uid annotation, mapping from uid to package name. LogEvent event2(/*uid=*/0, /*pid=*/0); makeRepeatedUidLogEvent(&event2, TAG_ID, intArray); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2).matched); fieldValueMatcher->set_eq_string("pkg0"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2).matched); fieldValueMatcher->set_eq_string("pkg1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); fieldValueMatcher->set_position(Position::ANY); fieldValueMatcher->set_eq_string("pkg"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2).matched); fieldValueMatcher->set_eq_string("pkg2"); // package names are normalized - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); } TEST(AtomMatcherTest, TestNeqAnyStringMatcher_SingleString) { @@ -498,17 +499,17 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher_SingleString) { // First string matched. LogEvent event1(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event1, TAG_ID, 0, "some value"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); // Second string matched. LogEvent event2(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event2, TAG_ID, 0, "another value"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2).matched); // No strings matched. LogEvent event3(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event3, TAG_ID, 0, "foo"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3).matched); } TEST(AtomMatcherTest, TestNeqAnyStringMatcher_AttributionUids) { @@ -551,26 +552,26 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher_AttributionUids) { fieldMatcher->set_field(FIELD_ID_2); fieldMatcher->set_eq_string("some value"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); neqStringList->Clear(); neqStringList->add_str_value("pkg1"); neqStringList->add_str_value("pkg3"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::ANY); neqStringList->Clear(); neqStringList->add_str_value("maps.com"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); neqStringList->Clear(); neqStringList->add_str_value("PkG3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::LAST); neqStringList->Clear(); neqStringList->add_str_value("AID_STATSD"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestEqAnyStringMatcher) { @@ -613,29 +614,29 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) { fieldMatcher->set_field(FIELD_ID_2); fieldMatcher->set_eq_string("some value"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); attributionMatcher->set_position(Position::ANY); eqStringList->Clear(); eqStringList->add_str_value("AID_STATSD"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); eqStringList->Clear(); eqStringList->add_str_value("pkg1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); auto normalStringField = fieldMatcher->mutable_eq_any_string(); normalStringField->add_str_value("some value123"); normalStringField->add_str_value("some value"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); normalStringField->Clear(); normalStringField->add_str_value("AID_STATSD"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); eqStringList->Clear(); eqStringList->add_str_value("maps.com"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestBoolMatcher) { @@ -656,19 +657,19 @@ TEST(AtomMatcherTest, TestBoolMatcher) { // Test keyValue1->set_eq_bool(true); keyValue2->set_eq_bool(false); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue1->set_eq_bool(false); keyValue2->set_eq_bool(false); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue1->set_eq_bool(false); keyValue2->set_eq_bool(true); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue1->set_eq_bool(true); keyValue2->set_eq_bool(true); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestStringMatcher) { @@ -686,7 +687,7 @@ TEST(AtomMatcherTest, TestStringMatcher) { makeStringLogEvent(&event, TAG_ID, 0, "some value"); // Test - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestIntMatcher_EmptyRepeatedField) { @@ -706,16 +707,16 @@ TEST(AtomMatcherTest, TestIntMatcher_EmptyRepeatedField) { // Match first int. fieldValueMatcher->set_position(Position::FIRST); fieldValueMatcher->set_eq_int(9); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last int. fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any int. fieldValueMatcher->set_position(Position::ANY); fieldValueMatcher->set_eq_int(13); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestIntMatcher_RepeatedIntField) { @@ -736,28 +737,28 @@ TEST(AtomMatcherTest, TestIntMatcher_RepeatedIntField) { fieldValueMatcher->set_field(FIELD_ID_1); fieldValueMatcher->set_position(Position::FIRST); fieldValueMatcher->set_eq_int(9); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_int(21); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last int. fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_int(9); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any int. fieldValueMatcher->set_position(Position::ANY); fieldValueMatcher->set_eq_int(13); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_int(21); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_int(9); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestLtIntMatcher_RepeatedIntField) { @@ -778,34 +779,34 @@ TEST(AtomMatcherTest, TestLtIntMatcher_RepeatedIntField) { fieldValueMatcher->set_field(FIELD_ID_1); fieldValueMatcher->set_position(Position::FIRST); fieldValueMatcher->set_lt_int(9); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_lt_int(21); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_lt_int(23); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last int. fieldValueMatcher->set_position(Position::LAST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_lt_int(9); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_lt_int(8); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any int. fieldValueMatcher->set_position(Position::ANY); fieldValueMatcher->set_lt_int(21); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_lt_int(8); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_lt_int(23); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestStringMatcher_RepeatedStringField) { @@ -826,31 +827,31 @@ TEST(AtomMatcherTest, TestStringMatcher_RepeatedStringField) { fieldValueMatcher->set_field(FIELD_ID_1); fieldValueMatcher->set_position(Position::FIRST); fieldValueMatcher->set_eq_string("str2"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_string("str1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last int. fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_string("str3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any int. fieldValueMatcher->set_position(Position::ANY); fieldValueMatcher->set_eq_string("str4"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_string("str1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_string("str2"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_eq_string("str3"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestEqAnyStringMatcher_RepeatedStringField) { @@ -871,43 +872,43 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher_RepeatedStringField) { StringListMatcher* eqStringList = fieldValueMatcher->mutable_eq_any_string(); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); eqStringList->add_str_value("str4"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); eqStringList->add_str_value("str2"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); eqStringList->add_str_value("str3"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); eqStringList->add_str_value("str1"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestNeqAnyStringMatcher_RepeatedStringField) { @@ -928,43 +929,43 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher_RepeatedStringField) { StringListMatcher* neqStringList = fieldValueMatcher->mutable_neq_any_string(); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); neqStringList->add_str_value("str4"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); neqStringList->add_str_value("str2"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); neqStringList->add_str_value("str3"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); neqStringList->add_str_value("str1"); fieldValueMatcher->set_position(Position::FIRST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::LAST); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); fieldValueMatcher->set_position(Position::ANY); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestMultiFieldsMatcher) { @@ -985,15 +986,15 @@ TEST(AtomMatcherTest, TestMultiFieldsMatcher) { // Test keyValue1->set_eq_int(2); keyValue2->set_eq_int(3); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue1->set_eq_int(2); keyValue2->set_eq_int(4); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue1->set_eq_int(4); keyValue2->set_eq_int(3); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestIntComparisonMatcher) { @@ -1014,43 +1015,43 @@ TEST(AtomMatcherTest, TestIntComparisonMatcher) { // eq_int keyValue->set_eq_int(10); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_eq_int(11); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_eq_int(12); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // lt_int keyValue->set_lt_int(10); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_lt_int(11); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_lt_int(12); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // lte_int keyValue->set_lte_int(10); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_lte_int(11); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_lte_int(12); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // gt_int keyValue->set_gt_int(10); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_gt_int(11); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_gt_int(12); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // gte_int keyValue->set_gte_int(10); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_gte_int(11); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); keyValue->set_gte_int(12); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); } TEST(AtomMatcherTest, TestFloatComparisonMatcher) { @@ -1066,20 +1067,20 @@ TEST(AtomMatcherTest, TestFloatComparisonMatcher) { LogEvent event1(/*uid=*/0, /*pid=*/0); makeFloatLogEvent(&event1, TAG_ID, 0, 10.1f); keyValue->set_lt_float(10.0); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); LogEvent event2(/*uid=*/0, /*pid=*/0); makeFloatLogEvent(&event2, TAG_ID, 0, 9.9f); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); LogEvent event3(/*uid=*/0, /*pid=*/0); makeFloatLogEvent(&event3, TAG_ID, 0, 10.1f); keyValue->set_gt_float(10.0); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3).matched); LogEvent event4(/*uid=*/0, /*pid=*/0); makeFloatLogEvent(&event4, TAG_ID, 0, 9.9f); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4).matched); } // Helper for the composite matchers. @@ -1226,17 +1227,17 @@ TEST(AtomMatcherTest, TestUidFieldMatcherWithWildcardString) { // Event without is_uid annotation. LogEvent event1(/*uid=*/0, /*pid=*/0); makeIntLogEvent(&event1, TAG_ID, 0, 1111); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1).matched); // Event where mapping from uid to package name occurs. LogEvent event2(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event2, TAG_ID, 1111, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); // Event where uid maps to package names that don't fit wildcard pattern. LogEvent event3(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event3, TAG_ID, 3333, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event3)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event3).matched); // Update matcher to match one AID simpleMatcher->mutable_field_value_matcher(0)->set_eq_wildcard_string( @@ -1245,12 +1246,12 @@ TEST(AtomMatcherTest, TestUidFieldMatcherWithWildcardString) { // Event where mapping from uid to aid doesn't fit wildcard pattern. LogEvent event4(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event4, TAG_ID, 1005, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4).matched); // Event where mapping from uid to aid does fit wildcard pattern. LogEvent event5(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event5, TAG_ID, 1000, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event5)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event5).matched); // Update matcher to match multiple AIDs simpleMatcher->mutable_field_value_matcher(0)->set_eq_wildcard_string("AID_SDCARD_*"); @@ -1258,16 +1259,16 @@ TEST(AtomMatcherTest, TestUidFieldMatcherWithWildcardString) { // Event where mapping from uid to aid doesn't fit wildcard pattern. LogEvent event6(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event6, TAG_ID, 1036, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event6)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event6).matched); // Event where mapping from uid to aid does fit wildcard pattern. LogEvent event7(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event7, TAG_ID, 1034, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event7)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event7).matched); LogEvent event8(/*uid=*/0, /*pid=*/0); makeIntWithBoolAnnotationLogEvent(&event8, TAG_ID, 1035, ASTATSLOG_ANNOTATION_ID_IS_UID, true); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event8)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event8).matched); } TEST(AtomMatcherTest, TestWildcardStringMatcher) { @@ -1284,55 +1285,57 @@ TEST(AtomMatcherTest, TestWildcardStringMatcher) { LogEvent event1(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event1, TAG_ID, 0, "test.string:test_0"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event1).matched); LogEvent event2(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event2, TAG_ID, 0, "test.string:test_19"); - EXPECT_FALSE( - matchesSimple(uidMap, *simpleMatcher, event2)); // extra character at end of string + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2) + .matched); // extra character at end of string LogEvent event3(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event3, TAG_ID, 0, "extra.test.string:test_1"); EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, - event3)); // extra characters at beginning of string + event3) + .matched); // extra characters at beginning of string LogEvent event4(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event4, TAG_ID, 0, "test.string:test_"); EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, - event4)); // missing character from 0-9 at end of string + event4) + .matched); // missing character from 0-9 at end of string LogEvent event5(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event5, TAG_ID, 0, "est.string:test_1"); - EXPECT_FALSE( - matchesSimple(uidMap, *simpleMatcher, event5)); // missing 't' at beginning of string + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event5) + .matched); // missing 't' at beginning of string LogEvent event6(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event6, TAG_ID, 0, "test.string:test_1extra"); - EXPECT_FALSE( - matchesSimple(uidMap, *simpleMatcher, event6)); // extra characters at end of string + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event6) + .matched); // extra characters at end of string // Matches any string that contains "test.string:test_" + any extra characters before or after fieldValueMatcher->set_eq_wildcard_string("*test.string:test_*"); LogEvent event7(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event7, TAG_ID, 0, "test.string:test_"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event7)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event7).matched); LogEvent event8(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event8, TAG_ID, 0, "extra.test.string:test_"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event8)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event8).matched); LogEvent event9(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event9, TAG_ID, 0, "test.string:test_extra"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event9)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event9).matched); LogEvent event10(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event10, TAG_ID, 0, "est.string:test_"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event10)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event10).matched); LogEvent event11(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event11, TAG_ID, 0, "test.string:test"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event11)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event11).matched); } TEST(AtomMatcherTest, TestEqAnyWildcardStringMatcher) { @@ -1352,17 +1355,17 @@ TEST(AtomMatcherTest, TestEqAnyWildcardStringMatcher) { // First wildcard pattern matched. LogEvent event1(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event1, TAG_ID, 0, "first_string_1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event1).matched); // Second wildcard pattern matched. LogEvent event2(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event2, TAG_ID, 0, "second_string_1"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); // No wildcard patterns matched. LogEvent event3(/*uid=*/0, /*pid=*/0); makeStringLogEvent(&event3, TAG_ID, 0, "third_string_1"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event3)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event3).matched); } TEST(AtomMatcherTest, TestNeqAnyWildcardStringMatcher) { @@ -1389,27 +1392,27 @@ TEST(AtomMatcherTest, TestNeqAnyWildcardStringMatcher) { // First tag is not matched. neq string list {"tag"} neqWildcardStrList->add_str_value("tag"); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // First tag is matched. neq string list {"tag", "location_*"} neqWildcardStrList->add_str_value("location_*"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last tag. attributionMatcher->set_position(Position::LAST); // Last tag is not matched. neq string list {"tag", "location_*"} - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Last tag is matched. neq string list {"tag", "location_*", "location*"} neqWildcardStrList->add_str_value("location*"); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any tag. attributionMatcher->set_position(Position::ANY); // All tags are matched. neq string list {"tag", "location_*", "location*"} - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Set up another log event. std::vector<string> attributionTags2 = {"location_1", "location", "string"}; @@ -1417,7 +1420,7 @@ TEST(AtomMatcherTest, TestNeqAnyWildcardStringMatcher) { makeAttributionLogEvent(&event2, TAG_ID, 0, attributionUids, attributionTags2, "some value"); // Tag "string" is not matched. neq string list {"tag", "location_*", "location*"} - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); } TEST(AtomMatcherTest, TestEqAnyIntMatcher) { @@ -1437,17 +1440,17 @@ TEST(AtomMatcherTest, TestEqAnyIntMatcher) { // First int matched. LogEvent event1(/*uid=*/0, /*pid=*/0); makeIntLogEvent(&event1, TAG_ID, 0, 3); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event1)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event1).matched); // Second int matched. LogEvent event2(/*uid=*/0, /*pid=*/0); makeIntLogEvent(&event2, TAG_ID, 0, 5); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2).matched); // No ints matched. LogEvent event3(/*uid=*/0, /*pid=*/0); makeIntLogEvent(&event3, TAG_ID, 0, 4); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event3)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event3).matched); } TEST(AtomMatcherTest, TestNeqAnyIntMatcher) { @@ -1473,31 +1476,569 @@ TEST(AtomMatcherTest, TestNeqAnyIntMatcher) { // First uid is not matched. neq int list {4444} neqIntList->add_int_value(4444); - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // First uid is matched. neq int list {4444, 1111} neqIntList->add_int_value(1111); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match last uid. attributionMatcher->set_position(Position::LAST); // Last uid is not matched. neq int list {4444, 1111} - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Last uid is matched. neq int list {4444, 1111, 3333} neqIntList->add_int_value(3333); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); // Match any uid. attributionMatcher->set_position(Position::ANY); // Uid 2222 is not matched. neq int list {4444, 1111, 3333} - EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event).matched); // All uids are matched. neq int list {4444, 1111, 3333, 2222} neqIntList->add_int_value(2222); - EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event)); + EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event).matched); +} + +TEST(AtomMatcherTest, TestStringReplaceRoot) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Set up the matcher. Replace second field. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(FIELD_ID_2); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "location1"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "location2"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "location3"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "some value"); +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagFirst) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Set up the matcher. Replace first attribution tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::FIRST); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "location2"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "location3"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "some value123"); +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagLast) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Set up the matcher. Replace last attribution tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::LAST); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "location1"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "location2"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "some value123"); +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagAll) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Set up the matcher. Replace all attribution tags. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::ALL); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "some value123"); +} + +TEST(AtomMatcherTest, TestStringReplaceNestedAllWithMultipleNestedStringFields) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Manually change uid fields to string fields, as there is no direct way to create a + // LogEvent with multiple nested string fields. + (*event.getMutableValues())[0].mValue = android::os::statsd::Value("abc1"); + (*event.getMutableValues())[2].mValue = android::os::statsd::Value("xyz2"); + (*event.getMutableValues())[4].mValue = android::os::statsd::Value("abc3"); + + // Set up the matcher. Replace all attribution tags. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::ALL); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.str_value, "abc1"); + EXPECT_EQ(fieldValues[1].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[2].mValue.str_value, "xyz2"); + EXPECT_EQ(fieldValues[3].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[4].mValue.str_value, "abc3"); + EXPECT_EQ(fieldValues[5].mValue.str_value, "location"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "some value123"); +} + +TEST(AtomMatcherTest, TestStringReplaceRootOnMatchedField) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the matcher. Replace second field and match on replaced field. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(FIELD_ID_2); + fvm->set_eq_string("bar"); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, + "some value123"); + + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "bar123"); + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "location1"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "location2"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "location3"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "bar"); + } +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagFirstOnMatchedField) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the matcher. Replace first attribution tag and match on that tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::FIRST); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + attributionTagFvm->set_eq_string("bar"); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, + "some value123"); + + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + attributionTags = {"bar1", "bar2", "bar3"}; + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "bar123"); + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "bar"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "bar2"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "bar3"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "bar123"); + } +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagLastOnMatchedField) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the matcher. Replace last attribution tag and match on that tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::LAST); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + attributionTagFvm->set_eq_string("bar"); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, + "some value123"); + + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + attributionTags = {"bar1", "bar2", "bar3"}; + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "bar123"); + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "bar1"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "bar2"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "bar"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "bar123"); + } +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagAnyOnMatchedField) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the matcher. Replace all attribution tags but match on any tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::ANY); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + attributionTagFvm->set_eq_string("bar"); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, + "some value123"); + + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + attributionTags = {"foo1", "bar2", "foo3"}; + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "bar123"); + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "foo"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "bar"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "foo"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "bar123"); + } +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagAnyAndRootOnMatchedFields) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the matcher. Replace all attribution tags but match on any tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::ANY); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + attributionTagFvm->set_eq_string("bar"); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + FieldValueMatcher* rootFvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + rootFvm->set_field(FIELD_ID_2); + rootFvm->set_eq_string("blah"); + stringReplacer = rootFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, {1111, 2222, 3333} /* uids */, + {"location1", "location2", "location3"} /* tags */, + "some value123" /* name */); + + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, {1111, 2222, 3333} /* uids */, + {"foo1", "bar2", "foo3"} /* tags */, "bar123" /* name */); + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, {1111, 2222, 3333} /* uids */, + {"foo1", "bar2", "foo3"} /* tags */, "blah123" /* name */); + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "foo"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "bar"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "foo"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "blah"); + } +} + +TEST(AtomMatcherTest, TestStringReplaceAttributionTagAnyWithAttributionUidValueMatcher) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the matcher. Replace all attribution tags but match on any uid and tag. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* attributionFvm = + matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + attributionFvm->set_field(FIELD_ID_1); + attributionFvm->set_position(Position::ANY); + FieldValueMatcher* attributionUidFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionUidFvm->set_field(ATTRIBUTION_UID_FIELD_ID); + attributionUidFvm->set_eq_int(2222); + FieldValueMatcher* attributionTagFvm = + attributionFvm->mutable_matches_tuple()->add_field_value_matcher(); + attributionTagFvm->set_field(ATTRIBUTION_TAG_FIELD_ID); + attributionTagFvm->set_eq_string("bar"); + StringReplacer* stringReplacer = attributionTagFvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, {1111, 2222, 3333} /* uids */, + {"location1", "location2", "location3"} /* tags */, + "some value123" /* name */); + + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, {1111, 3223, 3333} /* uids */, + {"foo1", "bar2", "foo3"} /* tags */, "bar123" /* name */); + EXPECT_FALSE(matchesSimple(uidMap, matcher.simple_atom_matcher(), event).matched); + } + + { + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, {1111, 2222, 3333} /* uids */, + {"foo1", "bar2", "foo3"} /* tags */, "bar123" /* name */); + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_NE(transformedEvent, nullptr); + const vector<FieldValue>& fieldValues = transformedEvent->getValues(); + ASSERT_EQ(fieldValues.size(), 7); + EXPECT_EQ(fieldValues[0].mValue.int_value, 1111); + EXPECT_EQ(fieldValues[1].mValue.str_value, "foo"); + EXPECT_EQ(fieldValues[2].mValue.int_value, 2222); + EXPECT_EQ(fieldValues[3].mValue.str_value, "bar"); + EXPECT_EQ(fieldValues[4].mValue.int_value, 3333); + EXPECT_EQ(fieldValues[5].mValue.str_value, "foo"); + EXPECT_EQ(fieldValues[6].mValue.str_value, "bar123"); + } +} + +TEST(AtomMatcherTest, TestStringReplaceBadRegex) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Set up the matcher. Replace second field. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(FIELD_ID_2); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"(*[\d]+$)"); // bad regex: asterisk not preceded by any expression. + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_EQ(transformedEvent, nullptr); +} + +TEST(AtomMatcherTest, TestStringReplaceNoop) { + sp<UidMap> uidMap = new UidMap(); + + // Set up the log event. + std::vector<int> attributionUids = {1111, 2222, 3333}; + std::vector<string> attributionTags = {"location1", "location2", "location3"}; + LogEvent event(/*uid=*/0, /*pid=*/0); + makeAttributionLogEvent(&event, TAG_ID, 0, attributionUids, attributionTags, "some value123"); + + // Set up the matcher. Replace second field. + AtomMatcher matcher = CreateSimpleAtomMatcher("matcher", TAG_ID); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(FIELD_ID_2); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"(this_pattern_should_not_match)"); + stringReplacer->set_replacement(""); + + const auto [hasMatched, transformedEvent] = + matchesSimple(uidMap, matcher.simple_atom_matcher(), event); + EXPECT_TRUE(hasMatched); + ASSERT_EQ(transformedEvent, nullptr); } #else diff --git a/statsd/tests/LogEvent_test.cpp b/statsd/tests/LogEvent_test.cpp index 674b5463..f53e2472 100644 --- a/statsd/tests/LogEvent_test.cpp +++ b/statsd/tests/LogEvent_test.cpp @@ -37,7 +37,8 @@ using ::util::ProtoReader; namespace { -Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) { +Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, + const vector<uint8_t>& last) { Field f(tag, (int32_t*)pos.data(), depth); // only decorate last position for depths with repeated fields (depth 1) diff --git a/statsd/tests/SocketListener_test.cpp b/statsd/tests/SocketListener_test.cpp index 90e5d3e1..3636508f 100644 --- a/statsd/tests/SocketListener_test.cpp +++ b/statsd/tests/SocketListener_test.cpp @@ -87,8 +87,11 @@ INSTANTIATE_TEST_SUITE_P(SocketParseMessageTest, SocketParseMessageTest, testing SocketParseMessageTest::ToString); TEST_P(SocketParseMessageTest, TestProcessMessage) { + StatsdStats::getInstance().reset(); + generateAtomLogging(mEventQueue, mLogEventFilter, kEventCount, kAtomId); + int64_t lastEventTs = 0; // check content of the queue EXPECT_EQ(kEventCount, mEventQueue->mQueue.size()); for (int i = 0; i < kEventCount; i++) { @@ -96,7 +99,11 @@ TEST_P(SocketParseMessageTest, TestProcessMessage) { EXPECT_TRUE(logEvent->isValid()); EXPECT_EQ(kAtomId + i, logEvent->GetTagId()); EXPECT_EQ(logEvent->isParsedHeaderOnly(), GetParam()); + lastEventTs = logEvent->GetElapsedTimestampNs(); } + + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, kEventCount); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, lastEventTs); } TEST_P(SocketParseMessageTest, TestProcessMessageEmptySetExplicitSet) { diff --git a/statsd/tests/UidMap_test.cpp b/statsd/tests/UidMap_test.cpp index 7cef63e9..9e5d7f01 100644 --- a/statsd/tests/UidMap_test.cpp +++ b/statsd/tests/UidMap_test.cpp @@ -52,7 +52,7 @@ const vector<string> kVersionStrings{"v1", "v1", "v2"}; const vector<string> kApps{kApp1, kApp2, kApp3}; const vector<string> kInstallers{"", "", "com.android.vending"}; const vector<vector<uint8_t>> kCertificateHashes{{'a', 'z'}, {'b', 'c'}, {'d', 'e'}}; -const vector<bool> kDeleted(3, false); +const vector<uint8_t> kDeleted(3, false); void sendPackagesToStatsd(shared_ptr<StatsService> service, const vector<int32_t>& uids, const vector<int64_t>& versions, const vector<string>& versionStrings, @@ -214,7 +214,7 @@ TEST(UidMapTest, TestRemoveApp) { std::set<string> name_set = uidMap->getAppNamesFromUid(1000, true /* returnNormalized */); EXPECT_THAT(name_set, UnorderedElementsAre(kApp2)); - vector<bool> deleted(kDeleted); + vector<uint8_t> deleted(kDeleted); deleted[0] = true; vector<PackageInfo> expectedPackageInfos = buildPackageInfos(kApps, kUids, kVersions, kVersionStrings, kInstallers, @@ -299,7 +299,7 @@ TEST(UidMapTest, TestUpdateApp) { versionStrings[0] = "v40"; vector<string> apps = concatenate(kApps, {"NeW_aPP1_NAmE", "NeW_aPP1_NAmE"}); vector<string> installers = concatenate(kInstallers, {"com.android.vending", "new_installer"}); - vector<bool> deleted = concatenate(kDeleted, {false, false}); + vector<uint8_t> deleted = concatenate(kDeleted, {false, false}); vector<vector<uint8_t>> certHashes = concatenate(kCertificateHashes, {{'a'}, {'b'}}); vector<PackageInfo> expectedPackageInfos = buildPackageInfos(apps, uids, versions, versionStrings, installers, certHashes, deleted, diff --git a/statsd/tests/anomaly/AnomalyTracker_test.cpp b/statsd/tests/anomaly/AnomalyTracker_test.cpp index 9d7ccea2..827f8f52 100644 --- a/statsd/tests/anomaly/AnomalyTracker_test.cpp +++ b/statsd/tests/anomaly/AnomalyTracker_test.cpp @@ -74,8 +74,7 @@ int64_t getBucketValue(const std::shared_ptr<DimToValMap>& bucket, } // Returns true if keys in trueList are detected as anomalies and keys in falseList are not. -bool detectAnomaliesPass(AnomalyTracker& tracker, - const int64_t& bucketNum, +bool detectAnomaliesPass(AnomalyTracker& tracker, int64_t bucketNum, const std::shared_ptr<DimToValMap>& currentBucket, const std::set<const MetricDimensionKey>& trueList, const std::set<const MetricDimensionKey>& falseList) { @@ -93,10 +92,8 @@ bool detectAnomaliesPass(AnomalyTracker& tracker, } // Calls tracker.detectAndDeclareAnomaly on each key in the bucket. -void detectAndDeclareAnomalies(AnomalyTracker& tracker, - const int64_t& bucketNum, - const std::shared_ptr<DimToValMap>& bucket, - const int64_t& eventTimestamp) { +void detectAndDeclareAnomalies(AnomalyTracker& tracker, int64_t bucketNum, + const std::shared_ptr<DimToValMap>& bucket, int64_t eventTimestamp) { for (const auto& kv : *bucket) { tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, 0 /*metric_id*/, kv.first, kv.second); @@ -107,9 +104,8 @@ void detectAndDeclareAnomalies(AnomalyTracker& tracker, // timestamp (in ns) + refractoryPeriodSec. // If a timestamp value is negative, instead asserts that the refractory period is inapplicable // (either non-existant or already past). -void checkRefractoryTimes(AnomalyTracker& tracker, - const int64_t& currTimestampNs, - const int32_t& refractoryPeriodSec, +void checkRefractoryTimes(AnomalyTracker& tracker, int64_t currTimestampNs, + int32_t refractoryPeriodSec, const std::unordered_map<MetricDimensionKey, int64_t>& timestamps) { for (const auto& kv : timestamps) { if (kv.second < 0) { diff --git a/statsd/tests/condition/SimpleConditionTracker_test.cpp b/statsd/tests/condition/SimpleConditionTracker_test.cpp index 1407cf46..b38ae4d0 100644 --- a/statsd/tests/condition/SimpleConditionTracker_test.cpp +++ b/statsd/tests/condition/SimpleConditionTracker_test.cpp @@ -146,7 +146,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueFalse) { EXPECT_EQ(ConditionState::kFalse, conditionCache[0]); vector<MatchingState> matcherState; - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); // Matched stop event. // Check that condition is still false. @@ -200,7 +200,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueUnknown) { EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]); vector<MatchingState> matcherState; - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); // Matched stop event. // Check that condition is changed to false. @@ -256,7 +256,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) { vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache); @@ -343,7 +343,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache); @@ -419,7 +419,7 @@ TEST_P(SimpleConditionTrackerTest, TestSlicedCondition) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache, changedCache); @@ -524,7 +524,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache, changedCache); @@ -616,7 +616,7 @@ TEST_P(SimpleConditionTrackerTest, TestStopAll) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache, changedCache); @@ -714,7 +714,7 @@ TEST(SimpleConditionTrackerTest, TestGuardrailNotHitWhenDefaultFalse) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache); @@ -761,7 +761,7 @@ TEST(SimpleConditionTrackerTest, TestGuardrailHitWhenDefaultUnknown) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache); @@ -791,7 +791,7 @@ TEST(SimpleConditionTrackerTest, TestGuardrailHitWhenDefaultUnknown) { matcherState.push_back(MatchingState::kNotMatched); vector<sp<ConditionTracker>> allPredicates; vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated); - vector<bool> changedCache(1, false); + vector<uint8_t> changedCache(1, false); conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache); diff --git a/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/statsd/tests/e2e/DurationMetric_e2e_test.cpp index 6908f57b..a6d50d9a 100644 --- a/statsd/tests/e2e/DurationMetric_e2e_test.cpp +++ b/statsd/tests/e2e/DurationMetric_e2e_test.cpp @@ -466,7 +466,6 @@ TEST(DurationMetricE2eTest, TestWithCondition) { TEST(DurationMetricE2eTest, TestWithSlicedCondition) { StatsdConfig config; - auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher(); *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher(); *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher(); *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); diff --git a/statsd/tests/e2e/EventMetric_e2e_test.cpp b/statsd/tests/e2e/EventMetric_e2e_test.cpp index 9ae86041..0432f3ce 100644 --- a/statsd/tests/e2e/EventMetric_e2e_test.cpp +++ b/statsd/tests/e2e/EventMetric_e2e_test.cpp @@ -127,7 +127,7 @@ TEST_F(EventMetricE2eTest, TestRepeatedFieldsAndEmptyArrays) { bool boolArray[boolArrayLength]; boolArray[0] = 1; boolArray[1] = 0; - vector<bool> boolArrayVector = {1, 0}; + vector<uint8_t> boolArrayVector = {1, 0}; vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF}; events.push_back(CreateTestAtomReportedEventVariableRepeatedFields( diff --git a/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp index 55e6f774..b852d7f8 100644 --- a/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp +++ b/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp @@ -341,7 +341,7 @@ TEST_F(GaugeMetricE2ePushedTest, TestRepeatedFieldsForPushedEvent) { bool boolArray[boolArrayLength]; boolArray[0] = 1; boolArray[1] = 0; - vector<bool> boolArrayVector = {1, 0}; + vector<uint8_t> boolArrayVector = {1, 0}; vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF}; events.push_back(CreateTestAtomReportedEventVariableRepeatedFields( @@ -498,6 +498,178 @@ TEST_F(GaugeMetricE2ePushedTest, TestDimensionalSampling) { {gaugeEventTimeNs3, gaugeEventTimeNs6}); } +TEST_F(GaugeMetricE2ePushedTest, TestPushedGaugeMetricSampling) { + // Initiating StatsdStats at the start of this test, so it doesn't call rand() during the test. + StatsdStats::getInstance(); + // Set srand seed to make rand deterministic for testing. + srand(0); + + StatsdConfig config; + config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + + AtomMatcher appCrashMatcher = + CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED); + *config.add_atom_matcher() = appCrashMatcher; + + GaugeMetric sampledGaugeMetric = + createGaugeMetric("GaugeSampledAppCrashesPerUid", appCrashMatcher.id(), + GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt); + *sampledGaugeMetric.mutable_dimensions_in_what() = + CreateDimensions(util::APP_CRASH_OCCURRED, {1 /* uid */}); + sampledGaugeMetric.set_sampling_percentage(50); + *config.add_gauge_metric() = sampledGaugeMetric; + + const int64_t configAddedTimeNs = 10 * NS_PER_SEC; // 0:10 + const int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000LL * 1000LL; + + int uid = 12345; + int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor( + configAddedTimeNs, configAddedTimeNs, config, cfgKey, nullptr, 0, new UidMap()); + + std::vector<std::unique_ptr<LogEvent>> events; + for (int i = 0; i < 10; i++) { + events.push_back( + CreateAppCrashOccurredEvent(configAddedTimeNs + (10 * i * NS_PER_SEC), 1000 + i)); + } + + // Send log events to StatsLogProcessor. + for (auto& event : events) { + processor->OnLogEvent(event.get()); + } + + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP, + FAST, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + backfillAggregatedAtoms(&reports); + + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + EXPECT_TRUE(reports.reports(0).metrics(0).has_gauge_metrics()); + StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); + ASSERT_EQ(5, gaugeMetrics.data_size()); + + GaugeMetricData data = gaugeMetrics.data(0); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1000); + ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs, + configAddedTimeNs + bucketSizeNs, {configAddedTimeNs}); + + data = gaugeMetrics.data(1); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1002); + ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs, + configAddedTimeNs + bucketSizeNs, + {configAddedTimeNs + (10 * 2 * NS_PER_SEC)}); + + data = gaugeMetrics.data(2); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1003); + ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs, + configAddedTimeNs + bucketSizeNs, + {configAddedTimeNs + (10 * 3 * NS_PER_SEC)}); + + data = gaugeMetrics.data(3); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1007); + ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs, + configAddedTimeNs + bucketSizeNs, + {configAddedTimeNs + (10 * 7 * NS_PER_SEC)}); + + data = gaugeMetrics.data(4); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1009); + ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs, + configAddedTimeNs + bucketSizeNs, + {configAddedTimeNs + (10 * 9 * NS_PER_SEC)}); +} + +TEST_F(GaugeMetricE2ePushedTest, TestPushedGaugeMetricSamplingWithDimensionalSampling) { + ShardOffsetProvider::getInstance().setShardOffset(5); + // Initiating StatsdStats at the start of this test, so it doesn't call rand() during the test. + StatsdStats::getInstance(); + // Set srand seed to make rand deterministic for testing. + srand(0); + + StatsdConfig config; + config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. + + AtomMatcher appCrashMatcher = + CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED); + *config.add_atom_matcher() = appCrashMatcher; + + GaugeMetric sampledGaugeMetric = + createGaugeMetric("GaugeSampledAppCrashesPerUid", appCrashMatcher.id(), + GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt); + *sampledGaugeMetric.mutable_dimensions_in_what() = + CreateDimensions(util::APP_CRASH_OCCURRED, {1 /* uid */}); + *sampledGaugeMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() = + CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/}); + sampledGaugeMetric.mutable_dimensional_sampling_info()->set_shard_count(2); + sampledGaugeMetric.set_sampling_percentage(50); + *config.add_gauge_metric() = sampledGaugeMetric; + + const int64_t configAddedTimeNs = 10 * NS_PER_SEC; // 0:10 + const int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000LL * 1000LL; + + int uid = 12345; + int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor( + configAddedTimeNs, configAddedTimeNs, config, cfgKey, nullptr, 0, new UidMap()); + + std::vector<std::unique_ptr<LogEvent>> events; + for (int i = 0; i < 30; i++) { + // Generate events with three different app uids: 1001, 1002, 1003. + events.push_back(CreateAppCrashOccurredEvent(configAddedTimeNs + (10 * i * NS_PER_SEC), + 1001 + (i % 3))); + } + + // Send log events to StatsLogProcessor. + for (auto& event : events) { + processor->OnLogEvent(event.get()); + } + + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP, + FAST, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + backfillAggregatedAtoms(&reports); + + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + EXPECT_TRUE(reports.reports(0).metrics(0).has_gauge_metrics()); + StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); + ASSERT_EQ(2, gaugeMetrics.data_size()); + + // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0 + GaugeMetricData data = gaugeMetrics.data(0); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1001); + ValidateGaugeBucketTimes( + data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs, + {10 * NS_PER_SEC, 40 * NS_PER_SEC, 220 * NS_PER_SEC, 280 * NS_PER_SEC}); + + data = gaugeMetrics.data(1); + ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1003); + ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs, + configAddedTimeNs + bucketSizeNs, + {60 * NS_PER_SEC, 120 * NS_PER_SEC, 150 * NS_PER_SEC, 180 * NS_PER_SEC, + 210 * NS_PER_SEC, 300 * NS_PER_SEC}); +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/statsd/tests/e2e/StringReplace_e2e_test.cpp b/statsd/tests/e2e/StringReplace_e2e_test.cpp new file mode 100644 index 00000000..27bcf520 --- /dev/null +++ b/statsd/tests/e2e/StringReplace_e2e_test.cpp @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2024, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <gtest_matchers.h> + +#include "src/StatsLogProcessor.h" +#include "tests/statsd_test_util.h" + +namespace android { +namespace os { +namespace statsd { + +#ifdef __ANDROID__ + +namespace { + +const int64_t metricId = 123456; +const int TEST_ATOM_REPORTED_STRING_FIELD_ID = 5; +const int SUBSYSTEM_SLEEP_STATE_SUBSYSTEM_NAME_FIELD_ID = 1; +const int SUBSYSTEM_SLEEP_STATE_SUBNAME_FIELD_ID = 2; +const int SUBSYSTEM_SLEEP_STATE_TIME_MILLIS_FIELD_ID = 4; +const int SCHEDULED_JOB_STATE_CHANGED_JOB_NAME_FIELD_ID = 2; +const int ACTIVITY_FOREGROUND_STATE_CHANGED_UID_FIELD_ID = 1; +const int ACTIVITY_FOREGROUND_STATE_CHANGED_PKG_NAME_FIELD_ID = 2; +const int WAKELOCK_STATE_CHANGED_TAG_FIELD_ID = 3; +const int ATTRIBUTION_CHAIN_FIELD_ID = 1; +const int ATTRIBUTION_TAG_FIELD_ID = 2; + +std::unique_ptr<LogEvent> CreateTestAtomReportedEventStringDim(uint64_t timestampNs, + const string& stringField) { + return CreateTestAtomReportedEventWithPrimitives( + timestampNs, 0 /* intField */, 0l /* longField */, 0.0f /* floatField */, stringField, + false /* boolField */, TestAtomReported::OFF /* enumField */); +} + +StatsdConfig CreateStatsdConfig() { + StatsdConfig config; + config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root. + config.set_hash_strings_in_metric_report(false); + + return config; +} + +} // namespace + +TEST(StringReplaceE2eTest, TestPushedDimension) { + StatsdConfig config = CreateStatsdConfig(); + + *config.add_atom_matcher() = + CreateSimpleAtomMatcher("TestAtomMatcher", util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = config.mutable_atom_matcher(0) + ->mutable_simple_atom_matcher() + ->add_field_value_matcher(); + fvm->set_field(TEST_ATOM_REPORTED_STRING_FIELD_ID); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + CountMetric* countMetric = config.add_count_metric(); + *countMetric = createCountMetric("TestCountMetric", config.atom_matcher(0).id() /* what */, + nullopt /* condition */, {} /* states */); + countMetric->mutable_dimensions_in_what()->set_field(util::TEST_ATOM_REPORTED); + countMetric->mutable_dimensions_in_what()->add_child()->set_field( + TEST_ATOM_REPORTED_STRING_FIELD_ID); + + // Initialize StatsLogProcessor. + const uint64_t bucketStartTimeNs = 10000000000; // 0:10 + const uint64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL; + const int uid = 12345; + const int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor( + bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap()); + + std::vector<std::unique_ptr<LogEvent>> events; + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 20 * NS_PER_SEC, + "dimA" /* stringField */)); // 0:30 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 40 * NS_PER_SEC, + "dimA123" /* stringField */)); // 0:50 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 60 * NS_PER_SEC, + "dimA123B" /* stringField */)); // 1:10 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 80 * NS_PER_SEC, + "dimC0" /* stringField */)); // 1:20 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 90 * NS_PER_SEC, + "dimC00000" /* stringField */)); // 1:30 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 100 * NS_PER_SEC, + "dimC" /* stringField */)); // 1:40 + + // Send log events to StatsLogProcessor. + for (auto& event : events) { + processor->OnLogEvent(event.get()); + } + + // Check dump report. + vector<uint8_t> buffer; + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP, + FAST, &buffer); + ASSERT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics()); + StatsLogReport::CountMetricDataWrapper countMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); + ASSERT_EQ(3, countMetrics.data_size()); + + CountMetricData data = countMetrics.data(0); + DimensionsValue dimValue = data.dimensions_in_what(); + EXPECT_EQ(dimValue.field(), util::TEST_ATOM_REPORTED); + ASSERT_EQ(dimValue.value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(dimValue.value_tuple().dimensions_value(0).field(), + TEST_ATOM_REPORTED_STRING_FIELD_ID); + EXPECT_EQ(dimValue.value_tuple().dimensions_value(0).value_str(), "dimA"); + ASSERT_EQ(1, data.bucket_info_size()); + EXPECT_EQ(2, data.bucket_info(0).count()); + + data = countMetrics.data(1); + dimValue = data.dimensions_in_what(); + EXPECT_EQ(dimValue.field(), util::TEST_ATOM_REPORTED); + ASSERT_EQ(dimValue.value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(dimValue.value_tuple().dimensions_value(0).field(), + TEST_ATOM_REPORTED_STRING_FIELD_ID); + EXPECT_EQ(dimValue.value_tuple().dimensions_value(0).value_str(), "dimA123B"); + ASSERT_EQ(1, data.bucket_info_size()); + EXPECT_EQ(1, data.bucket_info(0).count()); + + data = countMetrics.data(2); + dimValue = data.dimensions_in_what(); + EXPECT_EQ(dimValue.field(), util::TEST_ATOM_REPORTED); + ASSERT_EQ(dimValue.value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(dimValue.value_tuple().dimensions_value(0).field(), + TEST_ATOM_REPORTED_STRING_FIELD_ID); + EXPECT_EQ(dimValue.value_tuple().dimensions_value(0).value_str(), "dimC"); + ASSERT_EQ(1, data.bucket_info_size()); + EXPECT_EQ(3, data.bucket_info(0).count()); +} + +TEST(StringReplaceE2eTest, TestPushedWhat) { + StatsdConfig config = CreateStatsdConfig(); + + *config.add_atom_matcher() = + CreateSimpleAtomMatcher("TestAtomMatcher", util::TEST_ATOM_REPORTED); + + FieldValueMatcher* fvm = config.mutable_atom_matcher(0) + ->mutable_simple_atom_matcher() + ->add_field_value_matcher(); + fvm->set_field(TEST_ATOM_REPORTED_STRING_FIELD_ID); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + *config.add_gauge_metric() = createGaugeMetric( + "TestAtomGaugeMetric", config.atom_matcher(0).id() /* what */, + GaugeMetric::FIRST_N_SAMPLES, nullopt /* condition */, nullopt /* triggerEvent */); + + // Initialize StatsLogProcessor. + const uint64_t bucketStartTimeNs = 10000000000; // 0:10 + const uint64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000LL; + const int uid = 12345; + const int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor( + bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap()); + + std::vector<std::unique_ptr<LogEvent>> events; + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 20 * NS_PER_SEC, + "dimA" /* stringField */)); // 0:30 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 40 * NS_PER_SEC, + "dimA123" /* stringField */)); // 0:50 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 60 * NS_PER_SEC, + "dimA123B" /* stringField */)); // 1:10 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 80 * NS_PER_SEC, + "dimC0" /* stringField */)); // 1:20 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 90 * NS_PER_SEC, + "dimC00000" /* stringField */)); // 1:30 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 100 * NS_PER_SEC, + "dimC" /* stringField */)); // 1:40 + + // Send log events to StatsLogProcessor. + for (auto& event : events) { + processor->OnLogEvent(event.get()); + } + + // Check dump report. + vector<uint8_t> buffer; + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP, + FAST, &buffer); + ASSERT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + backfillAggregatedAtoms(&reports); + + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + EXPECT_TRUE(reports.reports(0).metrics(0).has_gauge_metrics()); + StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); + ASSERT_EQ(gaugeMetrics.data_size(), 1); + + auto data = gaugeMetrics.data(0); + ASSERT_EQ(1, data.bucket_info_size()); + + ASSERT_EQ(6, data.bucket_info(0).atom_size()); + EXPECT_EQ(data.bucket_info(0).atom(0).test_atom_reported().string_field(), "dimA"); + EXPECT_EQ(data.bucket_info(0).atom(1).test_atom_reported().string_field(), "dimA"); + EXPECT_EQ(data.bucket_info(0).atom(2).test_atom_reported().string_field(), "dimA123B"); + EXPECT_EQ(data.bucket_info(0).atom(3).test_atom_reported().string_field(), "dimC"); + EXPECT_EQ(data.bucket_info(0).atom(4).test_atom_reported().string_field(), "dimC"); + EXPECT_EQ(data.bucket_info(0).atom(5).test_atom_reported().string_field(), "dimC"); +} + +TEST(StringReplaceE2eTest, TestPulledDimension) { + StatsdConfig config = CreateStatsdConfig(); + + *config.add_atom_matcher() = + CreateSimpleAtomMatcher("SubsystemMatcher", util::SUBSYSTEM_SLEEP_STATE); + FieldValueMatcher* fvm = config.mutable_atom_matcher(0) + ->mutable_simple_atom_matcher() + ->add_field_value_matcher(); + fvm->set_field(SUBSYSTEM_SLEEP_STATE_SUBSYSTEM_NAME_FIELD_ID); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + stringReplacer->set_replacement(""); + + *config.add_gauge_metric() = createGaugeMetric( + "SubsystemGaugeMetric", config.atom_matcher(0).id() /* what */, + GaugeMetric::RANDOM_ONE_SAMPLE, nullopt /* condition */, nullopt /* triggerEvent */); + *config.mutable_gauge_metric(0)->mutable_dimensions_in_what() = + CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */}); + + int64_t baseTimeNs = getElapsedRealtimeNs(); + int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; + int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000; + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey, + SharedRefBase::make<FakeSubsystemSleepCallback>(), + util::SUBSYSTEM_SLEEP_STATE); + processor->mPullerManager->ForceClearPullerCache(); + + // Pulling alarm arrives on time and reset the sequential pulling alarm. + processor->informPullAlarmFired(baseTimeNs + 2 * bucketSizeNs + 1); + + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + 3 * bucketSizeNs + 10, false, true, + ADB_DUMP, FAST, &buffer); + EXPECT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + backfillAggregatedAtoms(&reports); + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); + ASSERT_EQ(gaugeMetrics.data_size(), 1); + + auto data = gaugeMetrics.data(0); + EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field()); + ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); + EXPECT_EQ(SUBSYSTEM_SLEEP_STATE_SUBSYSTEM_NAME_FIELD_ID, + data.dimensions_in_what().value_tuple().dimensions_value(0).field()); + + // Trailing numbers are trimmed from the dimension: subsystem_name_# --> subsystem_name_ + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), + "subsystem_name_"); +} + +TEST(StringReplaceE2eTest, TestPulledWhat) { + StatsdConfig config = CreateStatsdConfig(); + + *config.add_atom_matcher() = + CreateSimpleAtomMatcher("SubsystemMatcher", util::SUBSYSTEM_SLEEP_STATE); + FieldValueMatcher* fvm = config.mutable_atom_matcher(0) + ->mutable_simple_atom_matcher() + ->add_field_value_matcher(); + fvm->set_field(SUBSYSTEM_SLEEP_STATE_SUBNAME_FIELD_ID); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"(foo)"); + stringReplacer->set_replacement("bar"); + + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); + + *config.add_predicate() = CreateScreenIsOffPredicate(); + + *config.add_gauge_metric() = + createGaugeMetric("SubsystemGaugeMetric", config.atom_matcher(0).id() /* what */, + GaugeMetric::RANDOM_ONE_SAMPLE, + config.predicate(0).id() /* condition */, nullopt /* triggerEvent */); + + int64_t baseTimeNs = getElapsedRealtimeNs(); + int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; + int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000; + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey, + SharedRefBase::make<FakeSubsystemSleepCallback>(), + util::SUBSYSTEM_SLEEP_STATE); + processor->mPullerManager->ForceClearPullerCache(); + + auto screenOffEvent = + CreateScreenStateChangedEvent(configAddedTimeNs + 55, android::view::DISPLAY_STATE_OFF); + processor->OnLogEvent(screenOffEvent.get()); + + // Pulling alarm arrives on time and reset the sequential pulling alarm. + processor->informPullAlarmFired(baseTimeNs + 2 * bucketSizeNs + 1); + + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + 3 * bucketSizeNs + 10, false, true, + ADB_DUMP, FAST, &buffer); + EXPECT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + backfillAggregatedAtoms(&reports); + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); + ASSERT_EQ(gaugeMetrics.data_size(), 1); + + auto data = gaugeMetrics.data(0); + ASSERT_EQ(2, data.bucket_info_size()); + + ASSERT_EQ(1, data.bucket_info(0).atom_size()); + EXPECT_EQ(data.bucket_info(0).atom(0).subsystem_sleep_state().subname(), + "subsystem_subname bar"); + + ASSERT_EQ(1, data.bucket_info(1).atom_size()); + EXPECT_EQ(data.bucket_info(1).atom(0).subsystem_sleep_state().subname(), + "subsystem_subname bar"); +} + +TEST(StringReplaceE2eTest, TestCondition) { + StatsdConfig config = CreateStatsdConfig(); + + AtomMatcher matcher = CreateStartScheduledJobAtomMatcher(); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(SCHEDULED_JOB_STATE_CHANGED_JOB_NAME_FIELD_ID); + fvm->set_eq_string("foo"); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"(com.google.)"); + stringReplacer->set_replacement(""); + *config.add_atom_matcher() = matcher; + matcher = CreateFinishScheduledJobAtomMatcher(); + fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(SCHEDULED_JOB_STATE_CHANGED_JOB_NAME_FIELD_ID); + fvm->set_eq_string("foo"); + stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"(com.google.)"); + stringReplacer->set_replacement(""); + *config.add_atom_matcher() = matcher; + + Predicate predicate = CreateScheduledJobPredicate(); + *config.add_predicate() = predicate; + + matcher = CreateSimpleAtomMatcher("TestAtomMatcher", util::TEST_ATOM_REPORTED); + *config.add_atom_matcher() = matcher; + + CountMetric* countMetric = config.add_count_metric(); + *countMetric = createCountMetric("TestCountMetric", matcher.id() /* what */, + predicate.id() /* condition */, {} /* states */); + + // Initialize StatsLogProcessor. + const uint64_t bucketStartTimeNs = 10000000000; // 0:10 + const uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(countMetric->bucket()) * 1000000LL; + const int uid = 12345; + const int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor( + bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap()); + + std::vector<std::unique_ptr<LogEvent>> events; + events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 20 * NS_PER_SEC, + {1001} /* uids */, {"App1"}, + "com.google.job1")); // 0:30 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 30 * NS_PER_SEC, + "str" /* stringField */)); // 0:40 + events.push_back(CreateStartScheduledJobEvent(bucketStartTimeNs + 40 * NS_PER_SEC, + {1002} /* uids */, {"App1"}, + "com.google.foo")); // 0:50 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 50 * NS_PER_SEC, + "str" /* stringField */)); // 1:00 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 60 * NS_PER_SEC, + "str" /* stringField */)); // 1:10 + events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + 70 * NS_PER_SEC, + {1001} /* uids */, {"App1"}, + "com.google.job1")); // 1:20 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 80 * NS_PER_SEC, + "str" /* stringField */)); // 1:30 + events.push_back(CreateFinishScheduledJobEvent(bucketStartTimeNs + 90 * NS_PER_SEC, + {1002} /* uids */, {"App1"}, + "com.google.foo")); // 1:40 + events.push_back(CreateTestAtomReportedEventStringDim(bucketStartTimeNs + 100 * NS_PER_SEC, + "str" /* stringField */)); // 1:50 + + // Send log events to StatsLogProcessor. + for (auto& event : events) { + processor->OnLogEvent(event.get()); + } + + // Check dump report. + vector<uint8_t> buffer; + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP, + FAST, &buffer); + ASSERT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + ASSERT_TRUE(reports.reports(0).metrics(0).has_count_metrics()); + StatsLogReport::CountMetricDataWrapper countMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); + ASSERT_EQ(1, countMetrics.data_size()); + + CountMetricData data = countMetrics.data(0); + ASSERT_EQ(1, data.bucket_info_size()); + EXPECT_EQ(3, data.bucket_info(0).count()); +} + +TEST(StringReplaceE2eTest, TestDurationMetric) { + StatsdConfig config = CreateStatsdConfig(); + + AtomMatcher matcher = CreateAcquireWakelockAtomMatcher(); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(ATTRIBUTION_CHAIN_FIELD_ID); + fvm->set_position(Position::FIRST); + fvm->mutable_matches_tuple()->add_field_value_matcher()->set_field(ATTRIBUTION_TAG_FIELD_ID); + StringReplacer* stringReplacer = + fvm->mutable_matches_tuple()->mutable_field_value_matcher(0)->mutable_replace_string(); + stringReplacer->set_regex(R"([0-9]+)"); + stringReplacer->set_replacement("#"); + *config.add_atom_matcher() = matcher; + + matcher = CreateReleaseWakelockAtomMatcher(); + fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(ATTRIBUTION_CHAIN_FIELD_ID); + fvm->set_position(Position::FIRST); + fvm->mutable_matches_tuple()->add_field_value_matcher()->set_field(ATTRIBUTION_TAG_FIELD_ID); + stringReplacer = + fvm->mutable_matches_tuple()->mutable_field_value_matcher(0)->mutable_replace_string(); + stringReplacer->set_regex(R"([0-9]+)"); + stringReplacer->set_replacement("#"); + *config.add_atom_matcher() = matcher; + + matcher = CreateMoveToBackgroundAtomMatcher(); + fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(ACTIVITY_FOREGROUND_STATE_CHANGED_PKG_NAME_FIELD_ID); + stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([0-9]+)"); + stringReplacer->set_replacement("#"); + *config.add_atom_matcher() = matcher; + + matcher = CreateMoveToForegroundAtomMatcher(); + fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(ACTIVITY_FOREGROUND_STATE_CHANGED_PKG_NAME_FIELD_ID); + stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"([0-9]+)"); + stringReplacer->set_replacement("#"); + *config.add_atom_matcher() = matcher; + + Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate(); + // The predicate is dimensioning by first attribution node by uid and tag. + *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = + CreateAttributionUidAndTagDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + *config.add_predicate() = holdingWakelockPredicate; + + Predicate isInBackgroundPredicate = CreateIsInBackgroundPredicate(); + *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = + CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, + {ACTIVITY_FOREGROUND_STATE_CHANGED_UID_FIELD_ID, + ACTIVITY_FOREGROUND_STATE_CHANGED_PKG_NAME_FIELD_ID}); + *config.add_predicate() = isInBackgroundPredicate; + + DurationMetric durationMetric = + createDurationMetric("WakelockDuration", holdingWakelockPredicate.id() /* what */, + isInBackgroundPredicate.id() /* condition */, {} /* states */); + *durationMetric.mutable_dimensions_in_what() = + CreateAttributionUidAndTagDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + durationMetric.set_bucket(FIVE_MINUTES); + *config.add_duration_metric() = durationMetric; + + // Links between wakelock state atom and condition of app is in background. + MetricConditionLink* link = durationMetric.add_links(); + link->set_condition(isInBackgroundPredicate.id()); + *link->mutable_fields_in_what() = + CreateAttributionUidAndTagDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + *link->mutable_fields_in_condition() = + CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, + {ACTIVITY_FOREGROUND_STATE_CHANGED_UID_FIELD_ID, + ACTIVITY_FOREGROUND_STATE_CHANGED_PKG_NAME_FIELD_ID}); + + // Initialize StatsLogProcessor. + const uint64_t bucketStartTimeNs = 10000000000; // 0:10 + const uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(durationMetric.bucket()) * 1000000LL; + const int uid = 12345; + const int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<StatsLogProcessor> processor = CreateStatsLogProcessor( + bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap()); + + int appUid = 123; + std::vector<int> attributionUids1 = {appUid}; + std::vector<string> attributionTags1 = {"App1"}; + std::vector<string> attributionTags2 = {"App2"}; + + std::vector<std::unique_ptr<LogEvent>> events; + events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + 10 * NS_PER_SEC, + attributionUids1, attributionTags1, + "wl1")); // 0:10 + events.push_back(CreateActivityForegroundStateChangedEvent( + bucketStartTimeNs + 22 * NS_PER_SEC, appUid, "App1", "class_name", + ActivityForegroundStateChanged::BACKGROUND)); // 0:22 + events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + 60 * NS_PER_SEC, + attributionUids1, attributionTags1, + "wl1")); // 1:00 + events.push_back(CreateActivityForegroundStateChangedEvent( + bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC, appUid, "App1", "class_name", + ActivityForegroundStateChanged::FOREGROUND)); // 3:15 + events.push_back(CreateAcquireWakelockEvent(bucketStartTimeNs + (3 * 60 + 20) * NS_PER_SEC, + attributionUids1, attributionTags2, + "wl2")); // 3:20 + events.push_back(CreateActivityForegroundStateChangedEvent( + bucketStartTimeNs + (3 * 60 + 30) * NS_PER_SEC, appUid, "App1", "class_name", + ActivityForegroundStateChanged::BACKGROUND)); // 3:30 + events.push_back(CreateActivityForegroundStateChangedEvent( + bucketStartTimeNs + (3 * 60 + 40) * NS_PER_SEC, appUid, "App2", "class_name", + ActivityForegroundStateChanged::FOREGROUND)); // 3:40 + events.push_back(CreateReleaseWakelockEvent(bucketStartTimeNs + (3 * 60 + 50) * NS_PER_SEC, + attributionUids1, attributionTags2, + "wl2")); // 3:50 + + // Send log events to StatsLogProcessor. + for (auto& event : events) { + processor->OnLogEvent(event.get()); + } + + vector<uint8_t> buffer; + ConfigMetricsReportList reports; + processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP, + FAST, &buffer); + + ASSERT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(1, reports.reports(0).metrics_size()); + ASSERT_TRUE(reports.reports(0).metrics(0).has_duration_metrics()); + StatsLogReport::DurationMetricDataWrapper durationMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(), + &durationMetrics); + ASSERT_EQ(1, durationMetrics.data_size()); + + DurationMetricData data = durationMetrics.data(0); + // Validate dimension value. + ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), util::WAKELOCK_STATE_CHANGED, + appUid, "App#"); + // Validate bucket info. + ASSERT_EQ(1, data.bucket_info_size()); + + auto bucketInfo = data.bucket_info(0); + EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos()); + EXPECT_EQ(48 * NS_PER_SEC, bucketInfo.duration_nanos()); +} + +TEST(StringReplaceE2eTest, TestMultipleMatchersForAtom) { + StatsdConfig config = CreateStatsdConfig(); + + { + AtomMatcher matcher = CreateSimpleAtomMatcher("Matcher1", util::SUBSYSTEM_SLEEP_STATE); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(SUBSYSTEM_SLEEP_STATE_SUBSYSTEM_NAME_FIELD_ID); + fvm->set_eq_string("subsystem_name_1"); + fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(SUBSYSTEM_SLEEP_STATE_SUBNAME_FIELD_ID); + fvm->set_eq_string("subsystem_subname bar"); + StringReplacer* stringReplacer = fvm->mutable_replace_string(); + stringReplacer->set_regex(R"(foo)"); + stringReplacer->set_replacement("bar"); + *config.add_atom_matcher() = matcher; + + *config.add_value_metric() = + createValueMetric("Value1", matcher, SUBSYSTEM_SLEEP_STATE_TIME_MILLIS_FIELD_ID, + nullopt /* condition */, {} /* states */); + } + { + AtomMatcher matcher = CreateSimpleAtomMatcher("Matcher2", util::SUBSYSTEM_SLEEP_STATE); + FieldValueMatcher* fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(SUBSYSTEM_SLEEP_STATE_SUBSYSTEM_NAME_FIELD_ID); + fvm->set_eq_string("subsystem_name_2"); + fvm = matcher.mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(SUBSYSTEM_SLEEP_STATE_SUBNAME_FIELD_ID); + fvm->set_eq_string("subsystem_subname foo"); + *config.add_atom_matcher() = matcher; + + *config.add_value_metric() = + createValueMetric("Value2", matcher, SUBSYSTEM_SLEEP_STATE_TIME_MILLIS_FIELD_ID, + nullopt /* condition */, {} /* states */); + } + + int64_t baseTimeNs = getElapsedRealtimeNs(); + int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; + int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000; + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey, + SharedRefBase::make<FakeSubsystemSleepCallback>(), + util::SUBSYSTEM_SLEEP_STATE); + processor->mPullerManager->ForceClearPullerCache(); + + // Pulling alarm arrives on time and reset the sequential pulling alarm. + processor->informPullAlarmFired(baseTimeNs + 2 * bucketSizeNs + 1); + + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, configAddedTimeNs + 3 * bucketSizeNs + 10, false, true, + ADB_DUMP, FAST, &buffer); + EXPECT_GT(buffer.size(), 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + backfillDimensionPath(&reports); + backfillStringInReport(&reports); + backfillStartEndTimestamp(&reports); + backfillAggregatedAtoms(&reports); + ASSERT_EQ(1, reports.reports_size()); + ASSERT_EQ(2, reports.reports(0).metrics_size()); + + { + StatsLogReport::ValueMetricDataWrapper valueMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), + &valueMetrics); + ASSERT_EQ(valueMetrics.data_size(), 1); + + ValueMetricData data = valueMetrics.data(0); + ASSERT_EQ(data.bucket_info_size(), 1); + ASSERT_EQ(data.bucket_info(0).values_size(), 1); + } + { + StatsLogReport::ValueMetricDataWrapper valueMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(1).value_metrics(), + &valueMetrics); + ASSERT_EQ(valueMetrics.data_size(), 1); + + ValueMetricData data = valueMetrics.data(0); + ASSERT_EQ(data.bucket_info_size(), 1); + ASSERT_EQ(data.bucket_info(0).values_size(), 1); + } +} + +} // namespace statsd +} // namespace os +} // namespace android +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif diff --git a/statsd/tests/guardrail/StatsdStats_test.cpp b/statsd/tests/guardrail/StatsdStats_test.cpp index 6e61b620..1d56caaf 100644 --- a/statsd/tests/guardrail/StatsdStats_test.cpp +++ b/statsd/tests/guardrail/StatsdStats_test.cpp @@ -750,6 +750,16 @@ TEST(StatsdStatsTest, TestAtomDroppedStats) { EXPECT_FALSE(nonPlatformPushedAtomStats.has_skip_count()); } +TEST(StatsdStatsTest, TestQueueStats) { + StatsdStats stats; + + stats.noteEventQueueSize(100, 1000); + StatsdStatsReport report = getStatsdStatsReport(stats, /* reset stats */ true); + + ASSERT_EQ(100, report.event_queue_stats().max_size_observed()); + ASSERT_EQ(1000, report.event_queue_stats().max_size_observed_elapsed_nanos()); +} + TEST(StatsdStatsTest, TestAtomLoggedAndDroppedStats) { StatsdStats stats; diff --git a/statsd/tests/indexed_priority_queue_test.cpp b/statsd/tests/indexed_priority_queue_test.cpp index 3a654565..1d365e8b 100644 --- a/statsd/tests/indexed_priority_queue_test.cpp +++ b/statsd/tests/indexed_priority_queue_test.cpp @@ -30,7 +30,7 @@ struct AATest : public RefBase { const std::string b; struct Smaller { - bool operator()(const sp<const AATest> a, const sp<const AATest> b) const { + bool operator()(const sp<const AATest>& a, const sp<const AATest>& b) const { return (a->val < b->val); } }; diff --git a/statsd/tests/log_event/LogEventQueue_test.cpp b/statsd/tests/log_event/LogEventQueue_test.cpp index a15f95be..acc9c5d5 100644 --- a/statsd/tests/log_event/LogEventQueue_test.cpp +++ b/statsd/tests/log_event/LogEventQueue_test.cpp @@ -20,6 +20,7 @@ #include <thread> +#include "socket/StatsSocketListener.h" #include "stats_event.h" #include "tests/statsd_test_util.h" @@ -34,37 +35,43 @@ using std::unique_ptr; namespace { -std::unique_ptr<LogEvent> makeLogEvent(uint64_t timestampNs) { +AStatsEvent* makeStatsEvent(uint64_t timestampNs) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, 10); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); + AStatsEvent_build(statsEvent); + return statsEvent; +} +std::unique_ptr<LogEvent> makeLogEvent(uint64_t timestampNs) { + AStatsEvent* statsEvent = makeStatsEvent(timestampNs); std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0); parseStatsEventToLogEvent(statsEvent, logEvent.get()); + EXPECT_EQ(logEvent->GetElapsedTimestampNs(), timestampNs); return logEvent; } -} // anonymous namespace +} // anonymous namespace #ifdef __ANDROID__ TEST(LogEventQueue_test, TestGoodConsumer) { LogEventQueue queue(50); - int64_t timeBaseNs = 100; - std::thread writer([&queue, timeBaseNs] { + int64_t eventTimeNs = 100; + std::thread writer([&queue, eventTimeNs] { + LogEventQueue::Result result; for (int i = 0; i < 100; i++) { - int64_t oldestEventNs; - bool success = queue.push(makeLogEvent(timeBaseNs + i * 1000), &oldestEventNs); - EXPECT_TRUE(success); + result = queue.push(makeLogEvent(eventTimeNs + i * 1000)); + EXPECT_TRUE(result.success); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } }); - std::thread reader([&queue, timeBaseNs] { + std::thread reader([&queue, eventTimeNs] { for (int i = 0; i < 100; i++) { auto event = queue.waitPop(); EXPECT_TRUE(event != nullptr); // All events are in right order. - EXPECT_EQ(timeBaseNs + i * 1000, event->GetElapsedTimestampNs()); + EXPECT_EQ(eventTimeNs + i * 1000, event->GetElapsedTimestampNs()); } }); @@ -74,13 +81,15 @@ TEST(LogEventQueue_test, TestGoodConsumer) { TEST(LogEventQueue_test, TestSlowConsumer) { LogEventQueue queue(50); - int64_t timeBaseNs = 100; - std::thread writer([&queue, timeBaseNs] { + int64_t eventTimeNs = 100; + std::thread writer([&queue, eventTimeNs] { int failure_count = 0; - int64_t oldestEventNs; + LogEventQueue::Result result; for (int i = 0; i < 100; i++) { - bool success = queue.push(makeLogEvent(timeBaseNs + i * 1000), &oldestEventNs); - if (!success) failure_count++; + result = queue.push(makeLogEvent(eventTimeNs + i * 1000)); + if (!result.success) { + failure_count++; + } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -89,16 +98,16 @@ TEST(LogEventQueue_test, TestSlowConsumer) { // There will be at least 45 events lost due to overflow. EXPECT_TRUE(failure_count >= 45); // The oldest event must be at least the 6th event. - EXPECT_TRUE(oldestEventNs <= (100 + 5 * 1000)); + EXPECT_TRUE(result.oldestTimestampNs <= (100 + 5 * 1000)); }); - std::thread reader([&queue, timeBaseNs] { + std::thread reader([&queue, eventTimeNs] { // The consumer quickly processed 5 events, then it got stuck (not reading anymore). for (int i = 0; i < 5; i++) { auto event = queue.waitPop(); EXPECT_TRUE(event != nullptr); // All events are in right order. - EXPECT_EQ(timeBaseNs + i * 1000, event->GetElapsedTimestampNs()); + EXPECT_EQ(eventTimeNs + i * 1000, event->GetElapsedTimestampNs()); } }); @@ -106,6 +115,87 @@ TEST(LogEventQueue_test, TestSlowConsumer) { writer.join(); } +TEST(LogEventQueue_test, TestQueueMaxSize) { + StatsdStats::getInstance().reset(); + + std::shared_ptr<LogEventQueue> queue(std::make_shared<LogEventQueue>(50)); + std::shared_ptr<LogEventFilter> filter(std::make_shared<LogEventFilter>()); + filter->setFilteringEnabled(false); + + int64_t eventTimeNs = 100; + int64_t oldestEventNs = 0; + int32_t newSize = 0; + for (int i = 0; i < 30; i++, eventTimeNs++) { + auto statsEvent = makeStatsEvent(eventTimeNs); + size_t bufferSize; + const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize); + StatsSocketListener::processMessage(buffer, bufferSize, 0, 0, queue, filter); + AStatsEvent_release(statsEvent); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, i + 1); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, eventTimeNs); + } + + const int32_t lastMaxSizeObserved = StatsdStats::getInstance().mEventQueueMaxSizeObserved; + const int64_t lastMaxSizeElapsedNanos = + StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos; + + // consumer reads the entire queue + int64_t nextEventTs = 100; + for (int i = 0; i < 30; i++, nextEventTs++) { + auto event = queue->waitPop(); + EXPECT_TRUE(event != nullptr); + // All events are in right order. + EXPECT_EQ(nextEventTs, event->GetElapsedTimestampNs()); + } + + // the expectation after queue drained entirely the max count & ts do not update for + // smaller values + { + auto statsEvent = makeStatsEvent(eventTimeNs); + size_t bufferSize; + const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize); + StatsSocketListener::processMessage(buffer, bufferSize, 0, 0, queue, filter); + AStatsEvent_release(statsEvent); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, lastMaxSizeObserved); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, + lastMaxSizeElapsedNanos); + eventTimeNs++; + } + + for (int i = 0; i < 1; i++, nextEventTs++) { + auto event = queue->waitPop(); + EXPECT_TRUE(event != nullptr); + // All events are in right order. + EXPECT_EQ(nextEventTs, event->GetElapsedTimestampNs()); + } + + // the expectation after queue drained entirely the max count & ts do update for + // bigger values + // fill up to the the previous max values observed - stats are not changed + for (int i = 0; i < lastMaxSizeObserved; i++, eventTimeNs++) { + auto statsEvent = makeStatsEvent(eventTimeNs); + size_t bufferSize; + const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize); + StatsSocketListener::processMessage(buffer, bufferSize, 0, 0, queue, filter); + AStatsEvent_release(statsEvent); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, lastMaxSizeObserved); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, + lastMaxSizeElapsedNanos); + } + + // add extra elements to update the stats + for (int i = 0; i < 10; i++, eventTimeNs++) { + auto statsEvent = makeStatsEvent(eventTimeNs); + size_t bufferSize; + const uint8_t* buffer = AStatsEvent_getBuffer(statsEvent, &bufferSize); + StatsSocketListener::processMessage(buffer, bufferSize, 0, 0, queue, filter); + AStatsEvent_release(statsEvent); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObserved, + lastMaxSizeObserved + i + 1); + EXPECT_EQ(StatsdStats::getInstance().mEventQueueMaxSizeObservedElapsedNanos, eventTimeNs); + } +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/statsd/tests/metrics/metrics_test_helper.h b/statsd/tests/metrics/metrics_test_helper.h index 39232c19..d7501496 100644 --- a/statsd/tests/metrics/metrics_test_helper.h +++ b/statsd/tests/metrics/metrics_test_helper.h @@ -34,18 +34,18 @@ public: class MockStatsPullerManager : public StatsPullerManager { public: MOCK_METHOD5(RegisterReceiver, - void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver, + void(int tagId, const ConfigKey& key, const wp<PullDataReceiver>& receiver, int64_t nextPulltimeNs, int64_t intervalNs)); MOCK_METHOD3(UnRegisterReceiver, - void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver)); - MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key, const int64_t eventTimeNs, + void(int tagId, const ConfigKey& key, const wp<PullDataReceiver>& receiver)); + MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key, int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data)); MOCK_METHOD4(Pull, bool(const int pullCode, const vector<int32_t>& uids, const int64_t eventTimeNs, vector<std::shared_ptr<LogEvent>>* data)); MOCK_METHOD2(RegisterPullUidProvider, - void(const ConfigKey& configKey, wp<PullUidProvider> provider)); + void(const ConfigKey& configKey, const wp<PullUidProvider>& provider)); MOCK_METHOD2(UnregisterPullUidProvider, - void(const ConfigKey& configKey, wp<PullUidProvider> provider)); + void(const ConfigKey& configKey, const wp<PullUidProvider>& provider)); }; HashableDimensionKey getMockedDimensionKey(int tagId, int key, std::string value); @@ -55,7 +55,7 @@ HashableDimensionKey getMockedDimensionKeyLongValue(int tagId, int key, int64_t MetricDimensionKey getMockedStateDimensionKey(int tagId, int key, int64_t value); // Utils to build FieldMatcher proto for simple one-depth atoms. -void buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum, FieldMatcher* matcher); +void buildSimpleAtomFieldMatcher(const int tagId, int atomFieldNum, FieldMatcher* matcher); void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher); } // namespace statsd diff --git a/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp index ee3e22f7..b32d5d31 100644 --- a/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp +++ b/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp @@ -169,7 +169,7 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) { EXPECT_TRUE(initConfig(config)); vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); - vector<bool> cycleTracker(1, false); + vector<uint8_t> cycleTracker(1, false); unordered_map<int64_t, int> newAtomMatchingTrackerMap; newAtomMatchingTrackerMap[matcherId] = 0; EXPECT_EQ(determineMatcherUpdateStatus(config, 0, oldAtomMatchingTrackerMap, @@ -194,7 +194,7 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) { *newConfig.add_atom_matcher() = newMatcher; vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); - vector<bool> cycleTracker(1, false); + vector<uint8_t> cycleTracker(1, false); unordered_map<int64_t, int> newAtomMatchingTrackerMap; newAtomMatchingTrackerMap[matcherId] = 0; EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap, @@ -219,7 +219,7 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherNew) { *newConfig.add_atom_matcher() = newMatcher; vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN); - vector<bool> cycleTracker(1, false); + vector<uint8_t> cycleTracker(1, false); unordered_map<int64_t, int> newAtomMatchingTrackerMap; newAtomMatchingTrackerMap[matcherId] = 0; EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap, @@ -261,7 +261,7 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) { newAtomMatchingTrackerMap[matcher1Id] = 2; vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); - vector<bool> cycleTracker(3, false); + vector<uint8_t> cycleTracker(3, false); // Only update the combination. It should recurse the two child matchers and preserve all 3. EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newAtomMatchingTrackerMap, @@ -306,7 +306,7 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) { newAtomMatchingTrackerMap[matcher1Id] = 2; vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); - vector<bool> cycleTracker(3, false); + vector<uint8_t> cycleTracker(3, false); // Only update the combination. The simple matchers should not be evaluated. EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newAtomMatchingTrackerMap, @@ -351,7 +351,7 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) { newAtomMatchingTrackerMap[matcher1Id] = 2; vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN); - vector<bool> cycleTracker(3, false); + vector<uint8_t> cycleTracker(3, false); // Only update the combination. EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newAtomMatchingTrackerMap, @@ -475,19 +475,13 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) { EXPECT_NE(oldAtomMatchingTrackers[oldAtomMatchingTrackerMap.at(combination2Id)], newAtomMatchingTrackers[newAtomMatchingTrackerMap.at(combination2Id)]); - // Validation, make sure the matchers have the proper ids/indices. Could do more checks here. + // Validation, make sure the matchers have the proper ids. Could do more checks here. EXPECT_EQ(newAtomMatchingTrackers[0]->getId(), combination3Id); - EXPECT_EQ(newAtomMatchingTrackers[0]->mIndex, 0); EXPECT_EQ(newAtomMatchingTrackers[1]->getId(), simple2Id); - EXPECT_EQ(newAtomMatchingTrackers[1]->mIndex, 1); EXPECT_EQ(newAtomMatchingTrackers[2]->getId(), combination2Id); - EXPECT_EQ(newAtomMatchingTrackers[2]->mIndex, 2); EXPECT_EQ(newAtomMatchingTrackers[3]->getId(), simple1Id); - EXPECT_EQ(newAtomMatchingTrackers[3]->mIndex, 3); EXPECT_EQ(newAtomMatchingTrackers[4]->getId(), simple4Id); - EXPECT_EQ(newAtomMatchingTrackers[4]->mIndex, 4); EXPECT_EQ(newAtomMatchingTrackers[5]->getId(), combination1Id); - EXPECT_EQ(newAtomMatchingTrackers[5]->mIndex, 5); // Verify child indices of Combination Matchers are correct. CombinationAtomMatchingTracker* combinationTracker1 = @@ -531,7 +525,7 @@ TEST_F(ConfigUpdateTest, TestSimpleConditionPreserve) { set<int64_t> replacedMatchers; vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN); - vector<bool> cycleTracker(1, false); + vector<uint8_t> cycleTracker(1, false); unordered_map<int64_t, int> newConditionTrackerMap; newConditionTrackerMap[predicate.id()] = 0; EXPECT_EQ(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap, @@ -558,7 +552,7 @@ TEST_F(ConfigUpdateTest, TestSimpleConditionReplace) { set<int64_t> replacedMatchers; vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN); - vector<bool> cycleTracker(1, false); + vector<uint8_t> cycleTracker(1, false); unordered_map<int64_t, int> newConditionTrackerMap; newConditionTrackerMap[predicate.id()] = 0; EXPECT_EQ(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap, @@ -586,7 +580,7 @@ TEST_F(ConfigUpdateTest, TestSimpleConditionDepsChange) { replacedMatchers.insert(startMatcherId); vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN); - vector<bool> cycleTracker(1, false); + vector<uint8_t> cycleTracker(1, false); unordered_map<int64_t, int> newConditionTrackerMap; newConditionTrackerMap[predicate.id()] = 0; EXPECT_EQ(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap, @@ -630,7 +624,7 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionPreserve) { set<int64_t> replacedMatchers; vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN); - vector<bool> cycleTracker(3, false); + vector<uint8_t> cycleTracker(3, false); // Only update the combination. It should recurse the two child predicates and preserve all 3. EXPECT_EQ(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap, @@ -677,7 +671,7 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionReplace) { set<int64_t> replacedMatchers; vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN); - vector<bool> cycleTracker(3, false); + vector<uint8_t> cycleTracker(3, false); // Only update the combination. The simple conditions should not be evaluated. EXPECT_EQ(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap, @@ -723,7 +717,7 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) { set<int64_t> replacedMatchers; vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN); - vector<bool> cycleTracker(3, false); + vector<uint8_t> cycleTracker(3, false); // Only update the combination. Simple2 and combination1 must be evaluated. EXPECT_EQ(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap, @@ -815,7 +809,7 @@ TEST_F(ConfigUpdateTest, TestUpdateConditions) { vector<MatchingState> eventMatcherValues(6, MatchingState::kNotMatched); eventMatcherValues[1] = MatchingState::kMatched; vector<ConditionState> tmpConditionCache(6, ConditionState::kNotEvaluated); - vector<bool> conditionChangeCache(6, false); + vector<uint8_t> conditionChangeCache(6, false); oldConditionTrackers[0]->evaluateCondition(event, eventMatcherValues, oldConditionTrackers, tmpConditionCache, conditionChangeCache); EXPECT_EQ(tmpConditionCache[0], ConditionState::kFalse); @@ -2630,7 +2624,7 @@ TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) { vector<MatchingState> matchingStates(8, MatchingState::kNotMatched); matchingStates[2] = kMatched; vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated); - vector<bool> changedCache(5, false); + vector<uint8_t> changedCache(5, false); unique_ptr<LogEvent> event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid1}, {"tag"}, "wl1"); oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers, conditionCache, changedCache); @@ -2706,7 +2700,7 @@ TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) { newConditionTrackerMap), nullopt); } - vector<bool> cycleTracker(5, false); + vector<uint8_t> cycleTracker(5, false); fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated); for (int i = 0; i < newConditionTrackers.size(); i++) { EXPECT_EQ( diff --git a/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp index b402285f..21ddb26e 100644 --- a/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp +++ b/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp @@ -628,7 +628,7 @@ TEST_F(MetricsManagerUtilTest, TestEventMetricInvalidSamplingPercentage) { StringToId("Event"))); } -TEST_F(MetricsManagerUtilTest, TestEventMetricInvalidSamplingPercentage2) { +TEST_F(MetricsManagerUtilTest, TestEventMetricInvalidSamplingPercentageZero) { StatsdConfig config; EventMetric* metric = config.add_event_metric(); *metric = createEventMetric(/*name=*/"Event", /*what=*/StringToId("ScreenTurnedOn"), @@ -641,7 +641,7 @@ TEST_F(MetricsManagerUtilTest, TestEventMetricInvalidSamplingPercentage2) { StringToId("Event"))); } -TEST_F(MetricsManagerUtilTest, TestEventMetricValidSamplingPercentage2) { +TEST_F(MetricsManagerUtilTest, TestEventMetricValidSamplingPercentage) { StatsdConfig config; EventMetric* metric = config.add_event_metric(); *metric = createEventMetric(/*name=*/"Event", /*what=*/StringToId("ScreenTurnedOn"), @@ -652,6 +652,61 @@ TEST_F(MetricsManagerUtilTest, TestEventMetricValidSamplingPercentage2) { EXPECT_EQ(initConfig(config), nullopt); } +TEST_F(MetricsManagerUtilTest, TestGaugeMetricInvalidSamplingPercentage) { + StatsdConfig config; + GaugeMetric* metric = config.add_gauge_metric(); + *metric = createGaugeMetric(/*name=*/"Gauge", /*what=*/StringToId("ScreenTurnedOn"), + GaugeMetric::FIRST_N_SAMPLES, + /*condition=*/nullopt, /*triggerEvent=*/nullopt); + metric->set_sampling_percentage(101); + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + + EXPECT_EQ(initConfig(config), + InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, + StringToId("Gauge"))); +} + +TEST_F(MetricsManagerUtilTest, TestGaugeMetricInvalidSamplingPercentageZero) { + StatsdConfig config; + GaugeMetric* metric = config.add_gauge_metric(); + *metric = createGaugeMetric(/*name=*/"Gauge", /*what=*/StringToId("ScreenTurnedOn"), + GaugeMetric::FIRST_N_SAMPLES, + /*condition=*/nullopt, /*triggerEvent=*/nullopt); + metric->set_sampling_percentage(0); + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + + EXPECT_EQ(initConfig(config), + InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_INCORRECT_SAMPLING_PERCENTAGE, + StringToId("Gauge"))); +} + +TEST_F(MetricsManagerUtilTest, TestGaugeMetricValidSamplingPercentage) { + StatsdConfig config; + GaugeMetric* metric = config.add_gauge_metric(); + *metric = createGaugeMetric(/*name=*/"Gauge", /*what=*/StringToId("ScreenTurnedOn"), + GaugeMetric::FIRST_N_SAMPLES, + /*condition=*/nullopt, /*triggerEvent=*/nullopt); + metric->set_sampling_percentage(50); + *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); + + EXPECT_EQ(initConfig(config), nullopt); +} + +TEST_F(MetricsManagerUtilTest, TestPulledGaugeMetricWithSamplingPercentage) { + StatsdConfig config; + GaugeMetric* metric = config.add_gauge_metric(); + *metric = createGaugeMetric(/*name=*/"Gauge", /*what=*/StringToId("SubsystemSleep"), + GaugeMetric::FIRST_N_SAMPLES, + /*condition=*/nullopt, /*triggerEvent=*/nullopt); + metric->set_sampling_percentage(50); + *config.add_atom_matcher() = + CreateSimpleAtomMatcher("SubsystemSleep", util::SUBSYSTEM_SLEEP_STATE); + + EXPECT_EQ(initConfig(config), + InvalidConfigReason(INVALID_CONFIG_REASON_GAUGE_METRIC_PULLED_WITH_SAMPLING, + StringToId("Gauge"))); +} + TEST_F(MetricsManagerUtilTest, TestNumericValueMetricMissingIdOrWhat) { StatsdConfig config; int64_t metricId = 1; @@ -1174,14 +1229,13 @@ TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerInvalidMatcher) { // Matcher has no contents_case (simple/combination), so it is invalid. matcher.set_id(21); optional<InvalidConfigReason> invalidConfigReason; - EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap, invalidConfigReason), nullptr); + EXPECT_EQ(createAtomMatchingTracker(matcher, uidMap, invalidConfigReason), nullptr); EXPECT_EQ(invalidConfigReason, createInvalidConfigReasonWithMatcher( INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE, matcher.id())); } TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerSimple) { - int index = 1; int64_t id = 123; sp<UidMap> uidMap = new UidMap(); AtomMatcher matcher; @@ -1195,20 +1249,18 @@ TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerSimple) { optional<InvalidConfigReason> invalidConfigReason; sp<AtomMatchingTracker> tracker = - createAtomMatchingTracker(matcher, index, uidMap, invalidConfigReason); + createAtomMatchingTracker(matcher, uidMap, invalidConfigReason); EXPECT_NE(tracker, nullptr); EXPECT_EQ(invalidConfigReason, nullopt); EXPECT_TRUE(tracker->mInitialized); EXPECT_EQ(tracker->getId(), id); - EXPECT_EQ(tracker->mIndex, index); const set<int>& atomIds = tracker->getAtomIds(); ASSERT_EQ(atomIds.size(), 1); EXPECT_EQ(atomIds.count(SCREEN_STATE_ATOM_ID), 1); } TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerCombination) { - int index = 1; int64_t id = 123; sp<UidMap> uidMap = new UidMap(); AtomMatcher matcher; @@ -1220,14 +1272,13 @@ TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerCombination) { optional<InvalidConfigReason> invalidConfigReason; sp<AtomMatchingTracker> tracker = - createAtomMatchingTracker(matcher, index, uidMap, invalidConfigReason); + createAtomMatchingTracker(matcher, uidMap, invalidConfigReason); EXPECT_NE(tracker, nullptr); EXPECT_EQ(invalidConfigReason, nullopt); // Combination matchers need to be initialized first. EXPECT_FALSE(tracker->mInitialized); EXPECT_EQ(tracker->getId(), id); - EXPECT_EQ(tracker->mIndex, index); const set<int>& atomIds = tracker->getAtomIds(); ASSERT_EQ(atomIds.size(), 0); } @@ -1934,6 +1985,313 @@ TEST_P(MetricsManagerUtilDimLimitTest, TestDimLimit) { EXPECT_EQ(kllProducer->mDimensionHardLimit, actualLimit); } +TEST_F(MetricsManagerUtilTest, TestMissingValueMatcherAndStringReplacer) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(SCREEN_STATE_ATOM_ID); + matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_NO_VALUE_MATCHER_NOR_STRING_REPLACER); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestMatcherWithValueMatcherOnly) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(SCREEN_STATE_ATOM_ID); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(2 /*int_field*/); + fvm->set_eq_int(1); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_EQ(actualInvalidConfigReason, nullopt); +} + +TEST_F(MetricsManagerUtilTest, TestMatcherWithStringReplacerOnly) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(SCREEN_STATE_ATOM_ID); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(5 /*string_field*/); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement("#"); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_EQ(actualInvalidConfigReason, nullopt); +} + +TEST_F(MetricsManagerUtilTest, TestValueMatcherWithPositionAll) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(9 /*repeated_int_field*/); + fvm->set_position(Position::ALL); + fvm->set_eq_int(1); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestValueMatcherAndStringReplaceWithPositionAll) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(12 /*repeated_string_field*/); + fvm->set_position(Position::ALL); + fvm->set_eq_string("foo"); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestValueMatcherWithPositionAllNested) { + StatsdConfig config; + config.set_id(12345); + + // Match on attribution_node[ALL].uid = 1 + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(1 /*attribution_node*/); + fvm->set_position(Position::ALL); + fvm->mutable_matches_tuple()->add_field_value_matcher()->set_field(1 /* uid */); + fvm->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_int(1); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestValueMatcherAndStringReplaceWithPositionAllNested) { + StatsdConfig config; + config.set_id(12345); + + // Match on attribution_node[ALL].uid = 1 + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(1 /*attribution_node*/); + fvm->set_position(Position::ALL); + fvm->mutable_matches_tuple()->add_field_value_matcher()->set_field(2 /* tag */); + fvm->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("foo"); + fvm->mutable_matches_tuple() + ->mutable_field_value_matcher(0) + ->mutable_replace_string() + ->set_regex(R"([\d]+$)"); + fvm->mutable_matches_tuple() + ->mutable_field_value_matcher(0) + ->mutable_replace_string() + ->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_VALUE_MATCHER_WITH_POSITION_ALL); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestStringReplaceWithNoValueMatcherWithPositionAny) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(12 /*repeated_string_field*/); + fvm->set_position(Position::ANY); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_STRING_REPLACE_WITH_NO_VALUE_MATCHER_WITH_POSITION_ANY); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestStringReplaceWithNoValueMatcherWithPositionAnyNested) { + StatsdConfig config; + config.set_id(12345); + + // Match on attribution_node[ALL].uid = 1 + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(1 /*attribution_node*/); + fvm->set_position(Position::ANY); + fvm->mutable_matches_tuple()->add_field_value_matcher()->set_field(2 /* tag */); + fvm->mutable_matches_tuple() + ->mutable_field_value_matcher(0) + ->mutable_replace_string() + ->set_regex(R"([\d]+$)"); + fvm->mutable_matches_tuple() + ->mutable_field_value_matcher(0) + ->mutable_replace_string() + ->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_STRING_REPLACE_WITH_NO_VALUE_MATCHER_WITH_POSITION_ANY); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestStringReplaceWithValueMatcherWithPositionAny) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(12 /*repeated_string_field*/); + fvm->set_position(Position::ANY); + fvm->set_eq_string("bar"); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_EQ(actualInvalidConfigReason, nullopt); +} + +TEST_F(MetricsManagerUtilTest, TestStringReplaceWithValueMatcherWithPositionAnyNested) { + StatsdConfig config; + config.set_id(12345); + + // Match on attribution_node[ALL].uid = 1 + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(1 /*attribution_node*/); + fvm->set_position(Position::ANY); + fvm->mutable_matches_tuple()->add_field_value_matcher()->set_field(2 /* tag */); + fvm->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("bar"); + fvm->mutable_matches_tuple() + ->mutable_field_value_matcher(0) + ->mutable_replace_string() + ->set_regex(R"([\d]+$)"); + fvm->mutable_matches_tuple() + ->mutable_field_value_matcher(0) + ->mutable_replace_string() + ->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_EQ(actualInvalidConfigReason, nullopt); +} + +TEST_F(MetricsManagerUtilTest, TestStringReplaceWithPositionAllNested) { + StatsdConfig config; + config.set_id(12345); + + // Replace attribution_node[ALL].tag using "[\d]+$" -> "". + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(1 /*attribution_node*/); + fvm->set_position(Position::ALL); + fvm = fvm->mutable_matches_tuple()->add_field_value_matcher(); + fvm->set_field(2 /* tag */); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement(""); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_EQ(actualInvalidConfigReason, nullopt); +} + +TEST_F(MetricsManagerUtilTest, TestMatcherWithStringReplaceAndNonStringValueMatcher) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(2 /*int_field*/); + fvm->set_eq_int(1); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement("#"); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_INVALID_VALUE_MATCHER_WITH_STRING_REPLACE); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(111)); +} + +TEST_F(MetricsManagerUtilTest, TestCombinationMatcherWithStringReplace) { + StatsdConfig config; + config.set_id(12345); + + AtomMatcher* matcher = config.add_atom_matcher(); + matcher->set_id(111); + matcher->mutable_simple_atom_matcher()->set_atom_id(util::TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = matcher->mutable_simple_atom_matcher()->add_field_value_matcher(); + fvm->set_field(5 /*string_field*/); + fvm->mutable_replace_string()->set_regex(R"([\d]+$)"); + fvm->mutable_replace_string()->set_replacement("#"); + + matcher = config.add_atom_matcher(); + matcher->set_id(222); + matcher->mutable_combination()->set_operation(LogicalOperation::NOT); + matcher->mutable_combination()->add_matcher(111); + + optional<InvalidConfigReason> actualInvalidConfigReason = initConfig(config); + + ASSERT_NE(actualInvalidConfigReason, nullopt); + EXPECT_EQ(actualInvalidConfigReason->reason, + INVALID_CONFIG_REASON_MATCHER_COMBINATION_WITH_STRING_REPLACE); + EXPECT_THAT(actualInvalidConfigReason->matcherIds, ElementsAre(222)); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/statsd/tests/shell/ShellSubscriber_test.cpp b/statsd/tests/shell/ShellSubscriber_test.cpp index 04cc9ce5..4bd032ef 100644 --- a/statsd/tests/shell/ShellSubscriber_test.cpp +++ b/statsd/tests/shell/ShellSubscriber_test.cpp @@ -222,7 +222,7 @@ TestAtomReported createTestAtomReportedProto(const int32_t intFieldValue, TestAtomReported t; auto* attributionNode = t.add_attribution_node(); attributionNode->set_uid(1001); - attributionNode->set_tag("app1"); + attributionNode->set_tag("app"); // String transformation removes trailing digits. t.set_int_field(intFieldValue); t.set_long_field(0); t.set_float_field(0.0f); @@ -252,6 +252,15 @@ protected: ShellSubscription config; config.add_pushed()->set_atom_id(TEST_ATOM_REPORTED); + FieldValueMatcher* fvm = config.mutable_pushed(0)->add_field_value_matcher(); + fvm->set_field(1); // attribution_chain + fvm->set_position(Position::FIRST); + fvm = fvm->mutable_matches_tuple()->add_field_value_matcher(); + fvm->set_field(2); // tag field + fvm->mutable_replace_string()->set_regex( + R"([\d]+$)"); // match trailing digits, example "42" in "foo42". + fvm->mutable_replace_string()->set_replacement(""); + config.add_pushed()->set_atom_id(SCREEN_STATE_CHANGED); config.add_pushed()->set_atom_id(PHONE_SIGNAL_STRENGTH_CHANGED); configBytes = protoToBytes(config); @@ -364,7 +373,7 @@ TEST_F(ShellSubscriberCallbackTest, testAddSubscriptionExceedMax) { .Times(1) .RetiresOnSaturation(); - vector<bool> results(maxSubs, false); + vector<uint8_t> results(maxSubs, false); std::shared_ptr<MockStatsSubscriptionCallback> callbacks[maxSubs]; for (int i = 0; i < maxSubs; i++) { diff --git a/statsd/tests/statsd_test_util.cpp b/statsd/tests/statsd_test_util.cpp index d900f011..8e80a205 100644 --- a/statsd/tests/statsd_test_util.cpp +++ b/statsd/tests/statsd_test_util.cpp @@ -1079,6 +1079,18 @@ std::unique_ptr<LogEvent> CreateTestAtomReportedEventVariableRepeatedFields( repeatedBoolFieldLength, repeatedEnumField); } +std::unique_ptr<LogEvent> CreateTestAtomReportedEventWithPrimitives( + uint64_t timestampNs, int intField, long longField, float floatField, + const string& stringField, bool boolField, TestAtomReported::State enumField) { + return CreateTestAtomReportedEvent( + timestampNs, /* attributionUids */ {1001}, + /* attributionTags */ {"app1"}, intField, longField, floatField, stringField, boolField, + enumField, /* bytesField */ {}, + /* repeatedIntField */ {}, /* repeatedLongField */ {}, /* repeatedFloatField */ {}, + /* repeatedStringField */ {}, /* repeatedBoolField */ {}, + /* repeatedBoolFieldLength */ 0, /* repeatedEnumField */ {}); +} + std::unique_ptr<LogEvent> CreateTestAtomReportedEvent( uint64_t timestampNs, const vector<int>& attributionUids, const vector<string>& attributionTags, const int intField, const long longField, @@ -1160,14 +1172,15 @@ std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(uint64_t timestampNs, } std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent( - uint64_t timestampNs, const int uid, const ActivityForegroundStateChanged::State state) { + uint64_t timestampNs, const int uid, const string& pkgName, const string& className, + const ActivityForegroundStateChanged::State state) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, util::ACTIVITY_FOREGROUND_STATE_CHANGED); AStatsEvent_overwriteTimestamp(statsEvent, timestampNs); AStatsEvent_writeInt32(statsEvent, uid); - AStatsEvent_writeString(statsEvent, "pkg_name"); - AStatsEvent_writeString(statsEvent, "class_name"); + AStatsEvent_writeString(statsEvent, pkgName.c_str()); + AStatsEvent_writeString(statsEvent, className.c_str()); AStatsEvent_writeInt32(statsEvent, state); std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0); @@ -1176,12 +1189,12 @@ std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent( } std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid) { - return CreateActivityForegroundStateChangedEvent(timestampNs, uid, + return CreateActivityForegroundStateChangedEvent(timestampNs, uid, "pkg_name", "class_name", ActivityForegroundStateChanged::BACKGROUND); } std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid) { - return CreateActivityForegroundStateChangedEvent(timestampNs, uid, + return CreateActivityForegroundStateChangedEvent(timestampNs, uid, "pkg_name", "class_name", ActivityForegroundStateChanged::FOREGROUND); } @@ -1491,8 +1504,8 @@ sp<EventMatcherWizard> createEventMatcherWizard( } uint64_t matcherHash = 0x12345678; int64_t matcherId = 678; - return new EventMatcherWizard({new SimpleAtomMatchingTracker( - matcherId, matcherIndex, matcherHash, atomMatcher, uidMap)}); + return new EventMatcherWizard( + {new SimpleAtomMatchingTracker(matcherId, matcherHash, atomMatcher, uidMap)}); } StatsDimensionsValueParcel CreateAttributionUidDimensionsValueParcel(const int atomId, @@ -2155,7 +2168,7 @@ PackageInfo buildPackageInfo(const string& name, const int32_t uid, const int64_ vector<PackageInfo> buildPackageInfos( const vector<string>& names, const vector<int32_t>& uids, const vector<int64_t>& versions, const vector<string>& versionStrings, const vector<string>& installers, - const vector<vector<uint8_t>>& certHashes, const vector<bool>& deleted, + const vector<vector<uint8_t>>& certHashes, const vector<uint8_t>& deleted, const vector<uint32_t>& installerIndices, const bool hashStrings) { vector<PackageInfo> packageInfos; for (int i = 0; i < uids.size(); i++) { diff --git a/statsd/tests/statsd_test_util.h b/statsd/tests/statsd_test_util.h index 3303ba50..d2d10b23 100644 --- a/statsd/tests/statsd_test_util.h +++ b/statsd/tests/statsd_test_util.h @@ -334,31 +334,29 @@ FieldMatcher CreateAttributionUidAndOtherDimensions(const int atomId, const std::vector<Position>& positions, const std::vector<int>& fields); -EventMetric createEventMetric(const string& name, const int64_t what, - const optional<int64_t>& condition); +EventMetric createEventMetric(const string& name, int64_t what, const optional<int64_t>& condition); -CountMetric createCountMetric(const string& name, const int64_t what, - const optional<int64_t>& condition, const vector<int64_t>& states); +CountMetric createCountMetric(const string& name, int64_t what, const optional<int64_t>& condition, + const vector<int64_t>& states); -DurationMetric createDurationMetric(const string& name, const int64_t what, +DurationMetric createDurationMetric(const string& name, int64_t what, const optional<int64_t>& condition, const vector<int64_t>& states); -GaugeMetric createGaugeMetric(const string& name, const int64_t what, +GaugeMetric createGaugeMetric(const string& name, int64_t what, const GaugeMetric::SamplingType samplingType, const optional<int64_t>& condition, const optional<int64_t>& triggerEvent); -ValueMetric createValueMetric(const string& name, const AtomMatcher& what, const int valueField, +ValueMetric createValueMetric(const string& name, const AtomMatcher& what, int valueField, const optional<int64_t>& condition, const vector<int64_t>& states); -KllMetric createKllMetric(const string& name, const AtomMatcher& what, const int kllField, +KllMetric createKllMetric(const string& name, const AtomMatcher& what, int kllField, const optional<int64_t>& condition); -Alert createAlert(const string& name, const int64_t metricId, const int buckets, - const int64_t triggerSum); +Alert createAlert(const string& name, int64_t metricId, int buckets, const int64_t triggerSum); -Alarm createAlarm(const string& name, const int64_t offsetMillis, const int64_t periodMillis); +Alarm createAlarm(const string& name, int64_t offsetMillis, int64_t periodMillis); Subscription createSubscription(const string& name, const Subscription_RuleType type, const int64_t ruleId); @@ -477,11 +475,15 @@ std::unique_ptr<LogEvent> CreateBatteryStateChangedEvent(const uint64_t timestam // Create malformed log event for battery state change. std::unique_ptr<LogEvent> CreateMalformedBatteryStateChangedEvent(const uint64_t timestampNs); +std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent( + uint64_t timestampNs, const int uid, const string& pkgName, const string& className, + const ActivityForegroundStateChanged::State state); + // Create log event for app moving to background. -std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, const int uid); +std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(uint64_t timestampNs, int uid); // Create log event for app moving to foreground. -std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(uint64_t timestampNs, const int uid); +std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(uint64_t timestampNs, int uid); // Create log event when the app sync starts. std::unique_ptr<LogEvent> CreateSyncStartEvent(uint64_t timestampNs, const vector<int>& uids, @@ -492,10 +494,10 @@ std::unique_ptr<LogEvent> CreateSyncEndEvent(uint64_t timestampNs, const vector< const vector<string>& tags, const string& name); // Create log event when the app sync ends. -std::unique_ptr<LogEvent> CreateAppCrashEvent(uint64_t timestampNs, const int uid); +std::unique_ptr<LogEvent> CreateAppCrashEvent(uint64_t timestampNs, int uid); // Create log event for an app crash. -std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(uint64_t timestampNs, const int uid); +std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(uint64_t timestampNs, int uid); // Create log event for acquiring wakelock. std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(uint64_t timestampNs, const vector<int>& uids, @@ -528,7 +530,7 @@ std::unique_ptr<LogEvent> CreateOverlayStateChangedEvent(int64_t timestampNs, co const OverlayStateChanged::State state); std::unique_ptr<LogEvent> CreateAppStartOccurredEvent( - uint64_t timestampNs, const int uid, const string& pkg_name, + uint64_t timestampNs, int uid, const string& pkg_name, AppStartOccurred::TransitionType type, const string& activity_name, const string& calling_pkg_name, const bool is_instant_app, int64_t activity_start_msec); @@ -543,6 +545,10 @@ std::unique_ptr<LogEvent> CreateTestAtomReportedEventVariableRepeatedFields( const vector<string>& repeatedStringField, const bool* repeatedBoolField, const size_t repeatedBoolFieldLength, const vector<int>& repeatedEnumField); +std::unique_ptr<LogEvent> CreateTestAtomReportedEventWithPrimitives( + uint64_t timestampNs, int intField, long longField, float floatField, + const string& stringField, bool boolField, TestAtomReported::State enumField); + std::unique_ptr<LogEvent> CreateRestrictedLogEvent(int atomTag, int64_t timestampNs = 0); std::unique_ptr<LogEvent> CreateNonRestrictedLogEvent(int atomTag, int64_t timestampNs = 0); @@ -551,7 +557,7 @@ std::unique_ptr<LogEvent> CreatePhoneSignalStrengthChangedEvent( std::unique_ptr<LogEvent> CreateTestAtomReportedEvent( uint64_t timestampNs, const vector<int>& attributionUids, - const vector<string>& attributionTags, const int intField, const long longField, + const vector<string>& attributionTags, int intField, const long longField, const float floatField, const string& stringField, const bool boolField, const TestAtomReported::State enumField, const vector<uint8_t>& bytesField, const vector<int>& repeatedIntField, const vector<int64_t>& repeatedLongField, @@ -565,7 +571,7 @@ void fillStatsEventWithSampleValue(AStatsEvent* statsEvent, uint8_t typeId); // Create a statsd log event processor upon the start time in seconds, config and key. sp<StatsLogProcessor> CreateStatsLogProcessor( - const int64_t timeBaseNs, const int64_t currentTimeNs, const StatsdConfig& config, + const int64_t timeBaseNs, int64_t currentTimeNs, const StatsdConfig& config, const ConfigKey& key, const shared_ptr<IPullAtomCallback>& puller = nullptr, const int32_t atomTag = 0 /*for puller only*/, const sp<UidMap> = new UidMap(), const shared_ptr<LogEventFilter>& logEventFilter = std::make_shared<LogEventFilter>()); @@ -585,7 +591,7 @@ StatsDimensionsValueParcel CreateAttributionUidDimensionsValueParcel(const int a const int uid); void ValidateUidDimension(const DimensionsValue& value, int atomId, int uid); -void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId, +void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, int atomId, const int uid, const string& tag); void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid); void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid); @@ -712,8 +718,8 @@ void sortMetricDataByFirstDimensionLeafValue(const T& metricData, T* sortedMetri } template <typename T> -void backfillStartEndTimestampForFullBucket( - const int64_t timeBaseNs, const int64_t bucketSizeNs, T* bucket) { +void backfillStartEndTimestampForFullBucket(const int64_t timeBaseNs, int64_t bucketSizeNs, + T* bucket) { bucket->set_start_bucket_elapsed_nanos(timeBaseNs + bucketSizeNs * bucket->bucket_num()); bucket->set_end_bucket_elapsed_nanos( timeBaseNs + bucketSizeNs * bucket->bucket_num() + bucketSizeNs); @@ -735,7 +741,7 @@ void backfillStartEndTimestampForPartialBucket(const int64_t timeBaseNs, T* buck } template <typename T> -void backfillStartEndTimestampForMetrics(const int64_t timeBaseNs, const int64_t bucketSizeNs, +void backfillStartEndTimestampForMetrics(const int64_t timeBaseNs, int64_t bucketSizeNs, T* metrics) { for (int i = 0; i < metrics->data_size(); ++i) { auto data = metrics->mutable_data(i); @@ -790,10 +796,10 @@ void writeBootFlag(const std::string& flagName, const std::string& flagValue); PackageInfoSnapshot getPackageInfoSnapshot(const sp<UidMap> uidMap); -ApplicationInfo createApplicationInfo(const int32_t uid, const int64_t version, - const string& versionString, const string& package); +ApplicationInfo createApplicationInfo(int32_t uid, int64_t version, const string& versionString, + const string& package); -PackageInfo buildPackageInfo(const std::string& name, const int32_t uid, const int64_t version, +PackageInfo buildPackageInfo(const std::string& name, const int32_t uid, int64_t version, const std::string& versionString, const std::optional<std::string> installer, const std::vector<uint8_t>& certHash, const bool deleted, @@ -803,7 +809,7 @@ std::vector<PackageInfo> buildPackageInfos( const std::vector<string>& names, const std::vector<int32_t>& uids, const std::vector<int64_t>& versions, const std::vector<std::string>& versionStrings, const std::vector<std::string>& installers, - const std::vector<std::vector<uint8_t>>& certHashes, const std::vector<bool>& deleted, + const std::vector<std::vector<uint8_t>>& certHashes, const std::vector<uint8_t>& deleted, const std::vector<uint32_t>& installerIndices, const bool hashStrings); template <typename T> diff --git a/tests/Android.bp b/tests/Android.bp index e67a76c2..60bab5e3 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -29,6 +29,7 @@ java_test_host { "cts", "general-tests", "mts-statsd", + "mcts-statsd", ], libs: [ |