summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-02-02 22:49:33 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-02-02 22:49:33 +0000
commit64eead096a4af38f33357cf109225dac463788c6 (patch)
tree0832182584e6cef6347a0268e5cfea1aa7ee47ab
parent5c1c48fe8cd99076df016e78fece7d1a30cba376 (diff)
parentfe94a87a6437fe218c8e0dc58aa608ce197f2f68 (diff)
downloadStatsD-64eead096a4af38f33357cf109225dac463788c6.tar.gz
Snap for 9556825 from fe94a87a6437fe218c8e0dc58aa608ce197f2f68 to mainline-adservices-releaseaml_ads_331611190
Change-Id: Ibbe245821d0de8caf3f1ac3b6b9f3c9248240c55
-rw-r--r--apex/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java26
-rw-r--r--framework/Android.bp9
-rw-r--r--framework/test/unittests/AndroidTest.xml2
-rw-r--r--lib/libkll/Android.bp4
-rw-r--r--lib/libkll/encoding/Android.bp1
-rw-r--r--lib/libkll/proto/Android.bp1
-rw-r--r--lib/libstatspull/Android.bp7
-rw-r--r--lib/libstatspull/stats_pull_atom_callback.cpp121
-rw-r--r--lib/libstatssocket/Android.bp6
-rw-r--r--statsd/Android.bp47
-rw-r--r--statsd/src/FieldValue.cpp35
-rw-r--r--statsd/src/FieldValue.h5
-rw-r--r--statsd/src/HashableDimensionKey.cpp13
-rw-r--r--statsd/src/HashableDimensionKey.h3
-rw-r--r--statsd/src/StatsLogProcessor.h19
-rw-r--r--statsd/src/StatsService.h10
-rw-r--r--statsd/src/anomaly/AnomalyTracker.cpp8
-rw-r--r--statsd/src/anomaly/AnomalyTracker.h16
-rw-r--r--statsd/src/condition/CombinationConditionTracker.cpp59
-rw-r--r--statsd/src/condition/CombinationConditionTracker.h20
-rw-r--r--statsd/src/condition/ConditionTracker.h20
-rw-r--r--statsd/src/condition/SimpleConditionTracker.cpp19
-rw-r--r--statsd/src/condition/SimpleConditionTracker.h20
-rw-r--r--statsd/src/external/PullDataReceiver.h13
-rw-r--r--statsd/src/external/StatsPullerManager.cpp47
-rw-r--r--statsd/src/external/StatsPullerManager.h2
-rw-r--r--statsd/src/flags/FlagProvider.h3
-rw-r--r--statsd/src/guardrail/StatsdStats.cpp154
-rw-r--r--statsd/src/guardrail/StatsdStats.h73
-rw-r--r--statsd/src/guardrail/invalid_config_reason_enum.proto109
-rw-r--r--statsd/src/main.cpp3
-rw-r--r--statsd/src/matchers/AtomMatchingTracker.h27
-rw-r--r--statsd/src/matchers/CombinationAtomMatchingTracker.cpp43
-rw-r--r--statsd/src/matchers/CombinationAtomMatchingTracker.h14
-rw-r--r--statsd/src/matchers/SimpleAtomMatchingTracker.cpp22
-rw-r--r--statsd/src/matchers/SimpleAtomMatchingTracker.h15
-rw-r--r--statsd/src/metrics/CountMetricProducer.cpp42
-rw-r--r--statsd/src/metrics/CountMetricProducer.h2
-rw-r--r--statsd/src/metrics/DurationMetricProducer.cpp83
-rw-r--r--statsd/src/metrics/DurationMetricProducer.h2
-rw-r--r--statsd/src/metrics/EventMetricProducer.cpp42
-rw-r--r--statsd/src/metrics/EventMetricProducer.h2
-rw-r--r--statsd/src/metrics/GaugeMetricProducer.cpp62
-rw-r--r--statsd/src/metrics/GaugeMetricProducer.h13
-rw-r--r--statsd/src/metrics/KllMetricProducer.cpp2
-rw-r--r--statsd/src/metrics/KllMetricProducer.h1
-rw-r--r--statsd/src/metrics/MetricProducer.cpp40
-rw-r--r--statsd/src/metrics/MetricProducer.h29
-rw-r--r--statsd/src/metrics/MetricsManager.cpp41
-rw-r--r--statsd/src/metrics/MetricsManager.h39
-rw-r--r--statsd/src/metrics/NumericValueMetricProducer.cpp21
-rw-r--r--statsd/src/metrics/NumericValueMetricProducer.h12
-rw-r--r--statsd/src/metrics/ValueMetricProducer.cpp48
-rw-r--r--statsd/src/metrics/ValueMetricProducer.h12
-rw-r--r--statsd/src/metrics/parsing_utils/config_update_utils.cpp735
-rw-r--r--statsd/src/metrics/parsing_utils/config_update_utils.h181
-rw-r--r--statsd/src/metrics/parsing_utils/metrics_manager_util.cpp890
-rw-r--r--statsd/src/metrics/parsing_utils/metrics_manager_util.h165
-rw-r--r--statsd/src/stats_log.proto14
-rw-r--r--statsd/src/statsd_config.proto18
-rw-r--r--statsd/src/utils/ShardOffsetProvider.cpp33
-rw-r--r--statsd/src/utils/ShardOffsetProvider.h62
-rw-r--r--statsd/tests/ConfigManager_test.cpp4
-rw-r--r--statsd/tests/FieldValue_test.cpp244
-rw-r--r--statsd/tests/HashableDimensionKey_test.cpp35
-rw-r--r--statsd/tests/StatsLogProcessor_test.cpp5
-rw-r--r--statsd/tests/StatsService_test.cpp26
-rw-r--r--statsd/tests/e2e/Anomaly_count_e2e_test.cpp10
-rw-r--r--statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp37
-rw-r--r--statsd/tests/e2e/ConfigUpdate_e2e_test.cpp1
-rw-r--r--statsd/tests/e2e/CountMetric_e2e_test.cpp147
-rw-r--r--statsd/tests/e2e/DurationMetric_e2e_test.cpp100
-rw-r--r--statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp22
-rw-r--r--statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp87
-rw-r--r--statsd/tests/e2e/KllMetric_e2e_test.cpp175
-rw-r--r--statsd/tests/e2e/PartialBucket_e2e_test.cpp130
-rw-r--r--statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp73
-rw-r--r--statsd/tests/guardrail/StatsdStats_test.cpp119
-rw-r--r--statsd/tests/metrics/EventMetricProducer_test.cpp58
-rw-r--r--statsd/tests/metrics/GaugeMetricProducer_test.cpp116
-rw-r--r--statsd/tests/metrics/NumericValueMetricProducer_test.cpp392
-rw-r--r--statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp802
-rw-r--r--statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp1446
-rw-r--r--statsd/tests/statsd_test_util.cpp86
-rw-r--r--statsd/tests/statsd_test_util.h62
-rw-r--r--statsd/tools/localtools/Android.bp5
-rw-r--r--statsd/tools/localtools/TEST_MAPPING12
-rw-r--r--statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java85
-rw-r--r--statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java76
-rw-r--r--statsd/tools/localtools/test/data/atoms.proto (renamed from statsd/tools/localtools/test/external-atoms.proto)15
-rw-r--r--statsd/tools/localtools/test/data/atoms/external_atoms/external_test_atom.proto26
-rw-r--r--statsd/tools/localtools/test/data/enum.proto26
-rw-r--r--tests/src/android/cts/statsd/metric/CountMetricsTests.java17
93 files changed, 5996 insertions, 2030 deletions
diff --git a/apex/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
index 6108a324..028652b9 100644
--- a/apex/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
+++ b/apex/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
@@ -248,6 +248,32 @@ public class LibStatsPullTests {
}
}
+ /**
+ * Tests puller registration/unregistration is processed in order
+ */
+ @Test
+ public void testPullAtomCallbacksProcessedInOrder() throws Exception {
+ StatsManager statsManager = mContext.getSystemService(StatsManager.class);
+ // Upload a config that captures that pulled atom.
+ createAndAddConfigToStatsd(statsManager);
+ for(int i = 0; i < 20; i++) {
+ // Adding & removing the puller back to back to detect any potentional
+ // threads scheduling dependencies
+ setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
+ sPullLatencyMillis, sAtomsPerPull);
+ clearStatsPuller(PULL_ATOM_TAG);
+ }
+ // with out-of-order registration - there is a chance that the puller callback is still
+ // registered - this is wrong and we would like to test it
+ Thread.sleep(SHORT_SLEEP_MILLIS);
+ StatsLog.logStart(APP_BREADCRUMB_LABEL);
+
+ // Let the current bucket finish.
+ Thread.sleep(LONG_SLEEP_MILLIS);
+ List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+ assertThat(data.size()).isEqualTo(0);
+ }
+
private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception {
sConfigId = System.currentTimeMillis();
long triggerMatcherId = sConfigId + 10;
diff --git a/framework/Android.bp b/framework/Android.bp
index daf93cb6..c1a01f90 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -91,6 +91,15 @@ java_sdk_library {
min_sdk_version: "30",
}
+java_api_contribution {
+ name: "framework-statsd-public-stubs",
+ api_surface: "public",
+ api_file: "api/current.txt",
+ visibility: [
+ "//build/orchestrator/apis",
+ ],
+}
+
// JNI library for StatsLog.write
cc_library_shared {
name: "libstats_jni",
diff --git a/framework/test/unittests/AndroidTest.xml b/framework/test/unittests/AndroidTest.xml
index e32f16ec..4ab7b646 100644
--- a/framework/test/unittests/AndroidTest.xml
+++ b/framework/test/unittests/AndroidTest.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<configuration description="Runs Tests for Statsd.">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="test-file-name" value="FrameworkStatsdTest.apk" />
<option name="install-arg" value="-g" />
</target_preparer>
diff --git a/lib/libkll/Android.bp b/lib/libkll/Android.bp
index 94fb0ca2..f17d04e0 100644
--- a/lib/libkll/Android.bp
+++ b/lib/libkll/Android.bp
@@ -24,6 +24,7 @@ package {
cc_library {
name: "libkll",
host_supported: true,
+ vendor_available: true,
srcs: [
"compactor_stack.cpp",
"kll.cpp",
@@ -52,6 +53,9 @@ cc_library {
cc_test {
name: "libkll_test",
+ tidy_timeout_srcs: [
+ "tests/sampler_test.cpp",
+ ],
srcs: [
"tests/**/*.cpp",
],
diff --git a/lib/libkll/encoding/Android.bp b/lib/libkll/encoding/Android.bp
index b8d3f0a7..54729790 100644
--- a/lib/libkll/encoding/Android.bp
+++ b/lib/libkll/encoding/Android.bp
@@ -24,6 +24,7 @@ package {
cc_library_static {
name: "libkll-encoder",
host_supported: true,
+ vendor_available: true,
srcs: [
"encoder.cpp",
"varint.cpp",
diff --git a/lib/libkll/proto/Android.bp b/lib/libkll/proto/Android.bp
index a979f648..a827e15f 100644
--- a/lib/libkll/proto/Android.bp
+++ b/lib/libkll/proto/Android.bp
@@ -24,6 +24,7 @@ package {
cc_library_static {
name: "libkll-protos",
host_supported: true,
+ vendor_available: true,
srcs: ["*.proto"],
proto: {
export_proto_headers: true,
diff --git a/lib/libstatspull/Android.bp b/lib/libstatspull/Android.bp
index 60f237c2..0d6a7868 100644
--- a/lib/libstatspull/Android.bp
+++ b/lib/libstatspull/Android.bp
@@ -48,6 +48,7 @@ cc_defaults {
},
},
}
+
cc_library {
name: "libstatspull",
defaults: [
@@ -120,7 +121,10 @@ cc_test {
"libstatspull",
"libstatssocket",
],
- test_suites: ["general-tests", "mts-statsd"],
+ test_suites: [
+ "general-tests",
+ "mts-statsd",
+ ],
test_config: "libstatspull_test.xml",
//TODO(b/153588990): Remove when the build system properly separates
@@ -143,4 +147,5 @@ cc_test {
"-Wno-unused-parameter",
],
require_root: true,
+ min_sdk_version: "30",
}
diff --git a/lib/libstatspull/stats_pull_atom_callback.cpp b/lib/libstatspull/stats_pull_atom_callback.cpp
index 8a1c89b5..8c72944f 100644
--- a/lib/libstatspull/stats_pull_atom_callback.cpp
+++ b/lib/libstatspull/stats_pull_atom_callback.cpp
@@ -25,6 +25,7 @@
#include <stats_pull_atom_callback.h>
#include <map>
+#include <queue>
#include <thread>
#include <vector>
@@ -179,6 +180,10 @@ public:
}
std::shared_ptr<IStatsd> getStatsService() {
+ // There are host unit tests which are using libstatspull
+ // Since we do not have statsd on host - the getStatsService() is no-op and
+ // should return nullptr
+#ifdef __ANDROID__
std::lock_guard<std::mutex> lock(mStatsdMutex);
if (!mStatsd) {
// Fetch statsd
@@ -188,6 +193,7 @@ public:
AIBinder_linkToDeath(binder.get(), mDeathRecipient.get(), this);
}
}
+#endif // __ANDROID__
return mStatsd;
}
@@ -259,6 +265,114 @@ void unregisterStatsPullAtomCallbackBlocking(int32_t atomTag,
statsService->unregisterNativePullAtomCallback(atomTag);
}
+class CallbackOperationsHandler {
+ struct Cmd {
+ enum Type { CMD_REGISTER, CMD_UNREGISTER };
+
+ Type type;
+ int atomTag;
+ std::shared_ptr<StatsPullAtomCallbackInternal> callback;
+ };
+
+public:
+ ~CallbackOperationsHandler() {
+ for (auto& workThread : mWorkThreads) {
+ if (workThread.joinable()) {
+ mCondition.notify_one();
+ workThread.join();
+ }
+ }
+ }
+
+ static CallbackOperationsHandler& getInstance() {
+ static CallbackOperationsHandler handler;
+ return handler;
+ }
+
+ void registerCallback(int atomTag, std::shared_ptr<StatsPullAtomCallbackInternal> callback) {
+ auto registerCmd = std::make_unique<Cmd>();
+ registerCmd->type = Cmd::CMD_REGISTER;
+ registerCmd->atomTag = atomTag;
+ registerCmd->callback = std::move(callback);
+ pushToQueue(std::move(registerCmd));
+
+ std::thread registerThread(&CallbackOperationsHandler::processCommands, this,
+ statsProvider);
+ mWorkThreads.push_back(std::move(registerThread));
+ }
+
+ void unregisterCallback(int atomTag) {
+ auto unregisterCmd = std::make_unique<Cmd>();
+ unregisterCmd->type = Cmd::CMD_UNREGISTER;
+ unregisterCmd->atomTag = atomTag;
+ pushToQueue(std::move(unregisterCmd));
+
+ std::thread unregisterThread(&CallbackOperationsHandler::processCommands, this,
+ statsProvider);
+ mWorkThreads.push_back(std::move(unregisterThread));
+ }
+
+private:
+ std::vector<std::thread> mWorkThreads;
+
+ std::condition_variable mCondition;
+ std::mutex mMutex;
+ std::queue<std::unique_ptr<Cmd>> mCmdQueue;
+
+ CallbackOperationsHandler() {
+ }
+
+ void pushToQueue(std::unique_ptr<Cmd> cmd) {
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mCmdQueue.push(std::move(cmd));
+ }
+ mCondition.notify_one();
+ }
+
+ void processCommands(std::shared_ptr<StatsdProvider> statsProvider) {
+ /**
+ * First trying to obtain stats service instance
+ * This is a blocking call, which waits on service readiness
+ */
+ const std::shared_ptr<IStatsd> statsService = statsProvider->getStatsService();
+
+ /**
+ * To guarantee sequential commands processing we need to lock mutex queue
+ */
+ std::unique_lock<std::mutex> lock(mMutex);
+ /**
+ * This should never really block in practice, since the command was already queued
+ * from the main thread by registerCallback or unregisterCallback.
+ * We are putting command to the queue, and only after a worker thread is created,
+ * which will pop a single command from a queue and will be terminated after processing.
+ * It makes producer/consumer as 1:1 match
+ */
+ if (mCmdQueue.empty()) {
+ mCondition.wait(lock, [this] { return !this->mCmdQueue.empty(); });
+ }
+
+ std::unique_ptr<Cmd> cmd = std::move(mCmdQueue.front());
+ mCmdQueue.pop();
+
+ if (!statsService) {
+ // Statsd not available - dropping command request
+ return;
+ }
+
+ switch (cmd->type) {
+ case Cmd::CMD_REGISTER: {
+ registerStatsPullAtomCallbackBlocking(cmd->atomTag, statsProvider, cmd->callback);
+ break;
+ }
+ case Cmd::CMD_UNREGISTER: {
+ unregisterStatsPullAtomCallbackBlocking(cmd->atomTag, statsProvider);
+ break;
+ }
+ }
+ }
+};
+
void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata,
AStatsManager_PullAtomCallback callback, void* cookie) {
int64_t coolDownMillis =
@@ -280,9 +394,7 @@ void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomM
pullers[atom_tag] = callbackBinder;
}
- std::thread registerThread(registerStatsPullAtomCallbackBlocking, atom_tag, statsProvider,
- callbackBinder);
- registerThread.detach();
+ CallbackOperationsHandler::getInstance().registerCallback(atom_tag, callbackBinder);
}
void AStatsManager_clearPullAtomCallback(int32_t atom_tag) {
@@ -293,6 +405,5 @@ void AStatsManager_clearPullAtomCallback(int32_t atom_tag) {
pullers.erase(atom_tag);
}
- std::thread unregisterThread(unregisterStatsPullAtomCallbackBlocking, atom_tag, statsProvider);
- unregisterThread.detach();
+ CallbackOperationsHandler::getInstance().unregisterCallback(atom_tag);
}
diff --git a/lib/libstatssocket/Android.bp b/lib/libstatssocket/Android.bp
index 43694591..6a3c3a9c 100644
--- a/lib/libstatssocket/Android.bp
+++ b/lib/libstatssocket/Android.bp
@@ -111,7 +111,10 @@ cc_test {
shared_libs: [
"libutils",
],
- test_suites: ["device-tests", "mts-statsd"],
+ test_suites: [
+ "device-tests",
+ "mts-statsd",
+ ],
test_config: "libstatssocket_test.xml",
//TODO(b/153588990): Remove when the build system properly separates.
//32bit and 64bit architectures.
@@ -125,4 +128,5 @@ cc_test {
},
},
require_root: true,
+ min_sdk_version: "30",
}
diff --git a/statsd/Android.bp b/statsd/Android.bp
index 50ee9f95..d8cb209e 100644
--- a/statsd/Android.bp
+++ b/statsd/Android.bp
@@ -79,6 +79,7 @@ cc_defaults {
"src/statscompanion_util.cpp",
"src/statsd_config.proto",
"src/statsd_metadata.proto",
+ "src/guardrail/invalid_config_reason_enum.proto",
"src/StatsLogProcessor.cpp",
"src/StatsService.cpp",
"src/storage/StorageManager.cpp",
@@ -86,6 +87,7 @@ cc_defaults {
"src/subscriber/SubscriberReporter.cpp",
"src/uid_data.proto",
"src/utils/MultiConditionTrigger.cpp",
+ "src/utils/ShardOffsetProvider.cpp",
],
local_include_dirs: [
@@ -238,7 +240,10 @@ cc_binary {
cc_test {
name: "statsd_test",
defaults: ["statsd_defaults"],
- test_suites: ["device-tests", "mts-statsd"],
+ test_suites: [
+ "device-tests",
+ "mts-statsd",
+ ],
test_config: "statsd_test.xml",
//TODO(b/153588990): Remove when the build system properly separates
@@ -265,6 +270,42 @@ cc_test {
require_root: true,
+ tidy_timeout_srcs: [
+ "tests/condition/SimpleConditionTracker_test.cpp",
+ "tests/ConfigManager_test.cpp",
+ "tests/e2e/Anomaly_count_e2e_test.cpp",
+ "tests/e2e/Anomaly_duration_sum_e2e_test.cpp",
+ "tests/e2e/ConfigUpdate_e2e_ab_test.cpp",
+ "tests/e2e/ConfigUpdate_e2e_test.cpp",
+ "tests/e2e/CountMetric_e2e_test.cpp",
+ "tests/e2e/DurationMetric_e2e_test.cpp",
+ "tests/e2e/GaugeMetric_e2e_pull_test.cpp",
+ "tests/e2e/MetricActivation_e2e_test.cpp",
+ "tests/e2e/PartialBucket_e2e_test.cpp",
+ "tests/e2e/ValueMetric_pull_e2e_test.cpp",
+ "tests/e2e/WakelockDuration_e2e_test.cpp",
+ "tests/external/puller_util_test.cpp",
+ "tests/external/StatsPuller_test.cpp",
+ "tests/FieldValue_test.cpp",
+ "tests/guardrail/StatsdStats_test.cpp",
+ "tests/LogEvent_test.cpp",
+ "tests/metrics/CountMetricProducer_test.cpp",
+ "tests/metrics/DurationMetricProducer_test.cpp",
+ "tests/metrics/EventMetricProducer_test.cpp",
+ "tests/metrics/GaugeMetricProducer_test.cpp",
+ "tests/metrics/KllMetricProducer_test.cpp",
+ "tests/metrics/MaxDurationTracker_test.cpp",
+ "tests/metrics/NumericValueMetricProducer_test.cpp",
+ "tests/metrics/OringDurationTracker_test.cpp",
+ "tests/MetricsManager_test.cpp",
+ "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: [
":libstats_internal_protos",
@@ -345,6 +386,7 @@ cc_test {
"external/protobuf/src",
],
},
+ min_sdk_version: "30",
}
@@ -425,6 +467,7 @@ java_library {
"src/shell/shell_data.proto",
"src/stats_log.proto",
"src/statsd_config.proto",
+ "src/guardrail/invalid_config_reason_enum.proto",
],
static_libs: [
@@ -453,6 +496,7 @@ java_library {
"src/shell/shell_data.proto",
"src/stats_log.proto",
"src/statsd_config.proto",
+ "src/guardrail/invalid_config_reason_enum.proto",
],
static_libs: [
"platformprotosnano",
@@ -481,5 +525,6 @@ filegroup {
"src/statsd_metadata.proto",
"src/stats_log.proto",
"src/uid_data.proto",
+ "src/guardrail/invalid_config_reason_enum.proto",
],
}
diff --git a/statsd/src/FieldValue.cpp b/statsd/src/FieldValue.cpp
index 406c19f0..9e1f21f2 100644
--- a/statsd/src/FieldValue.cpp
+++ b/statsd/src/FieldValue.cpp
@@ -16,8 +16,11 @@
#define STATSD_DEBUG false
#include "Log.h"
+
#include "FieldValue.h"
+
#include "HashableDimensionKey.h"
+#include "hash.h"
#include "math.h"
namespace android {
@@ -521,6 +524,38 @@ size_t getSize(const std::vector<FieldValue>& fieldValues) {
return totalSize;
}
+bool shouldKeepSample(const FieldValue& sampleFieldValue, int shardOffset, int shardCount) {
+ int hashValue = 0;
+ switch (sampleFieldValue.mValue.type) {
+ case INT:
+ hashValue = Hash32(reinterpret_cast<const char*>(&sampleFieldValue.mValue.int_value),
+ sizeof(sampleFieldValue.mValue.int_value));
+ break;
+ case LONG:
+ hashValue = Hash32(reinterpret_cast<const char*>(&sampleFieldValue.mValue.long_value),
+ sizeof(sampleFieldValue.mValue.long_value));
+ break;
+ case FLOAT:
+ hashValue = Hash32(reinterpret_cast<const char*>(&sampleFieldValue.mValue.float_value),
+ sizeof(sampleFieldValue.mValue.float_value));
+ break;
+ case DOUBLE:
+ hashValue = Hash32(reinterpret_cast<const char*>(&sampleFieldValue.mValue.double_value),
+ sizeof(sampleFieldValue.mValue.double_value));
+ break;
+ case STRING:
+ hashValue = Hash32(sampleFieldValue.mValue.str_value);
+ break;
+ case STORAGE:
+ hashValue = Hash32((const char*)sampleFieldValue.mValue.storage_value.data(),
+ sampleFieldValue.mValue.storage_value.size());
+ break;
+ default:
+ return true;
+ }
+ return (hashValue + shardOffset) % shardCount == 0;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/FieldValue.h b/statsd/src/FieldValue.h
index 979264c6..963e2c0d 100644
--- a/statsd/src/FieldValue.h
+++ b/statsd/src/FieldValue.h
@@ -241,7 +241,7 @@ struct Matcher {
}
bool hasAllPositionMatcher() const {
- return mMatcher.getDepth() >= 1 && getRawMaskAtDepth(1) == 0x7f;
+ return mMatcher.getDepth() >= 1 && mMatcher.getRawPosAtDepth(1) == 0;
}
inline bool operator!=(const Matcher& that) const {
@@ -465,6 +465,9 @@ bool subsetDimensions(const std::vector<Matcher>& dimension_a,
// Estimate the memory size of the FieldValues. This is different from sizeof(FieldValue) because
// the size is computed at runtime using the actual contents stored in the FieldValue.
size_t getSize(const std::vector<FieldValue>& fieldValues);
+
+bool shouldKeepSample(const FieldValue& sampleFieldValue, int shardOffset, int shardCount);
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/HashableDimensionKey.cpp b/statsd/src/HashableDimensionKey.cpp
index c1b250a1..447a7311 100644
--- a/statsd/src/HashableDimensionKey.cpp
+++ b/statsd/src/HashableDimensionKey.cpp
@@ -135,6 +135,16 @@ android::hash_t hashDimension(const HashableDimensionKey& value) {
android::hash_type(fieldValue.mValue.float_value));
break;
}
+ case DOUBLE: {
+ hash = android::JenkinsHashMix(hash,
+ android::hash_type(fieldValue.mValue.double_value));
+ break;
+ }
+ case STORAGE: {
+ hash = android::JenkinsHashMixBytes(hash, fieldValue.mValue.storage_value.data(),
+ fieldValue.mValue.storage_value.size());
+ break;
+ }
default:
break;
}
@@ -144,6 +154,9 @@ android::hash_t hashDimension(const HashableDimensionKey& value) {
bool filterValues(const Matcher& matcherField, const vector<FieldValue>& values,
FieldValue* output) {
+ if (matcherField.hasAllPositionMatcher()) {
+ return false;
+ }
for (const auto& value : values) {
if (value.mField.matches(matcherField)) {
(*output) = value;
diff --git a/statsd/src/HashableDimensionKey.h b/statsd/src/HashableDimensionKey.h
index 19a47dfd..b5df4561 100644
--- a/statsd/src/HashableDimensionKey.h
+++ b/statsd/src/HashableDimensionKey.h
@@ -166,7 +166,8 @@ android::hash_t hashDimension(const HashableDimensionKey& key);
/**
* Returns true if a FieldValue field matches the matcher field.
- * The value of the FieldValue is output.
+ * This function can only be used to match one field (i.e. matcher with position ALL will return
+ * false). The value of the FieldValue is output.
*/
bool filterValues(const Matcher& matcherField, const std::vector<FieldValue>& values,
FieldValue* output);
diff --git a/statsd/src/StatsLogProcessor.h b/statsd/src/StatsLogProcessor.h
index 231b4118..d8476cca 100644
--- a/statsd/src/StatsLogProcessor.h
+++ b/statsd/src/StatsLogProcessor.h
@@ -329,15 +329,16 @@ private:
FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition);
FRIEND_TEST(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_single_bucket);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest,
+ TestCountMetric_save_refractory_to_disk_no_data_written);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestCountMetric_save_refractory_to_disk);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestCountMetric_load_refractory_from_disk);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
diff --git a/statsd/src/StatsService.h b/statsd/src/StatsService.h
index d0f13254..4cbd66f6 100644
--- a/statsd/src/StatsService.h
+++ b/statsd/src/StatsService.h
@@ -398,6 +398,8 @@ private:
ScopedAIBinder_DeathRecipient mStatsCompanionServiceDeathRecipient;
+ friend class StatsServiceConfigTest;
+
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
FRIEND_TEST(StatsServiceTest, TestAddConfig_simple);
FRIEND_TEST(StatsServiceTest, TestAddConfig_empty);
@@ -419,10 +421,10 @@ private:
FRIEND_TEST(ConfigUpdateE2eTest, TestAnomalyDurationMetric);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
};
} // namespace statsd
diff --git a/statsd/src/anomaly/AnomalyTracker.cpp b/statsd/src/anomaly/AnomalyTracker.cpp
index 68dc0aa0..fe390ca2 100644
--- a/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/statsd/src/anomaly/AnomalyTracker.cpp
@@ -255,13 +255,15 @@ bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs,
return false;
}
-std::pair<bool, uint64_t> AnomalyTracker::getProtoHash() const {
+std::pair<optional<InvalidConfigReason>, uint64_t> AnomalyTracker::getProtoHash() const {
string serializedAlert;
if (!mAlert.SerializeToString(&serializedAlert)) {
ALOGW("Unable to serialize alert %lld", (long long)mAlert.id());
- return {false, 0};
+ return {createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_SERIALIZATION_FAILED,
+ mAlert.metric_id(), mAlert.id()),
+ 0};
}
- return {true, Hash64(serializedAlert)};
+ return {nullopt, Hash64(serializedAlert)};
}
void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t metric_id,
diff --git a/statsd/src/anomaly/AnomalyTracker.h b/statsd/src/anomaly/AnomalyTracker.h
index feb6bd9f..281c1f6b 100644
--- a/statsd/src/anomaly/AnomalyTracker.h
+++ b/statsd/src/anomaly/AnomalyTracker.h
@@ -22,15 +22,17 @@
#include "AlarmMonitor.h"
#include "config/ConfigKey.h"
+#include "guardrail/StatsdStats.h"
+#include "hash.h"
#include "src/statsd_config.pb.h" // Alert
#include "src/statsd_metadata.pb.h" // AlertMetadata
-#include "hash.h"
-#include "stats_util.h" // HashableDimensionKey and DimToValMap
+#include "stats_util.h" // HashableDimensionKey and DimToValMap
namespace android {
namespace os {
namespace statsd {
+using std::optional;
using std::shared_ptr;
using std::unordered_map;
@@ -109,7 +111,7 @@ public:
return mNumOfPastBuckets;
}
- std::pair<bool, uint64_t> getProtoHash() const;
+ std::pair<optional<InvalidConfigReason>, uint64_t> getProtoHash() const;
// Sets an alarm for the given timestamp.
// Replaces previous alarm if one already exists.
@@ -217,10 +219,10 @@ protected:
FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets);
FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection);
FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
};
diff --git a/statsd/src/condition/CombinationConditionTracker.cpp b/statsd/src/condition/CombinationConditionTracker.cpp
index 7a97ab39..829ae06f 100644
--- a/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/statsd/src/condition/CombinationConditionTracker.cpp
@@ -35,11 +35,11 @@ CombinationConditionTracker::~CombinationConditionTracker() {
VLOG("~CombinationConditionTracker() %lld", (long long)mConditionId);
}
-bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConfig,
- const vector<sp<ConditionTracker>>& allConditionTrackers,
- const unordered_map<int64_t, int>& conditionIdIndexMap,
- vector<bool>& stack,
- vector<ConditionState>& conditionCache) {
+optional<InvalidConfigReason> CombinationConditionTracker::init(
+ const vector<Predicate>& allConditionConfig,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionIdIndexMap, vector<bool>& stack,
+ vector<ConditionState>& conditionCache) {
VLOG("Combination predicate init() %lld", (long long)mConditionId);
if (mInitialized) {
// All the children are guaranteed to be initialized, but the recursion is needed to
@@ -56,21 +56,24 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
}
conditionCache[mIndex] =
evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
- return true;
+ return nullopt;
}
// mark this node as visited in the recursion stack.
stack[mIndex] = true;
Predicate_Combination combinationCondition = allConditionConfig[mIndex].combination();
+ optional<InvalidConfigReason> invalidConfigReason;
if (!combinationCondition.has_operation()) {
- return false;
+ return createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_NO_OPERATION,
+ mConditionId);
}
mLogicalOperation = combinationCondition.operation();
if (mLogicalOperation == LogicalOperation::NOT && combinationCondition.predicate_size() != 1) {
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_NOT_OPERATION_IS_NOT_UNARY, mConditionId);
}
for (auto child : combinationCondition.predicate()) {
@@ -78,7 +81,10 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
if (it == conditionIdIndexMap.end()) {
ALOGW("Predicate %lld not found in the config", (long long)child);
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_CHILD_NOT_FOUND, mConditionId);
+ invalidConfigReason->conditionIds.push_back(child);
+ return invalidConfigReason;
}
int childIndex = it->second;
@@ -86,15 +92,19 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
// if the child is a visited node in the recursion -> circle detected.
if (stack[childIndex]) {
ALOGW("Circle detected!!!");
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_CYCLE, mConditionId);
+ invalidConfigReason->conditionIds.push_back(child);
+ return invalidConfigReason;
}
- bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers,
- conditionIdIndexMap, stack, conditionCache);
+ invalidConfigReason = childTracker->init(allConditionConfig, allConditionTrackers,
+ conditionIdIndexMap, stack, conditionCache);
- if (!initChildSucceeded) {
+ if (invalidConfigReason.has_value()) {
ALOGW("Child initialization failed %lld ", (long long)child);
- return false;
+ invalidConfigReason->conditionIds.push_back(mConditionId);
+ return invalidConfigReason;
} else {
VLOG("Child initialization success %lld ", (long long)child);
}
@@ -120,10 +130,10 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
mInitialized = true;
- return true;
+ return nullopt;
}
-bool CombinationConditionTracker::onConfigUpdated(
+optional<InvalidConfigReason> CombinationConditionTracker::onConfigUpdated(
const vector<Predicate>& allConditionProtos, const int index,
const vector<sp<ConditionTracker>>& allConditionTrackers,
const unordered_map<int64_t, int>& atomMatchingTrackerMap,
@@ -135,23 +145,30 @@ bool CombinationConditionTracker::onConfigUpdated(
mUnSlicedChildren.clear();
mSlicedChildren.clear();
Predicate_Combination combinationCondition = allConditionProtos[mIndex].combination();
+ optional<InvalidConfigReason> invalidConfigReason;
for (const int64_t child : combinationCondition.predicate()) {
const auto& it = conditionTrackerMap.find(child);
if (it == conditionTrackerMap.end()) {
ALOGW("Predicate %lld not found in the config", (long long)child);
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_CHILD_NOT_FOUND, mConditionId);
+ invalidConfigReason->conditionIds.push_back(child);
+ return invalidConfigReason;
}
int childIndex = it->second;
const sp<ConditionTracker>& childTracker = allConditionTrackers[childIndex];
// Ensures that the child's tracker indices are updated.
- if (!childTracker->onConfigUpdated(allConditionProtos, childIndex, allConditionTrackers,
- atomMatchingTrackerMap, conditionTrackerMap)) {
+ invalidConfigReason =
+ childTracker->onConfigUpdated(allConditionProtos, childIndex, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ if (invalidConfigReason.has_value()) {
ALOGW("Child update failed %lld ", (long long)child);
- return false;
+ invalidConfigReason->conditionIds.push_back(child);
+ return invalidConfigReason;
}
if (allConditionTrackers[childIndex]->isSliced()) {
@@ -163,7 +180,7 @@ bool CombinationConditionTracker::onConfigUpdated(
mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(),
childTracker->getAtomMatchingTrackerIndex().end());
}
- return true;
+ return nullopt;
}
void CombinationConditionTracker::isConditionMet(
diff --git a/statsd/src/condition/CombinationConditionTracker.h b/statsd/src/condition/CombinationConditionTracker.h
index 3889e568..82463f07 100644
--- a/statsd/src/condition/CombinationConditionTracker.h
+++ b/statsd/src/condition/CombinationConditionTracker.h
@@ -30,15 +30,17 @@ public:
~CombinationConditionTracker();
- bool 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;
-
- bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const 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;
+ 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;
+
+ optional<InvalidConfigReason> onConfigUpdated(
+ const std::vector<Predicate>& allConditionProtos, const 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;
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
diff --git a/statsd/src/condition/ConditionTracker.h b/statsd/src/condition/ConditionTracker.h
index 4ce8cb13..2aa3ff06 100644
--- a/statsd/src/condition/ConditionTracker.h
+++ b/statsd/src/condition/ConditionTracker.h
@@ -54,10 +54,11 @@ public:
// stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
// conditionCache: tracks initial conditions of all ConditionTrackers. returns the
// current condition if called on a config update.
- virtual bool 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;
+ 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;
// 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.
@@ -71,12 +72,13 @@ public:
// atomMatchingTrackerMap: map of atom matcher id to index after the config update.
// conditionTrackerMap: map of condition tracker id to index after the config update.
// returns whether or not the update is successful.
- virtual bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
- const std::vector<sp<ConditionTracker>>& allConditionTrackers,
- const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
- const std::unordered_map<int64_t, int>& conditionTrackerMap) {
+ virtual optional<InvalidConfigReason> onConfigUpdated(
+ const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) {
mIndex = index;
- return true;
+ return nullopt;
}
// evaluate current condition given the new event.
diff --git a/statsd/src/condition/SimpleConditionTracker.cpp b/statsd/src/condition/SimpleConditionTracker.cpp
index 66ce961f..5d7d3858 100644
--- a/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/statsd/src/condition/SimpleConditionTracker.cpp
@@ -56,10 +56,11 @@ SimpleConditionTracker::~SimpleConditionTracker() {
VLOG("~SimpleConditionTracker()");
}
-bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
- const vector<sp<ConditionTracker>>& allConditionTrackers,
- const unordered_map<int64_t, int>& conditionIdIndexMap,
- vector<bool>& stack, vector<ConditionState>& conditionCache) {
+optional<InvalidConfigReason> SimpleConditionTracker::init(
+ const vector<Predicate>& allConditionConfig,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionIdIndexMap, vector<bool>& stack,
+ vector<ConditionState>& conditionCache) {
// SimpleConditionTracker does not have dependency on other conditions, thus we just return
// if the initialization was successful.
ConditionKey conditionKey;
@@ -67,10 +68,14 @@ bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
conditionKey[mConditionId] = DEFAULT_DIMENSION_KEY;
}
isConditionMet(conditionKey, allConditionTrackers, mSliced, conditionCache);
- return mInitialized;
+ if (!mInitialized) {
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_TRACKER_NOT_INITIALIZED, mConditionId);
+ }
+ return nullopt;
}
-bool SimpleConditionTracker::onConfigUpdated(
+optional<InvalidConfigReason> SimpleConditionTracker::onConfigUpdated(
const vector<Predicate>& allConditionProtos, const int index,
const vector<sp<ConditionTracker>>& allConditionTrackers,
const unordered_map<int64_t, int>& atomMatchingTrackerMap,
@@ -78,7 +83,7 @@ bool SimpleConditionTracker::onConfigUpdated(
ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
atomMatchingTrackerMap, conditionTrackerMap);
setMatcherIndices(allConditionProtos[index].simple_predicate(), atomMatchingTrackerMap);
- return true;
+ return nullopt;
}
void SimpleConditionTracker::setMatcherIndices(
diff --git a/statsd/src/condition/SimpleConditionTracker.h b/statsd/src/condition/SimpleConditionTracker.h
index 4dc56607..4687d8e1 100644
--- a/statsd/src/condition/SimpleConditionTracker.h
+++ b/statsd/src/condition/SimpleConditionTracker.h
@@ -35,15 +35,17 @@ public:
~SimpleConditionTracker();
- bool 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;
-
- bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const 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;
+ 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;
+
+ optional<InvalidConfigReason> onConfigUpdated(
+ const std::vector<Predicate>& allConditionProtos, const 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;
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
diff --git a/statsd/src/external/PullDataReceiver.h b/statsd/src/external/PullDataReceiver.h
index 8e3a8a13..47e13773 100644
--- a/statsd/src/external/PullDataReceiver.h
+++ b/statsd/src/external/PullDataReceiver.h
@@ -23,17 +23,22 @@ namespace android {
namespace os {
namespace statsd {
+// Determine if pull was needed and if so, whether the pull was successful
+enum PullResult { PULL_RESULT_SUCCESS = 1, PULL_RESULT_FAIL = 2, PULL_NOT_NEEDED = 3 };
+
class PullDataReceiver : virtual public RefBase{
public:
virtual ~PullDataReceiver() {}
/**
* @param data The pulled data.
- * @param pullSuccess Whether the pull succeeded. If the pull does not succeed, the data for the
- * bucket should be invalidated.
+ * @param pullResult Whether the pull succeeded and was needed. If the pull does not succeed,
+ * the data for the bucket should be invalidated.
* @param originalPullTimeNs This is when all the pulls have been initiated (elapsed time).
*/
- virtual void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data, bool pullSuccess,
- int64_t originalPullTimeNs) = 0;
+ virtual void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
+ PullResult pullResult, int64_t originalPullTimeNs) = 0;
+
+ virtual bool isPullNeeded() const = 0;
};
} // namespace statsd
diff --git a/statsd/src/external/StatsPullerManager.cpp b/statsd/src/external/StatsPullerManager.cpp
index 90e1cd0e..ca5ee5b8 100644
--- a/statsd/src/external/StatsPullerManager.cpp
+++ b/statsd/src/external/StatsPullerManager.cpp
@@ -32,6 +32,7 @@
#include "../statscompanion_util.h"
#include "StatsCallbackPuller.h"
#include "TrainInfoPuller.h"
+#include "flags/FlagProvider.h"
#include "statslog_statsd.h"
using std::shared_ptr;
@@ -49,7 +50,8 @@ StatsPullerManager::StatsPullerManager()
// TrainInfo.
{{.atomTag = util::TRAIN_INFO, .uid = AID_STATSD}, new TrainInfoPuller()},
}),
- mNextPullTimeNs(NO_ALARM_UPDATE) {
+ mNextPullTimeNs(NO_ALARM_UPDATE),
+ mLimitPull(FlagProvider::getInstance().getBootFlagBool(LIMIT_PULL_FLAG, FLAG_FALSE)) {
}
bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
@@ -227,11 +229,32 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
vector<ReceiverInfo*> receivers;
if (pair.second.size() != 0) {
for (ReceiverInfo& receiverInfo : pair.second) {
- if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) {
- receivers.push_back(&receiverInfo);
+ // If mLimitPull is true, check if metric needs to pull data (pullNecessary).
+ // If pullNecessary and enough time has passed for the next bucket, then add
+ // receiver to the list that will pull on this alarm.
+ // If pullNecessary is false, check if next pull time needs to be updated.
+ if (mLimitPull) {
+ sp<PullDataReceiver> receiverPtr = receiverInfo.receiver.promote();
+ const bool pullNecessary =
+ receiverPtr != nullptr && receiverPtr->isPullNeeded();
+ if (receiverInfo.nextPullTimeNs <= elapsedTimeNs && pullNecessary) {
+ receivers.push_back(&receiverInfo);
+ } else {
+ if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) {
+ receiverPtr->onDataPulled({}, PullResult::PULL_NOT_NEEDED,
+ elapsedTimeNs);
+ int numBucketsAhead = (elapsedTimeNs - receiverInfo.nextPullTimeNs) /
+ receiverInfo.intervalNs;
+ receiverInfo.nextPullTimeNs +=
+ (numBucketsAhead + 1) * receiverInfo.intervalNs;
+ }
+ minNextPullTimeNs = min(receiverInfo.nextPullTimeNs, minNextPullTimeNs);
+ }
} else {
- if (receiverInfo.nextPullTimeNs < minNextPullTimeNs) {
- minNextPullTimeNs = receiverInfo.nextPullTimeNs;
+ if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) {
+ receivers.push_back(&receiverInfo);
+ } else {
+ minNextPullTimeNs = min(receiverInfo.nextPullTimeNs, minNextPullTimeNs);
}
}
}
@@ -242,9 +265,11 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
}
for (const auto& pullInfo : needToPull) {
vector<shared_ptr<LogEvent>> data;
- bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey,
- elapsedTimeNs, &data);
- if (!pullSuccess) {
+ PullResult pullResult =
+ PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey, elapsedTimeNs, &data)
+ ? PullResult::PULL_RESULT_SUCCESS
+ : PullResult::PULL_RESULT_FAIL;
+ if (pullResult == PullResult::PULL_RESULT_FAIL) {
VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs);
}
@@ -263,14 +288,12 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
for (const auto& receiverInfo : pullInfo.second) {
sp<PullDataReceiver> receiverPtr = receiverInfo->receiver.promote();
if (receiverPtr != nullptr) {
- receiverPtr->onDataPulled(data, pullSuccess, elapsedTimeNs);
+ receiverPtr->onDataPulled(data, pullResult, elapsedTimeNs);
// We may have just come out of a coma, compute next pull time.
int numBucketsAhead =
(elapsedTimeNs - receiverInfo->nextPullTimeNs) / receiverInfo->intervalNs;
receiverInfo->nextPullTimeNs += (numBucketsAhead + 1) * receiverInfo->intervalNs;
- if (receiverInfo->nextPullTimeNs < minNextPullTimeNs) {
- minNextPullTimeNs = receiverInfo->nextPullTimeNs;
- }
+ minNextPullTimeNs = min(receiverInfo->nextPullTimeNs, minNextPullTimeNs);
} else {
VLOG("receiver already gone.");
}
diff --git a/statsd/src/external/StatsPullerManager.h b/statsd/src/external/StatsPullerManager.h
index b503aa83..6e65f31a 100644
--- a/statsd/src/external/StatsPullerManager.h
+++ b/statsd/src/external/StatsPullerManager.h
@@ -164,6 +164,8 @@ private:
int64_t mNextPullTimeNs;
+ const bool mLimitPull;
+
FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents);
FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm);
FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation);
diff --git a/statsd/src/flags/FlagProvider.h b/statsd/src/flags/FlagProvider.h
index 6684ba4d..e948911f 100644
--- a/statsd/src/flags/FlagProvider.h
+++ b/statsd/src/flags/FlagProvider.h
@@ -39,6 +39,8 @@ const std::string STATSD_NATIVE_BOOT_NAMESPACE = "statsd_native_boot";
const std::string OPTIMIZATION_ATOM_MATCHER_MAP_FLAG = "optimization_atom_matcher_map";
+const std::string LIMIT_PULL_FLAG = "limit_pull";
+
const std::string FLAG_TRUE = "true";
const std::string FLAG_FALSE = "false";
const std::string FLAG_EMPTY = "";
@@ -103,6 +105,7 @@ private:
friend class ConfigUpdateE2eTest;
friend class ConfigUpdateTest;
friend class EventMetricE2eTest;
+ friend class ValueMetricE2eTest;
friend class GaugeMetricE2ePulledTest;
friend class GaugeMetricE2ePushedTest;
friend class EventMetricProducerTest;
diff --git a/statsd/src/guardrail/StatsdStats.cpp b/statsd/src/guardrail/StatsdStats.cpp
index 0e660190..f18497a6 100644
--- a/statsd/src/guardrail/StatsdStats.cpp
+++ b/statsd/src/guardrail/StatsdStats.cpp
@@ -29,6 +29,7 @@ namespace statsd {
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
+using android::util::FIELD_TYPE_ENUM;
using android::util::FIELD_TYPE_FLOAT;
using android::util::FIELD_TYPE_INT32;
using android::util::FIELD_TYPE_INT64;
@@ -81,6 +82,7 @@ const int FIELD_ID_CONFIG_STATS_CONDITION_COUNT = 6;
const int FIELD_ID_CONFIG_STATS_MATCHER_COUNT = 7;
const int FIELD_ID_CONFIG_STATS_ALERT_COUNT = 8;
const int FIELD_ID_CONFIG_STATS_VALID = 9;
+const int FIELD_ID_CONFIG_STATS_INVALID_CONFIG_REASON = 24;
const int FIELD_ID_CONFIG_STATS_BROADCAST = 10;
const int FIELD_ID_CONFIG_STATS_DATA_DROP_TIME = 11;
const int FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES = 21;
@@ -97,6 +99,15 @@ const int FIELD_ID_CONFIG_STATS_DEACTIVATION = 23;
const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT64 = 1;
const int FIELD_ID_CONFIG_STATS_ANNOTATION_INT32 = 2;
+const int FIELD_ID_INVALID_CONFIG_REASON_ENUM = 1;
+const int FIELD_ID_INVALID_CONFIG_REASON_METRIC_ID = 2;
+const int FIELD_ID_INVALID_CONFIG_REASON_STATE_ID = 3;
+const int FIELD_ID_INVALID_CONFIG_REASON_ALERT_ID = 4;
+const int FIELD_ID_INVALID_CONFIG_REASON_ALARM_ID = 5;
+const int FIELD_ID_INVALID_CONFIG_REASON_SUBSCRIPTION_ID = 6;
+const int FIELD_ID_INVALID_CONFIG_REASON_MATCHER_ID = 7;
+const int FIELD_ID_INVALID_CONFIG_REASON_CONDITION_ID = 8;
+
const int FIELD_ID_MATCHER_STATS_ID = 1;
const int FIELD_ID_MATCHER_STATS_COUNT = 2;
const int FIELD_ID_CONDITION_STATS_ID = 1;
@@ -141,7 +152,7 @@ void StatsdStats::addToIceBoxLocked(shared_ptr<ConfigStats>& stats) {
void StatsdStats::noteConfigReceived(
const ConfigKey& key, int metricsCount, int conditionsCount, int matchersCount,
int alertsCount, const std::list<std::pair<const int64_t, const int32_t>>& annotations,
- bool isValid) {
+ const optional<InvalidConfigReason>& reason) {
lock_guard<std::mutex> lock(mLock);
int32_t nowTimeSec = getWallClockSec();
@@ -156,12 +167,13 @@ void StatsdStats::noteConfigReceived(
configStats->condition_count = conditionsCount;
configStats->matcher_count = matchersCount;
configStats->alert_count = alertsCount;
- configStats->is_valid = isValid;
+ configStats->is_valid = !reason.has_value();
+ configStats->reason = reason;
for (auto& v : annotations) {
configStats->annotations.emplace_back(v);
}
- if (isValid) {
+ if (!reason.has_value()) {
mConfigStats[key] = configStats;
} else {
configStats->deletion_time_sec = nowTimeSec;
@@ -678,12 +690,17 @@ void StatsdStats::dumpStats(int out) const {
for (const auto& configStats : mIceBox) {
dprintf(out,
"Config {%d_%lld}: creation=%d, deletion=%d, reset=%d, #metric=%d, #condition=%d, "
- "#matcher=%d, #alert=%d, valid=%d\n",
+ "#matcher=%d, #alert=%d, valid=%d\n",
configStats->uid, (long long)configStats->id, configStats->creation_time_sec,
configStats->deletion_time_sec, configStats->reset_time_sec,
configStats->metric_count, configStats->condition_count, configStats->matcher_count,
configStats->alert_count, configStats->is_valid);
+ if (!configStats->is_valid) {
+ dprintf(out, "\tinvalid config reason: %s\n",
+ InvalidConfigReasonEnum_Name(configStats->reason->reason).c_str());
+ }
+
for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) {
dprintf(out, "\tbroadcast time: %d\n", broadcastTime);
}
@@ -709,11 +726,17 @@ void StatsdStats::dumpStats(int out) const {
auto& configStats = pair.second;
dprintf(out,
"Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
- "#matcher=%d, #alert=%d, valid=%d\n",
+ "#matcher=%d, #alert=%d, valid=%d\n",
configStats->uid, (long long)configStats->id, configStats->creation_time_sec,
configStats->deletion_time_sec, configStats->metric_count,
configStats->condition_count, configStats->matcher_count, configStats->alert_count,
configStats->is_valid);
+
+ if (!configStats->is_valid) {
+ dprintf(out, "\tinvalid config reason: %s\n",
+ InvalidConfigReasonEnum_Name(configStats->reason->reason).c_str());
+ }
+
for (const auto& annotation : configStats->annotations) {
dprintf(out, "\tannotation: %lld, %d\n", (long long)annotation.first,
annotation.second);
@@ -878,6 +901,44 @@ void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* pr
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_ALERT_COUNT, configStats.alert_count);
proto->write(FIELD_TYPE_BOOL | FIELD_ID_CONFIG_STATS_VALID, configStats.is_valid);
+ if (!configStats.is_valid) {
+ uint64_t tmpToken =
+ proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_STATS_INVALID_CONFIG_REASON);
+ proto->write(FIELD_TYPE_ENUM | FIELD_ID_INVALID_CONFIG_REASON_ENUM,
+ configStats.reason->reason);
+ if (configStats.reason->metricId.has_value()) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_INVALID_CONFIG_REASON_METRIC_ID,
+ configStats.reason->metricId.value());
+ }
+ if (configStats.reason->stateId.has_value()) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_INVALID_CONFIG_REASON_STATE_ID,
+ configStats.reason->stateId.value());
+ }
+ if (configStats.reason->alertId.has_value()) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_INVALID_CONFIG_REASON_ALERT_ID,
+ configStats.reason->alertId.value());
+ }
+ if (configStats.reason->alarmId.has_value()) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_INVALID_CONFIG_REASON_ALARM_ID,
+ configStats.reason->alarmId.value());
+ }
+ if (configStats.reason->subscriptionId.has_value()) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_INVALID_CONFIG_REASON_SUBSCRIPTION_ID,
+ configStats.reason->subscriptionId.value());
+ }
+ for (const auto& matcherId : configStats.reason->matcherIds) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED |
+ FIELD_ID_INVALID_CONFIG_REASON_MATCHER_ID,
+ matcherId);
+ }
+ for (const auto& conditionId : configStats.reason->conditionIds) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED |
+ FIELD_ID_INVALID_CONFIG_REASON_CONDITION_ID,
+ conditionId);
+ }
+ proto->end(tmpToken);
+ }
+
for (const auto& broadcast : configStats.broadcast_sent_time_sec) {
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_BROADCAST | FIELD_COUNT_REPEATED,
broadcast);
@@ -1106,6 +1167,89 @@ std::pair<size_t, size_t> StatsdStats::getAtomDimensionKeySizeLimits(const int a
kDimensionKeySizeHardLimit);
}
+InvalidConfigReason createInvalidConfigReasonWithMatcher(const InvalidConfigReasonEnum reason,
+ const int64_t matcherId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.matcherIds.push_back(matcherId);
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithMatcher(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t matcherId) {
+ InvalidConfigReason invalidConfigReason(reason, metricId);
+ invalidConfigReason.matcherIds.push_back(matcherId);
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithPredicate(const InvalidConfigReasonEnum reason,
+ const int64_t conditionId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.conditionIds.push_back(conditionId);
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithPredicate(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t conditionId) {
+ InvalidConfigReason invalidConfigReason(reason, metricId);
+ invalidConfigReason.conditionIds.push_back(conditionId);
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithState(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t stateId) {
+ InvalidConfigReason invalidConfigReason(reason, metricId);
+ invalidConfigReason.stateId = stateId;
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithAlert(const InvalidConfigReasonEnum reason,
+ const int64_t alertId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.alertId = alertId;
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithAlert(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t alertId) {
+ InvalidConfigReason invalidConfigReason(reason, metricId);
+ invalidConfigReason.alertId = alertId;
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithAlarm(const InvalidConfigReasonEnum reason,
+ const int64_t alarmId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.alarmId = alarmId;
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithSubscription(const InvalidConfigReasonEnum reason,
+ const int64_t subscriptionId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.subscriptionId = subscriptionId;
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithSubscriptionAndAlarm(
+ const InvalidConfigReasonEnum reason, const int64_t subscriptionId, const int64_t alarmId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.subscriptionId = subscriptionId;
+ invalidConfigReason.alarmId = alarmId;
+ return invalidConfigReason;
+}
+
+InvalidConfigReason createInvalidConfigReasonWithSubscriptionAndAlert(
+ const InvalidConfigReasonEnum reason, const int64_t subscriptionId, const int64_t alertId) {
+ InvalidConfigReason invalidConfigReason(reason);
+ invalidConfigReason.subscriptionId = subscriptionId;
+ invalidConfigReason.alertId = alertId;
+ return invalidConfigReason;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/guardrail/StatsdStats.h b/statsd/src/guardrail/StatsdStats.h
index 1393e56f..40283b13 100644
--- a/statsd/src/guardrail/StatsdStats.h
+++ b/statsd/src/guardrail/StatsdStats.h
@@ -15,20 +15,43 @@
*/
#pragma once
-#include "config/ConfigKey.h"
-
#include <gtest/gtest_prod.h>
#include <log/log_time.h>
+#include <src/guardrail/invalid_config_reason_enum.pb.h>
+
#include <list>
#include <mutex>
#include <string>
-#include <vector>
#include <unordered_map>
+#include <vector>
+
+#include "config/ConfigKey.h"
namespace android {
namespace os {
namespace statsd {
+struct InvalidConfigReason {
+ InvalidConfigReasonEnum reason;
+ std::optional<int64_t> metricId;
+ std::optional<int64_t> stateId;
+ std::optional<int64_t> alertId;
+ std::optional<int64_t> alarmId;
+ std::optional<int64_t> subscriptionId;
+ std::vector<int64_t> matcherIds;
+ std::vector<int64_t> conditionIds;
+ InvalidConfigReason(){};
+ InvalidConfigReason(InvalidConfigReasonEnum reason) : reason(reason){};
+ InvalidConfigReason(InvalidConfigReasonEnum reason, int64_t metricId)
+ : reason(reason), metricId(metricId){};
+ bool operator==(const InvalidConfigReason& other) const {
+ return (this->reason == other.reason) && (this->metricId == other.metricId) &&
+ (this->stateId == other.stateId) && (this->alertId == other.alertId) &&
+ (this->alarmId == other.alarmId) && (this->subscriptionId == other.subscriptionId) &&
+ (this->matcherIds == other.matcherIds) && (this->conditionIds == other.conditionIds);
+ }
+};
+
struct ConfigStats {
int32_t uid;
int64_t id;
@@ -41,6 +64,9 @@ struct ConfigStats {
int32_t alert_count;
bool is_valid;
+ // Stores reasons for why config is valid or not
+ std::optional<InvalidConfigReason> reason;
+
std::list<int32_t> broadcast_sent_time_sec;
// Times at which this config is activated.
@@ -200,7 +226,7 @@ public:
void noteConfigReceived(const ConfigKey& key, int metricsCount, int conditionsCount,
int matchersCount, int alertCount,
const std::list<std::pair<const int64_t, const int32_t>>& annotations,
- bool isValid);
+ const std::optional<InvalidConfigReason>& reason);
/**
* Report a config has been removed.
*/
@@ -663,6 +689,8 @@ private:
FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd);
FRIEND_TEST(StatsdStatsTest, TestInvalidConfigAdd);
+ FRIEND_TEST(StatsdStatsTest, TestInvalidConfigMissingMetricId);
+ FRIEND_TEST(StatsdStatsTest, TestInvalidConfigOnlyMetricId);
FRIEND_TEST(StatsdStatsTest, TestConfigRemove);
FRIEND_TEST(StatsdStatsTest, TestSubStats);
FRIEND_TEST(StatsdStatsTest, TestAtomLog);
@@ -678,6 +706,43 @@ private:
FRIEND_TEST(StatsLogProcessorTest, InvalidConfigRemoved);
};
+InvalidConfigReason createInvalidConfigReasonWithMatcher(const InvalidConfigReasonEnum reason,
+ const int64_t matcherId);
+
+InvalidConfigReason createInvalidConfigReasonWithMatcher(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t matcherId);
+
+InvalidConfigReason createInvalidConfigReasonWithPredicate(const InvalidConfigReasonEnum reason,
+ const int64_t conditionId);
+
+InvalidConfigReason createInvalidConfigReasonWithPredicate(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t conditionId);
+
+InvalidConfigReason createInvalidConfigReasonWithState(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t stateId);
+
+InvalidConfigReason createInvalidConfigReasonWithAlert(const InvalidConfigReasonEnum reason,
+ const int64_t alertId);
+
+InvalidConfigReason createInvalidConfigReasonWithAlert(const InvalidConfigReasonEnum reason,
+ const int64_t metricId,
+ const int64_t alertId);
+
+InvalidConfigReason createInvalidConfigReasonWithAlarm(const InvalidConfigReasonEnum reason,
+ const int64_t alarmId);
+
+InvalidConfigReason createInvalidConfigReasonWithSubscription(const InvalidConfigReasonEnum reason,
+ const int64_t subscriptionId);
+
+InvalidConfigReason createInvalidConfigReasonWithSubscriptionAndAlarm(
+ const InvalidConfigReasonEnum reason, const int64_t subscriptionId, const int64_t alarmId);
+
+InvalidConfigReason createInvalidConfigReasonWithSubscriptionAndAlert(
+ const InvalidConfigReasonEnum reason, const int64_t subscriptionId, const int64_t alertId);
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/guardrail/invalid_config_reason_enum.proto b/statsd/src/guardrail/invalid_config_reason_enum.proto
new file mode 100644
index 00000000..c56e39c1
--- /dev/null
+++ b/statsd/src/guardrail/invalid_config_reason_enum.proto
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+ syntax = "proto2";
+
+ package android.os.statsd;
+
+ option java_package = "com.android.os";
+ option java_outer_classname = "InvalidConfigReason";
+
+enum InvalidConfigReasonEnum {
+ INVALID_CONFIG_REASON_UNKNOWN = 0;
+ INVALID_CONFIG_REASON_LOG_SOURCE_ALLOWLIST_EMPTY = 1;
+ INVALID_CONFIG_REASON_TOO_MANY_LOG_SOURCES = 2;
+ INVALID_CONFIG_REASON_DEFAULT_PULL_PACKAGES_NOT_IN_MAP = 3;
+ INVALID_CONFIG_REASON_TOO_MANY_SOURCES_IN_PULL_PACKAGES = 4;
+ INVALID_CONFIG_REASON_TOO_MANY_METRICS = 5;
+ INVALID_CONFIG_REASON_TOO_MANY_CONDITIONS = 6;
+ INVALID_CONFIG_REASON_TOO_MANY_MATCHERS = 7;
+ INVALID_CONFIG_REASON_TOO_MANY_ALERTS = 8;
+ INVALID_CONFIG_REASON_PACKAGE_CERT_HASH_SIZE_TOO_LARGE = 9;
+ INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND = 10;
+ INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG = 11;
+ INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN = 12;
+ INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS = 13;
+ INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID = 14;
+ INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT = 15;
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION = 16;
+ INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE = 17;
+ INVALID_CONFIG_REASON_METRIC_BAD_THRESHOLD = 18;
+ INVALID_CONFIG_REASON_METRIC_MATCHER_NOT_FOUND = 19;
+ INVALID_CONFIG_REASON_METRIC_MATCHER_MORE_THAN_ONE_ATOM = 20;
+ INVALID_CONFIG_REASON_METRIC_CONDITION_NOT_FOUND = 21;
+ INVALID_CONFIG_REASON_METRIC_CONDITION_LINK_NOT_FOUND = 22;
+ INVALID_CONFIG_REASON_METRIC_STATE_NOT_FOUND = 23;
+ INVALID_CONFIG_REASON_METRIC_STATELINKS_NOT_SUBSET_DIM_IN_WHAT = 24;
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND = 25;
+ INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND = 26;
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND_NEW = 27;
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND_EXISTING = 28;
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_NOT_FOUND_EXISTING = 29;
+ INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND_NEW = 30;
+ INVALID_CONFIG_REASON_METRIC_SERIALIZATION_FAILED = 31;
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_SERIALIZATION_FAILED = 32;
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_SIMPLE = 33;
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_FOUND = 34;
+ INVALID_CONFIG_REASON_DURATION_METRIC_MISSING_START = 35;
+ INVALID_CONFIG_REASON_DURATION_METRIC_PRODUCER_INVALID = 36;
+ INVALID_CONFIG_REASON_DURATION_METRIC_MAX_SPARSE_HAS_SLICE_BY_STATE = 37;
+ INVALID_CONFIG_REASON_VALUE_METRIC_MISSING_VALUE_FIELD = 38;
+ INVALID_CONFIG_REASON_VALUE_METRIC_VALUE_FIELD_HAS_POSITION_ALL = 39;
+ INVALID_CONFIG_REASON_VALUE_METRIC_HAS_INCORRECT_VALUE_FIELD = 40;
+ INVALID_CONFIG_REASON_KLL_METRIC_MISSING_KLL_FIELD = 41;
+ INVALID_CONFIG_REASON_KLL_METRIC_KLL_FIELD_HAS_POSITION_ALL = 42;
+ INVALID_CONFIG_REASON_KLL_METRIC_HAS_INCORRECT_KLL_FIELD = 43;
+ INVALID_CONFIG_REASON_GAUGE_METRIC_INCORRECT_FIELD_FILTER = 44;
+ INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_PULL_ATOM = 45;
+ INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_FIRST_N_SAMPLES = 46;
+ INVALID_CONFIG_REASON_GAUGE_METRIC_FIRST_N_SAMPLES_WITH_WRONG_EVENT = 47;
+ INVALID_CONFIG_REASON_MATCHER_NOT_IN_PREV_CONFIG = 48;
+ INVALID_CONFIG_REASON_MATCHER_UPDATE_STATUS_UNKNOWN = 49;
+ INVALID_CONFIG_REASON_MATCHER_DUPLICATE = 50;
+ INVALID_CONFIG_REASON_MATCHER_SERIALIZATION_FAILED = 51;
+ INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE = 52;
+ INVALID_CONFIG_REASON_MATCHER_TRACKER_NOT_INITIALIZED = 53;
+ INVALID_CONFIG_REASON_MATCHER_NO_OPERATION = 54;
+ INVALID_CONFIG_REASON_MATCHER_NOT_OPERATION_IS_NOT_UNARY = 55;
+ INVALID_CONFIG_REASON_MATCHER_CYCLE = 56;
+ INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND = 57;
+ INVALID_CONFIG_REASON_CONDITION_NOT_IN_PREV_CONFIG = 58;
+ INVALID_CONFIG_REASON_CONDITION_UPDATE_STATUS_UNKNOWN = 59;
+ INVALID_CONFIG_REASON_CONDITION_DUPLICATE = 60;
+ INVALID_CONFIG_REASON_CONDITION_SERIALIZATION_FAILED = 61;
+ INVALID_CONFIG_REASON_CONDITION_MALFORMED_CONTENTS_CASE = 62;
+ INVALID_CONFIG_REASON_CONDITION_TRACKER_NOT_INITIALIZED = 63;
+ INVALID_CONFIG_REASON_CONDITION_NO_OPERATION = 64;
+ INVALID_CONFIG_REASON_CONDITION_NOT_OPERATION_IS_NOT_UNARY = 65;
+ INVALID_CONFIG_REASON_CONDITION_CYCLE = 66;
+ INVALID_CONFIG_REASON_CONDITION_CHILD_NOT_FOUND = 67;
+ INVALID_CONFIG_REASON_STATE_SERIALIZATION_FAILED = 68;
+ INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND = 69;
+ INVALID_CONFIG_REASON_ALERT_THRESHOLD_MISSING = 70;
+ INVALID_CONFIG_REASON_ALERT_INVALID_TRIGGER_OR_NUM_BUCKETS = 71;
+ INVALID_CONFIG_REASON_ALERT_CANNOT_ADD_ANOMALY = 72;
+ INVALID_CONFIG_REASON_ALERT_NOT_IN_PREV_CONFIG = 73;
+ INVALID_CONFIG_REASON_ALERT_UPDATE_STATUS_UNKNOWN = 74;
+ INVALID_CONFIG_REASON_ALERT_SERIALIZATION_FAILED = 75;
+ INVALID_CONFIG_REASON_ALARM_OFFSET_LESS_THAN_OR_EQUAL_ZERO = 76;
+ INVALID_CONFIG_REASON_ALARM_PERIOD_LESS_THAN_OR_EQUAL_ZERO = 77;
+ INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING = 78;
+ INVALID_CONFIG_REASON_SUBSCRIPTION_RULE_NOT_FOUND = 79;
+ INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_INCORRECT_SHARD_COUNT = 80;
+ INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_MISSING_SAMPLED_FIELD = 81;
+ INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE = 82;
+ INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELDS_NOT_SUBSET_DIM_IN_WHAT = 83;
+};
diff --git a/statsd/src/main.cpp b/statsd/src/main.cpp
index cd64fe7f..02dbbe84 100644
--- a/statsd/src/main.cpp
+++ b/statsd/src/main.cpp
@@ -76,7 +76,8 @@ int main(int /*argc*/, char** /*argv*/) {
std::make_shared<LogEventQueue>(4000 /*buffer limit. Buffer is NOT pre-allocated*/);
// Initialize boot flags
- FlagProvider::getInstance().initBootFlags({OPTIMIZATION_ATOM_MATCHER_MAP_FLAG});
+ FlagProvider::getInstance().initBootFlags(
+ {OPTIMIZATION_ATOM_MATCHER_MAP_FLAG, LIMIT_PULL_FLAG});
sp<UidMap> uidMap = UidMap::getInstance();
diff --git a/statsd/src/matchers/AtomMatchingTracker.h b/statsd/src/matchers/AtomMatchingTracker.h
index cdb17165..3e35d9bf 100644
--- a/statsd/src/matchers/AtomMatchingTracker.h
+++ b/statsd/src/matchers/AtomMatchingTracker.h
@@ -17,16 +17,17 @@
#ifndef ATOM_MATCHING_TRACKER_H
#define ATOM_MATCHING_TRACKER_H
-#include "src/statsd_config.pb.h"
-#include "logd/LogEvent.h"
-#include "matchers/matcher_util.h"
-
#include <utils/RefBase.h>
#include <set>
#include <unordered_map>
#include <vector>
+#include "guardrail/StatsdStats.h"
+#include "logd/LogEvent.h"
+#include "matchers/matcher_util.h"
+#include "src/statsd_config.pb.h"
+
namespace android {
namespace os {
namespace statsd {
@@ -47,17 +48,17 @@ 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 bool init(const std::vector<AtomMatcher>& allAtomMatchers,
- const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- const std::unordered_map<int64_t, int>& matcherMap,
- std::vector<bool>& stack) = 0;
+ virtual 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) = 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 bool onConfigUpdated(
+ virtual optional<InvalidConfigReason> onConfigUpdated(
const AtomMatcher& matcher, const int index,
const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) = 0;
@@ -87,6 +88,10 @@ public:
return mProtoHash;
}
+ bool isInitialized() {
+ return mInitialized;
+ }
+
protected:
// Name of this matching. We don't really need the name, but it makes log message easy to debug.
const int64_t mId;
@@ -106,8 +111,8 @@ protected:
// Used to determine if the definition of this matcher has changed across a config update.
const uint64_t mProtoHash;
- FRIEND_TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerSimple);
- FRIEND_TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination);
+ FRIEND_TEST(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerSimple);
+ FRIEND_TEST(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerCombination);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers);
};
diff --git a/statsd/src/matchers/CombinationAtomMatchingTracker.cpp b/statsd/src/matchers/CombinationAtomMatchingTracker.cpp
index 45685ce5..846a5308 100644
--- a/statsd/src/matchers/CombinationAtomMatchingTracker.cpp
+++ b/statsd/src/matchers/CombinationAtomMatchingTracker.cpp
@@ -36,12 +36,12 @@ CombinationAtomMatchingTracker::CombinationAtomMatchingTracker(const int64_t& id
CombinationAtomMatchingTracker::~CombinationAtomMatchingTracker() {
}
-bool CombinationAtomMatchingTracker::init(
+optional<InvalidConfigReason> CombinationAtomMatchingTracker::init(
const vector<AtomMatcher>& allAtomMatchers,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& matcherMap, vector<bool>& stack) {
if (mInitialized) {
- return true;
+ return nullopt;
}
// mark this node as visited in the recursion stack.
@@ -51,20 +51,26 @@ bool CombinationAtomMatchingTracker::init(
// LogicalOperation is missing in the config
if (!matcher.has_operation()) {
- return false;
+ return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_NO_OPERATION,
+ mId);
}
mLogicalOperation = matcher.operation();
if (mLogicalOperation == LogicalOperation::NOT && matcher.matcher_size() != 1) {
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_NOT_OPERATION_IS_NOT_UNARY, mId);
}
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);
- return false;
+ optional<InvalidConfigReason> invalidConfigReason =
+ createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND, mId);
+ invalidConfigReason->matcherIds.push_back(child);
+ return invalidConfigReason;
}
int childIndex = pair->second;
@@ -72,13 +78,18 @@ bool CombinationAtomMatchingTracker::init(
// if the child is a visited node in the recursion -> circle detected.
if (stack[childIndex]) {
ALOGE("Circle detected in matcher config");
- return false;
+ optional<InvalidConfigReason> invalidConfigReason =
+ createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_CYCLE, mId);
+ invalidConfigReason->matcherIds.push_back(child);
+ return invalidConfigReason;
}
-
- if (!allAtomMatchingTrackers[childIndex]->init(allAtomMatchers, allAtomMatchingTrackers,
- matcherMap, stack)) {
+ optional<InvalidConfigReason> invalidConfigReason =
+ allAtomMatchingTrackers[childIndex]->init(allAtomMatchers, allAtomMatchingTrackers,
+ matcherMap, stack);
+ if (invalidConfigReason.has_value()) {
ALOGW("child matcher init failed %lld", (long long)child);
- return false;
+ invalidConfigReason->matcherIds.push_back(mId);
+ return invalidConfigReason;
}
mChildren.push_back(childIndex);
@@ -90,10 +101,10 @@ bool CombinationAtomMatchingTracker::init(
mInitialized = true;
// unmark this node in the recursion stack.
stack[mIndex] = false;
- return true;
+ return nullopt;
}
-bool CombinationAtomMatchingTracker::onConfigUpdated(
+optional<InvalidConfigReason> CombinationAtomMatchingTracker::onConfigUpdated(
const AtomMatcher& matcher, const int index,
const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
mIndex = index;
@@ -103,11 +114,15 @@ bool CombinationAtomMatchingTracker::onConfigUpdated(
const auto& pair = atomMatchingTrackerMap.find(child);
if (pair == atomMatchingTrackerMap.end()) {
ALOGW("Matcher %lld not found in the config", (long long)child);
- return false;
+ optional<InvalidConfigReason> invalidConfigReason =
+ createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND, matcher.id());
+ invalidConfigReason->matcherIds.push_back(child);
+ return invalidConfigReason;
}
mChildren.push_back(pair->second);
}
- return true;
+ return nullopt;
}
void CombinationAtomMatchingTracker::onLogEvent(
diff --git a/statsd/src/matchers/CombinationAtomMatchingTracker.h b/statsd/src/matchers/CombinationAtomMatchingTracker.h
index cf02086b..edcbb49c 100644
--- a/statsd/src/matchers/CombinationAtomMatchingTracker.h
+++ b/statsd/src/matchers/CombinationAtomMatchingTracker.h
@@ -31,12 +31,14 @@ class CombinationAtomMatchingTracker : public AtomMatchingTracker {
public:
CombinationAtomMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash);
- bool init(const std::vector<AtomMatcher>& allAtomMatchers,
- const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- const std::unordered_map<int64_t, int>& matcherMap, std::vector<bool>& stack);
-
- bool onConfigUpdated(const AtomMatcher& matcher, const int index,
- const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override;
+ 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);
+
+ optional<InvalidConfigReason> onConfigUpdated(
+ const AtomMatcher& matcher, const int index,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override;
~CombinationAtomMatchingTracker();
diff --git a/statsd/src/matchers/SimpleAtomMatchingTracker.cpp b/statsd/src/matchers/SimpleAtomMatchingTracker.cpp
index 76bd4761..a0e30b24 100644
--- a/statsd/src/matchers/SimpleAtomMatchingTracker.cpp
+++ b/statsd/src/matchers/SimpleAtomMatchingTracker.cpp
@@ -42,20 +42,28 @@ SimpleAtomMatchingTracker::SimpleAtomMatchingTracker(const int64_t& id, const in
SimpleAtomMatchingTracker::~SimpleAtomMatchingTracker() {
}
-bool SimpleAtomMatchingTracker::init(const vector<AtomMatcher>& allAtomMatchers,
- const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- const unordered_map<int64_t, int>& matcherMap,
- vector<bool>& stack) {
+optional<InvalidConfigReason> SimpleAtomMatchingTracker::init(
+ const vector<AtomMatcher>& allAtomMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& matcherMap, vector<bool>& stack) {
// no need to do anything.
- return mInitialized;
+ if (!mInitialized) {
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_TRACKER_NOT_INITIALIZED, mId);
+ }
+ return nullopt;
}
-bool SimpleAtomMatchingTracker::onConfigUpdated(
+optional<InvalidConfigReason> SimpleAtomMatchingTracker::onConfigUpdated(
const AtomMatcher& matcher, const int index,
const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
mIndex = index;
// Do not need to update mMatcher since the matcher must be identical across the update.
- return mInitialized;
+ if (!mInitialized) {
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_TRACKER_NOT_INITIALIZED, mId);
+ }
+ return nullopt;
}
void SimpleAtomMatchingTracker::onLogEvent(
diff --git a/statsd/src/matchers/SimpleAtomMatchingTracker.h b/statsd/src/matchers/SimpleAtomMatchingTracker.h
index 13ef344d..70585f9b 100644
--- a/statsd/src/matchers/SimpleAtomMatchingTracker.h
+++ b/statsd/src/matchers/SimpleAtomMatchingTracker.h
@@ -35,13 +35,14 @@ public:
~SimpleAtomMatchingTracker();
- bool 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;
-
- bool onConfigUpdated(const AtomMatcher& matcher, const int index,
- const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override;
+ 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;
+
+ optional<InvalidConfigReason> onConfigUpdated(
+ const AtomMatcher& matcher, const int index,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap) override;
void onLogEvent(const LogEvent& event,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
diff --git a/statsd/src/metrics/CountMetricProducer.cpp b/statsd/src/metrics/CountMetricProducer.cpp
index cb141a22..db40b02e 100644
--- a/statsd/src/metrics/CountMetricProducer.cpp
+++ b/statsd/src/metrics/CountMetricProducer.cpp
@@ -119,7 +119,7 @@ CountMetricProducer::CountMetricProducer(
// Adjust start for partial bucket
mCurrentBucketStartTimeNs = startTimeNs;
- VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
+ VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)mMetricId,
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
@@ -127,7 +127,7 @@ CountMetricProducer::~CountMetricProducer() {
VLOG("~CountMetricProducer() called");
}
-bool CountMetricProducer::onConfigUpdatedLocked(
+optional<InvalidConfigReason> CountMetricProducer::onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -141,31 +141,35 @@ bool CountMetricProducer::onConfigUpdatedLocked(
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
- if (!MetricProducer::onConfigUpdatedLocked(
- config, configIndex, metricIndex, allAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
- allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
- trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason = MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
const CountMetric& metric = config.count_metric(configIndex);
int trackerIndex;
// Update appropriate indices, specifically mConditionIndex and MetricsManager maps.
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
- return false;
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), mMetricId, metricIndex, false, allAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
- if (metric.has_condition() &&
- !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, mConditionTrackerIndex,
- conditionToMetricMap)) {
- return false;
+ if (metric.has_condition()) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), mMetricId, metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, mConditionTrackerIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
- return true;
+ return nullopt;
}
void CountMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
diff --git a/statsd/src/metrics/CountMetricProducer.h b/statsd/src/metrics/CountMetricProducer.h
index 93984670..830a1146 100644
--- a/statsd/src/metrics/CountMetricProducer.h
+++ b/statsd/src/metrics/CountMetricProducer.h
@@ -97,7 +97,7 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
- bool onConfigUpdatedLocked(
+ optional<InvalidConfigReason> onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
diff --git a/statsd/src/metrics/DurationMetricProducer.cpp b/statsd/src/metrics/DurationMetricProducer.cpp
index ec0af844..04cecbb4 100644
--- a/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/statsd/src/metrics/DurationMetricProducer.cpp
@@ -114,6 +114,7 @@ DurationMetricProducer::DurationMetricProducer(
// Dimensions in what must be subset of internal dimensions
if (!subsetDimensions(mDimensionsInWhat, mInternalDimensions)) {
ALOGE("Dimensions in what must be a subset of the internal dimensions");
+ // TODO: Add invalidConfigReason
mValid = false;
}
@@ -127,6 +128,7 @@ DurationMetricProducer::DurationMetricProducer(
translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
if (!subsetDimensions(mc.metricFields, mInternalDimensions)) {
ALOGE(("Condition links must be a subset of the internal dimensions"));
+ // TODO: Add invalidConfigReason
mValid = false;
}
mMetric2ConditionLinks.push_back(mc);
@@ -142,6 +144,7 @@ DurationMetricProducer::DurationMetricProducer(
translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
if (!subsetDimensions(ms.metricFields, mInternalDimensions)) {
ALOGE(("State links must be a subset of the dimensions in what internal dimensions"));
+ // TODO: Add invalidConfigReason
mValid = false;
}
mMetric2StateLinks.push_back(ms);
@@ -156,7 +159,7 @@ DurationMetricProducer::DurationMetricProducer(
flushIfNeededLocked(startTimeNs);
// Adjust start for partial bucket
mCurrentBucketStartTimeNs = startTimeNs;
- VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
+ VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)mMetricId,
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
initTrueDimensions(whatIndex, startTimeNs);
@@ -166,7 +169,7 @@ DurationMetricProducer::~DurationMetricProducer() {
VLOG("~DurationMetric() called");
}
-bool DurationMetricProducer::onConfigUpdatedLocked(
+optional<InvalidConfigReason> DurationMetricProducer::onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -180,68 +183,76 @@ bool DurationMetricProducer::onConfigUpdatedLocked(
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
- if (!MetricProducer::onConfigUpdatedLocked(
- config, configIndex, metricIndex, allAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
- allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
- trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason = MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
const DurationMetric& metric = config.duration_metric(configIndex);
const auto& what_it = conditionTrackerMap.find(metric.what());
if (what_it == conditionTrackerMap.end()) {
ALOGE("DurationMetric's \"what\" is not present in the config");
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_FOUND, mMetricId, metric.what());
}
const Predicate& durationWhat = config.predicate(what_it->second);
if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
ALOGE("DurationMetric's \"what\" must be a simple condition");
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_SIMPLE, mMetricId, metric.what());
}
const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
// Update indices: mStartIndex, mStopIndex, mStopAllIndex, mConditionIndex and MetricsManager
// maps.
- if (!handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, mStartIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ simplePredicate.start(), mMetricId, metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, trackerToMetricMap, mStartIndex);
+ if (invalidConfigReason.has_value()) {
ALOGE("Duration metrics must specify a valid start event matcher");
- return false;
+ return invalidConfigReason;
}
- if (simplePredicate.has_stop() &&
- !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, mStopIndex)) {
- return false;
+ if (simplePredicate.has_stop()) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ simplePredicate.stop(), mMetricId, metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, trackerToMetricMap, mStopIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
- if (simplePredicate.has_stop_all() &&
- !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, mStopAllIndex)) {
- return false;
+ if (simplePredicate.has_stop_all()) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ simplePredicate.stop_all(), mMetricId, metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, trackerToMetricMap,
+ mStopAllIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
- if (metric.has_condition() &&
- !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, mConditionTrackerIndex,
- conditionToMetricMap)) {
- return false;
+ if (metric.has_condition()) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), mMetricId, metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, mConditionTrackerIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
for (const auto& it : mCurrentSlicedDurationTrackerMap) {
it.second->onConfigUpdated(wizard, mConditionTrackerIndex);
}
- return true;
+ return nullopt;
}
void DurationMetricProducer::initTrueDimensions(const int whatIndex, const int64_t startTimeNs) {
@@ -702,6 +713,10 @@ void DurationMetricProducer::handleMatchedLogEventValuesLocked(const size_t matc
return;
}
+ if (!passesSampleCheckLocked(values)) {
+ return;
+ }
+
HashableDimensionKey dimensionInWhat = DEFAULT_DIMENSION_KEY;
if (!mDimensionsInWhat.empty()) {
filterValues(mDimensionsInWhat, values, &dimensionInWhat);
diff --git a/statsd/src/metrics/DurationMetricProducer.h b/statsd/src/metrics/DurationMetricProducer.h
index ba5fe958..831388b0 100644
--- a/statsd/src/metrics/DurationMetricProducer.h
+++ b/statsd/src/metrics/DurationMetricProducer.h
@@ -123,7 +123,7 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
- bool onConfigUpdatedLocked(
+ optional<InvalidConfigReason> onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
diff --git a/statsd/src/metrics/EventMetricProducer.cpp b/statsd/src/metrics/EventMetricProducer.cpp
index 502ea8ad..dd679193 100644
--- a/statsd/src/metrics/EventMetricProducer.cpp
+++ b/statsd/src/metrics/EventMetricProducer.cpp
@@ -78,7 +78,7 @@ EventMetricProducer::EventMetricProducer(
mConditionSliced = true;
}
mTotalSize = 0;
- VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
+ VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)mMetricId,
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
@@ -86,7 +86,7 @@ EventMetricProducer::~EventMetricProducer() {
VLOG("~EventMetricProducer() called");
}
-bool EventMetricProducer::onConfigUpdatedLocked(
+optional<InvalidConfigReason> EventMetricProducer::onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -100,31 +100,35 @@ bool EventMetricProducer::onConfigUpdatedLocked(
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
- if (!MetricProducer::onConfigUpdatedLocked(
- config, configIndex, metricIndex, allAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
- allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
- trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason = MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
const EventMetric& metric = config.event_metric(configIndex);
int trackerIndex;
// Update appropriate indices, specifically mConditionIndex and MetricsManager maps.
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
- return false;
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), mMetricId, metricIndex, false, allAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
- if (metric.has_condition() &&
- !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, mConditionTrackerIndex,
- conditionToMetricMap)) {
- return false;
+ if (metric.has_condition()) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), mMetricId, metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, mConditionTrackerIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
- return true;
+ return nullopt;
}
void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
diff --git a/statsd/src/metrics/EventMetricProducer.h b/statsd/src/metrics/EventMetricProducer.h
index 76747b67..fc3e79db 100644
--- a/statsd/src/metrics/EventMetricProducer.h
+++ b/statsd/src/metrics/EventMetricProducer.h
@@ -70,7 +70,7 @@ private:
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
- bool onConfigUpdatedLocked(
+ optional<InvalidConfigReason> onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
diff --git a/statsd/src/metrics/GaugeMetricProducer.cpp b/statsd/src/metrics/GaugeMetricProducer.cpp
index f8b9de1e..cb615124 100644
--- a/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -141,8 +141,7 @@ GaugeMetricProducer::GaugeMetricProducer(
mCurrentBucketStartTimeNs = startTimeNs;
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
- (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
- mConditionSliced);
+ (long long)mMetricId, (long long)mBucketSizeNs, (long long)mTimeBaseNs, mConditionSliced);
}
GaugeMetricProducer::~GaugeMetricProducer() {
@@ -152,7 +151,7 @@ GaugeMetricProducer::~GaugeMetricProducer() {
}
}
-bool GaugeMetricProducer::onConfigUpdatedLocked(
+optional<InvalidConfigReason> GaugeMetricProducer::onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -166,38 +165,45 @@ bool GaugeMetricProducer::onConfigUpdatedLocked(
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
- if (!MetricProducer::onConfigUpdatedLocked(
- config, configIndex, metricIndex, allAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
- allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
- trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason = MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
const GaugeMetric& metric = config.gauge_metric(configIndex);
// Update appropriate indices: mWhatMatcherIndex, mConditionIndex and MetricsManager maps.
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, /*enforceOneAtom=*/false,
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, mWhatMatcherIndex)) {
- return false;
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), mMetricId, metricIndex, /*enforceOneAtom=*/false,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, trackerToMetricMap,
+ mWhatMatcherIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
// Need to update maps since the index changed, but mTriggerAtomId will not change.
int triggerTrackerIndex;
- if (metric.has_trigger_event() &&
- !handleMetricWithAtomMatchingTrackers(metric.trigger_event(), metricIndex,
- /*enforceOneAtom=*/true, allAtomMatchingTrackers,
- newAtomMatchingTrackerMap, trackerToMetricMap,
- triggerTrackerIndex)) {
- return false;
+ if (metric.has_trigger_event()) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.trigger_event(), mMetricId, metricIndex,
+ /*enforceOneAtom=*/true, allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, triggerTrackerIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
- if (metric.has_condition() &&
- !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, mConditionTrackerIndex,
- conditionToMetricMap)) {
- return false;
+ if (metric.has_condition()) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), mMetricId, metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, mConditionTrackerIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
sp<EventMatcherWizard> tmpEventWizard = mEventMatcherWizard;
mEventMatcherWizard = matcherWizard;
@@ -208,7 +214,7 @@ bool GaugeMetricProducer::onConfigUpdatedLocked(
mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
}
- return true;
+ return nullopt;
}
void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
@@ -477,9 +483,9 @@ std::shared_ptr<vector<FieldValue>> GaugeMetricProducer::getGaugeFields(const Lo
}
void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
- bool pullSuccess, int64_t originalPullTimeNs) {
+ PullResult pullResult, int64_t originalPullTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
- if (!pullSuccess || allData.size() == 0) {
+ if (pullResult != PullResult::PULL_RESULT_SUCCESS || allData.size() == 0) {
return;
}
const int64_t pullDelayNs = getElapsedRealtimeNs() - originalPullTimeNs;
diff --git a/statsd/src/metrics/GaugeMetricProducer.h b/statsd/src/metrics/GaugeMetricProducer.h
index af995359..f0a59ce1 100644
--- a/statsd/src/metrics/GaugeMetricProducer.h
+++ b/statsd/src/metrics/GaugeMetricProducer.h
@@ -76,8 +76,14 @@ public:
virtual ~GaugeMetricProducer();
// Handles when the pulled data arrives.
- void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
- bool pullSuccess, int64_t originalPullTimeNs) override;
+ void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data, PullResult pullResult,
+ int64_t originalPullTimeNs) override;
+
+ // Determine if metric needs to pull
+ bool isPullNeeded() const override {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mIsActive && (mCondition == ConditionState::kTrue);
+ };
// GaugeMetric needs to immediately trigger another pull when we create the partial bucket.
void notifyAppUpgradeInternalLocked(const int64_t eventTimeNs) override {
@@ -143,7 +149,7 @@ private:
// Only call if mCondition == ConditionState::kTrue && metric is active.
void pullAndMatchEventsLocked(const int64_t timestampNs);
- bool onConfigUpdatedLocked(
+ optional<InvalidConfigReason> onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -221,6 +227,7 @@ private:
FRIEND_TEST(GaugeMetricProducerTest, TestFirstBucket);
FRIEND_TEST(GaugeMetricProducerTest, TestPullOnTrigger);
FRIEND_TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput);
+ FRIEND_TEST(GaugeMetricProducerTest, TestPullDimensionalSampling);
FRIEND_TEST(GaugeMetricProducerTest_PartialBucket, TestPushedEvents);
FRIEND_TEST(GaugeMetricProducerTest_PartialBucket, TestPulled);
diff --git a/statsd/src/metrics/KllMetricProducer.cpp b/statsd/src/metrics/KllMetricProducer.cpp
index e5658a93..91f22f41 100644
--- a/statsd/src/metrics/KllMetricProducer.cpp
+++ b/statsd/src/metrics/KllMetricProducer.cpp
@@ -76,7 +76,7 @@ KllMetricProducer::DumpProtoFields KllMetricProducer::getDumpProtoFields() const
}
void KllMetricProducer::writePastBucketAggregateToProto(
- const int aggIndex, const unique_ptr<KllQuantile>& kll,
+ const int aggIndex, const unique_ptr<KllQuantile>& kll, const int sampleSize,
ProtoOutputStream* const protoOutput) const {
uint64_t sketchesToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SKETCHES);
diff --git a/statsd/src/metrics/KllMetricProducer.h b/statsd/src/metrics/KllMetricProducer.h
index b1c59f27..c1421139 100644
--- a/statsd/src/metrics/KllMetricProducer.h
+++ b/statsd/src/metrics/KllMetricProducer.h
@@ -99,6 +99,7 @@ private:
void writePastBucketAggregateToProto(const int aggIndex,
const std::unique_ptr<KllQuantile>& kll,
+ const int sampleSize,
ProtoOutputStream* const protoOutput) const override;
bool aggregateFields(const int64_t eventTimeNs, const MetricDimensionKey& eventKey,
diff --git a/statsd/src/metrics/MetricProducer.cpp b/statsd/src/metrics/MetricProducer.cpp
index 93f044b9..137510e6 100644
--- a/statsd/src/metrics/MetricProducer.cpp
+++ b/statsd/src/metrics/MetricProducer.cpp
@@ -74,10 +74,12 @@ MetricProducer::MetricProducer(
mSlicedStateAtoms(slicedStateAtoms),
mStateGroupMap(stateGroupMap),
mSplitBucketForAppUpgrade(splitBucketForAppUpgrade),
- mHasHitGuardrail(false) {
+ mHasHitGuardrail(false),
+ mSampledWhatFields({}),
+ mShardCount(0) {
}
-bool MetricProducer::onConfigUpdatedLocked(
+optional<InvalidConfigReason> MetricProducer::onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -96,17 +98,18 @@ bool MetricProducer::onConfigUpdatedLocked(
unordered_map<int, shared_ptr<Activation>> newEventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> newEventDeactivationMap;
- if (!handleMetricActivationOnConfigUpdate(
- config, mMetricId, metricIndex, metricToActivationMap, oldAtomMatchingTrackerMap,
- newAtomMatchingTrackerMap, mEventActivationMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, newEventActivationMap,
- newEventDeactivationMap)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason = handleMetricActivationOnConfigUpdate(
+ config, mMetricId, metricIndex, metricToActivationMap, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, mEventActivationMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, newEventActivationMap,
+ newEventDeactivationMap);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
mEventActivationMap = newEventActivationMap;
mEventDeactivationMap = newEventDeactivationMap;
mAnomalyTrackers.clear();
- return true;
+ return nullopt;
}
void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
@@ -119,6 +122,10 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo
return;
}
+ if (!passesSampleCheckLocked(event.getValues())) {
+ return;
+ }
+
bool condition;
ConditionKey conditionKey;
if (mConditionSliced) {
@@ -361,6 +368,21 @@ bool MetricProducer::maxDropEventsReached() const {
return mCurrentSkippedBucket.dropEvents.size() >= StatsdStats::kMaxLoggedBucketDropEvents;
}
+bool MetricProducer::passesSampleCheckLocked(const vector<FieldValue>& values) const {
+ // Only perform sampling if shard count is correct and there is a sampled what field.
+ if (mShardCount <= 1 || mSampledWhatFields.size() == 0) {
+ return true;
+ }
+ // If filtering fails, don't perform sampling. Event could be a gauge trigger event or stop all
+ // event.
+ FieldValue sampleFieldValue;
+ if (!filterValues(mSampledWhatFields[0], values, &sampleFieldValue)) {
+ return true;
+ }
+ return shouldKeepSample(sampleFieldValue, ShardOffsetProvider::getInstance().getShardOffset(),
+ mShardCount);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/metrics/MetricProducer.h b/statsd/src/metrics/MetricProducer.h
index 7d21cd0a..b8bd6fa3 100644
--- a/statsd/src/metrics/MetricProducer.h
+++ b/statsd/src/metrics/MetricProducer.h
@@ -26,11 +26,13 @@
#include "anomaly/AnomalyTracker.h"
#include "condition/ConditionWizard.h"
#include "config/ConfigKey.h"
+#include "guardrail/StatsdStats.h"
#include "matchers/EventMatcherWizard.h"
#include "matchers/matcher_util.h"
#include "packages/PackageInfoListener.h"
#include "state/StateListener.h"
#include "state/StateManager.h"
+#include "utils/ShardOffsetProvider.h"
namespace android {
namespace os {
@@ -132,6 +134,13 @@ struct SkippedBucket {
}
};
+struct SamplingInfo {
+ // Matchers for sampled fields. Currently only one sampled dimension is supported.
+ std::vector<Matcher> sampledWhatFields;
+
+ int shardCount = 0;
+};
+
template <class T>
optional<bool> getAppUpgradeBucketSplit(const T& metric) {
return metric.has_split_bucket_for_app_upgrade()
@@ -166,7 +175,7 @@ public:
// This metric and all of its dependencies are guaranteed to be preserved across the update.
// This function also updates several maps used by metricsManager.
// This function clears all anomaly trackers. All anomaly trackers need to be added again.
- bool onConfigUpdated(
+ optional<InvalidConfigReason> onConfigUpdated(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -253,7 +262,7 @@ public:
dumpLatency, str_set, protoOutput);
}
- virtual bool onConfigUpdatedLocked(
+ virtual optional<InvalidConfigReason> onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -371,6 +380,12 @@ public:
std::lock_guard<std::mutex> lock(mMutex);
mAnomalyTrackers.push_back(anomalyTracker);
}
+
+ void setSamplingInfo(SamplingInfo samplingInfo) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mSampledWhatFields.swap(samplingInfo.sampledWhatFields);
+ mShardCount = samplingInfo.shardCount;
+ }
// End: getters/setters
protected:
/**
@@ -485,6 +500,8 @@ protected:
// exceeded the maximum number allowed, which is currently capped at 10.
bool maxDropEventsReached() const;
+ bool passesSampleCheckLocked(const vector<FieldValue>& values) const;
+
const int64_t mMetricId;
// Hash of the Metric's proto bytes from StatsdConfig, including any activations.
@@ -566,6 +583,11 @@ protected:
// If hard dimension guardrail is hit, do not spam logcat
bool mHasHitGuardrail;
+ // Matchers for sampled fields. Currently only one sampled dimension is supported.
+ std::vector<Matcher> mSampledWhatFields;
+
+ int mShardCount;
+
FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
@@ -603,7 +625,8 @@ protected:
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
- FRIEND_TEST(MetricsManagerTest, TestInitialConditions);
+ FRIEND_TEST(MetricsManagerUtilTest, TestInitialConditions);
+ FRIEND_TEST(MetricsManagerUtilTest, TestSampledMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricActivations);
FRIEND_TEST(ConfigUpdateTest, TestUpdateCountMetrics);
diff --git a/statsd/src/metrics/MetricsManager.cpp b/statsd/src/metrics/MetricsManager.cpp
index d192476b..156d7c21 100644
--- a/statsd/src/metrics/MetricsManager.cpp
+++ b/statsd/src/metrics/MetricsManager.cpp
@@ -82,7 +82,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
// Init the ttl end timestamp.
refreshTtl(timeBaseNs);
- mConfigValid = initStatsdConfig(
+ mInvalidConfigReason = initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mTagIdsToMatchersMap, mAllAtomMatchingTrackers,
mAtomMatchingTrackerMap, mAllConditionTrackers, mConditionTrackerMap,
@@ -139,7 +139,7 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
mDeactivationAtomTrackerToMetricMap.clear();
mMetricIndexesWithActivation.clear();
mNoReportMetricIds.clear();
- mConfigValid = updateStatsdConfig(
+ mInvalidConfigReason = updateStatsdConfig(
mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mMetricProducerMap,
@@ -188,15 +188,16 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
verifyGuardrailsAndUpdateStatsdStats();
initializeConfigActiveStatus();
- return mConfigValid;
+ return !mInvalidConfigReason.has_value();
}
void MetricsManager::createAllLogSourcesFromConfig(const StatsdConfig& config) {
// Init allowed pushed atom uids.
if (config.allowed_log_source_size() == 0) {
- mConfigValid = false;
ALOGE("Log source allowlist is empty! This config won't get any data. Suggest adding at "
"least AID_SYSTEM and AID_STATSD to the allowed_log_source field.");
+ mInvalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_LOG_SOURCE_ALLOWLIST_EMPTY);
} else {
for (const auto& source : config.allowed_log_source()) {
auto it = UidMap::sAidToUidMapping.find(source);
@@ -209,7 +210,7 @@ void MetricsManager::createAllLogSourcesFromConfig(const StatsdConfig& config) {
if (mAllowedUid.size() + mAllowedPkg.size() > StatsdStats::kMaxLogSourceCount) {
ALOGE("Too many log sources. This is likely to be an error in the config.");
- mConfigValid = false;
+ mInvalidConfigReason = InvalidConfigReason(INVALID_CONFIG_REASON_TOO_MANY_LOG_SOURCES);
} else {
initAllowedLogSources();
}
@@ -224,7 +225,8 @@ void MetricsManager::createAllLogSourcesFromConfig(const StatsdConfig& config) {
mDefaultPullUids.insert(it->second);
} else {
ALOGE("Default pull atom packages must be in sAidToUidMapping");
- mConfigValid = false;
+ mInvalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_DEFAULT_PULL_PACKAGES_NOT_IN_MAP);
}
}
// Init per-atom pull atom packages.
@@ -243,7 +245,8 @@ void MetricsManager::createAllLogSourcesFromConfig(const StatsdConfig& config) {
if (numPullPackages > StatsdStats::kMaxPullAtomPackages) {
ALOGE("Too many sources in default_pull_packages and pull_atom_packages. This is likely to "
"be an error in the config");
- mConfigValid = false;
+ mInvalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_TOO_MANY_SOURCES_IN_PULL_PACKAGES);
} else {
initPullAtomSources();
}
@@ -251,21 +254,27 @@ void MetricsManager::createAllLogSourcesFromConfig(const StatsdConfig& config) {
void MetricsManager::verifyGuardrailsAndUpdateStatsdStats() {
// Guardrail. Reject the config if it's too big.
- if (mAllMetricProducers.size() > StatsdStats::kMaxMetricCountPerConfig ||
- mAllConditionTrackers.size() > StatsdStats::kMaxConditionCountPerConfig ||
- mAllAtomMatchingTrackers.size() > StatsdStats::kMaxMatcherCountPerConfig) {
- ALOGE("This config is too big! Reject!");
- mConfigValid = false;
+ if (mAllMetricProducers.size() > StatsdStats::kMaxMetricCountPerConfig) {
+ ALOGE("This config has too many metrics! Reject!");
+ mInvalidConfigReason = InvalidConfigReason(INVALID_CONFIG_REASON_TOO_MANY_METRICS);
+ }
+ if (mAllConditionTrackers.size() > StatsdStats::kMaxConditionCountPerConfig) {
+ ALOGE("This config has too many predicates! Reject!");
+ mInvalidConfigReason = InvalidConfigReason(INVALID_CONFIG_REASON_TOO_MANY_CONDITIONS);
+ }
+ if (mAllAtomMatchingTrackers.size() > StatsdStats::kMaxMatcherCountPerConfig) {
+ ALOGE("This config has too many matchers! Reject!");
+ mInvalidConfigReason = InvalidConfigReason(INVALID_CONFIG_REASON_TOO_MANY_MATCHERS);
}
if (mAllAnomalyTrackers.size() > StatsdStats::kMaxAlertCountPerConfig) {
ALOGE("This config has too many alerts! Reject!");
- mConfigValid = false;
+ mInvalidConfigReason = InvalidConfigReason(INVALID_CONFIG_REASON_TOO_MANY_ALERTS);
}
// no matter whether this config is valid, log it in the stats.
StatsdStats::getInstance().noteConfigReceived(
mConfigKey, mAllMetricProducers.size(), mAllConditionTrackers.size(),
mAllAtomMatchingTrackers.size(), mAllAnomalyTrackers.size(), mAnnotations,
- mConfigValid);
+ mInvalidConfigReason);
}
void MetricsManager::initializeConfigActiveStatus() {
@@ -309,7 +318,7 @@ void MetricsManager::initPullAtomSources() {
}
bool MetricsManager::isConfigValid() const {
- return mConfigValid;
+ return !mInvalidConfigReason.has_value();
}
void MetricsManager::notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
@@ -526,7 +535,7 @@ bool MetricsManager::eventSanityCheck(const LogEvent& event) {
// Consume the stats log if it's interesting to this metric.
void MetricsManager::onLogEvent(const LogEvent& event) {
- if (!mConfigValid) {
+ if (!isConfigValid()) {
return;
}
diff --git a/statsd/src/metrics/MetricsManager.h b/statsd/src/metrics/MetricsManager.h
index c855a050..94879f15 100644
--- a/statsd/src/metrics/MetricsManager.h
+++ b/statsd/src/metrics/MetricsManager.h
@@ -16,20 +16,21 @@
#pragma once
+#include <unordered_map>
+
#include "anomaly/AlarmMonitor.h"
#include "anomaly/AlarmTracker.h"
#include "anomaly/AnomalyTracker.h"
#include "condition/ConditionTracker.h"
#include "config/ConfigKey.h"
#include "external/StatsPullerManager.h"
-#include "src/statsd_config.pb.h"
-#include "src/statsd_metadata.pb.h"
+#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "matchers/AtomMatchingTracker.h"
#include "metrics/MetricProducer.h"
#include "packages/UidMap.h"
-
-#include <unordered_map>
+#include "src/statsd_config.pb.h"
+#include "src/statsd_metadata.pb.h"
namespace android {
namespace os {
@@ -168,8 +169,6 @@ private:
sp<UidMap> mUidMap;
- bool mConfigValid = false;
-
bool mHashStringsInReport = false;
bool mVersionStringsInReport = false;
bool mInstallerInReport = false;
@@ -181,6 +180,8 @@ private:
int64_t mLastReportTimeNs;
int64_t mLastReportWallClockNs;
+ optional<InvalidConfigReason> mInvalidConfigReason;
+
sp<StatsPullerManager> mPullerManager;
// The uid log sources from StatsdConfig.
@@ -294,11 +295,12 @@ private:
void initPullAtomSources();
// Only called on config creation/update to initialize log sources from the config.
- // Calls initAllowedLogSources and initPullAtomSources. Sets mConfigValid to false on error.
+ // Calls initAllowedLogSources and initPullAtomSources. Sets up mInvalidConfigReason on
+ // error.
void createAllLogSourcesFromConfig(const StatsdConfig& config);
// Verifies the config meets guardrails and updates statsdStats.
- // Sets mConfigValid to false on error. Should be called on config creation/update
+ // Sets up mInvalidConfigReason on error. Should be called on config creation/update
void verifyGuardrailsAndUpdateStatsdStats();
// Initializes mIsAlwaysActive and mIsActive.
@@ -328,15 +330,16 @@ private:
FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition);
FRIEND_TEST(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
- FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_single_bucket);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest,
+ TestCountMetric_save_refractory_to_disk_no_data_written);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestCountMetric_save_refractory_to_disk);
+ FRIEND_TEST(AnomalyCountDetectionE2eTest, TestCountMetric_load_refractory_from_disk);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
@@ -350,6 +353,7 @@ private:
FRIEND_TEST(MetricsManagerTest, TestLogSources);
FRIEND_TEST(MetricsManagerTest, TestLogSourcesOnConfigUpdate);
FRIEND_TEST(MetricsManagerTest_SPlus, TestAtomMatcherOptimizationEnabledFlag);
+ FRIEND_TEST(MetricsManagerUtilTest, TestSampledMetrics);
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
@@ -384,6 +388,7 @@ private:
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
+ FRIEND_TEST(GaugeMetricE2ePushedTest, TestDimensionalSampling);
};
} // namespace statsd
diff --git a/statsd/src/metrics/NumericValueMetricProducer.cpp b/statsd/src/metrics/NumericValueMetricProducer.cpp
index 58abc431..12c8c043 100644
--- a/statsd/src/metrics/NumericValueMetricProducer.cpp
+++ b/statsd/src/metrics/NumericValueMetricProducer.cpp
@@ -50,6 +50,7 @@ const int FIELD_ID_VALUE_METRICS = 7;
const int FIELD_ID_VALUE_INDEX = 1;
const int FIELD_ID_VALUE_LONG = 2;
const int FIELD_ID_VALUE_DOUBLE = 3;
+const int FIELD_ID_VALUE_SAMPLESIZE = 4;
const int FIELD_ID_VALUES = 9;
const int FIELD_ID_BUCKET_NUM = 4;
const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
@@ -71,6 +72,9 @@ NumericValueMetricProducer::NumericValueMetricProducer(
conditionOptions, stateOptions, activationOptions, guardrailOptions),
mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()),
mAggregationType(metric.aggregation_type()),
+ mIncludeSampleSize(metric.has_include_sample_size()
+ ? metric.include_sample_size()
+ : metric.aggregation_type() == ValueMetric_AggregationType_AVG),
mUseDiff(metric.has_use_diff() ? metric.use_diff() : isPulled()),
mValueDirection(metric.value_direction()),
mSkipZeroDiffOutput(metric.skip_zero_diff_output()),
@@ -112,10 +116,14 @@ void NumericValueMetricProducer::resetBase() {
}
void NumericValueMetricProducer::writePastBucketAggregateToProto(
- const int aggIndex, const Value& value, ProtoOutputStream* const protoOutput) const {
+ const int aggIndex, const Value& value, const int sampleSize,
+ ProtoOutputStream* const protoOutput) const {
uint64_t valueToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_VALUES);
protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_VALUE_INDEX, aggIndex);
+ if (mIncludeSampleSize) {
+ protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_VALUE_SAMPLESIZE, sampleSize);
+ }
if (value.getType() == LONG) {
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_LONG, (long long)value.long_value);
VLOG("\t\t value %d: %lld", aggIndex, (long long)value.long_value);
@@ -175,14 +183,14 @@ int64_t NumericValueMetricProducer::calcPreviousBucketEndTime(const int64_t curr
// By design, statsd pulls data at bucket boundaries using AlarmManager. These pulls are likely
// to be delayed. Other events like condition changes or app upgrade which are not based on
// AlarmManager might have arrived earlier and close the bucket.
-void NumericValueMetricProducer::onDataPulled(const vector<shared_ptr<LogEvent>>& allData,
- bool pullSuccess, int64_t originalPullTimeNs) {
+void NumericValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
+ PullResult pullResult, int64_t originalPullTimeNs) {
lock_guard<mutex> lock(mMutex);
if (mCondition == ConditionState::kTrue) {
// If the pull failed, we won't be able to compute a diff.
- if (!pullSuccess) {
+ if (pullResult == PullResult::PULL_RESULT_FAIL) {
invalidateCurrentBucket(originalPullTimeNs, BucketDropReason::PULL_FAILED);
- } else {
+ } else if (pullResult == PullResult::PULL_RESULT_SUCCESS) {
bool isEventLate = originalPullTimeNs < getCurrentBucketEndTimeNs();
if (isEventLate) {
// If the event is late, we are in the middle of a bucket. Just
@@ -527,6 +535,9 @@ PastBucket<Value> NumericValueMetricProducer::buildPartialBucket(int64_t bucketE
bucket.aggIndex.push_back(interval.aggIndex);
bucket.aggregates.push_back(getFinalValue(interval));
+ if (mIncludeSampleSize) {
+ bucket.sampleSizes.push_back(interval.sampleSize);
+ }
}
return bucket;
}
diff --git a/statsd/src/metrics/NumericValueMetricProducer.h b/statsd/src/metrics/NumericValueMetricProducer.h
index 0c8b1876..78c414fc 100644
--- a/statsd/src/metrics/NumericValueMetricProducer.h
+++ b/statsd/src/metrics/NumericValueMetricProducer.h
@@ -39,9 +39,15 @@ public:
const GuardrailOptions& guardrailOptions);
// Process data pulled on bucket boundary.
- void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data, bool pullSuccess,
+ void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData, PullResult pullResult,
int64_t originalPullTimeNs) override;
+ // Determine if metric needs to pull
+ bool isPullNeeded() const override {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mIsActive && (mCondition == ConditionState::kTrue);
+ }
+
inline MetricType getMetricType() const override {
return METRIC_TYPE_VALUE;
}
@@ -130,6 +136,7 @@ private:
DumpProtoFields getDumpProtoFields() const override;
void writePastBucketAggregateToProto(const int aggIndex, const Value& value,
+ const int sampleSize,
ProtoOutputStream* const protoOutput) const override;
// Internal function to calculate the current used bytes.
@@ -142,6 +149,8 @@ private:
const ValueMetric::AggregationType mAggregationType;
+ const bool mIncludeSampleSize;
+
const bool mUseDiff;
const ValueMetric::ValueDirection mValueDirection;
@@ -204,6 +213,7 @@ private:
TestResetBaseOnPullFailAfterConditionChange_EndOfBucket);
FRIEND_TEST(NumericValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange);
FRIEND_TEST(NumericValueMetricProducerTest, TestResetBaseOnPullTooLate);
+ FRIEND_TEST(NumericValueMetricProducerTest, TestSampleSize);
FRIEND_TEST(NumericValueMetricProducerTest, TestSkipZeroDiffOutput);
FRIEND_TEST(NumericValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue);
FRIEND_TEST(NumericValueMetricProducerTest, TestSlicedState);
diff --git a/statsd/src/metrics/ValueMetricProducer.cpp b/statsd/src/metrics/ValueMetricProducer.cpp
index 48a86afc..33a29afb 100644
--- a/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/statsd/src/metrics/ValueMetricProducer.cpp
@@ -174,7 +174,8 @@ void ValueMetricProducer<AggregatedValue, DimExtras>::notifyAppUpgradeInternalLo
}
template <typename AggregatedValue, typename DimExtras>
-bool ValueMetricProducer<AggregatedValue, DimExtras>::onConfigUpdatedLocked(
+optional<InvalidConfigReason>
+ValueMetricProducer<AggregatedValue, DimExtras>::onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -188,35 +189,37 @@ bool ValueMetricProducer<AggregatedValue, DimExtras>::onConfigUpdatedLocked(
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
- if (!MetricProducer::onConfigUpdatedLocked(
- config, configIndex, metricIndex, allAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
- allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
- trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason = MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
-
// Update appropriate indices: mWhatMatcherIndex, mConditionIndex and MetricsManager maps.
const int64_t atomMatcherId = getWhatAtomMatcherIdForMetric(config, configIndex);
- if (!handleMetricWithAtomMatchingTrackers(atomMatcherId, metricIndex, /*enforceOneAtom=*/false,
- allAtomMatchingTrackers, newAtomMatchingTrackerMap,
- trackerToMetricMap, mWhatMatcherIndex)) {
- return false;
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ atomMatcherId, mMetricId, metricIndex, /*enforceOneAtom=*/false,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, trackerToMetricMap,
+ mWhatMatcherIndex);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
-
const optional<int64_t>& conditionIdOpt = getConditionIdForMetric(config, configIndex);
const ConditionLinks& conditionLinks = getConditionLinksForMetric(config, configIndex);
- if (conditionIdOpt.has_value() &&
- !handleMetricWithConditions(conditionIdOpt.value(), metricIndex, conditionTrackerMap,
- conditionLinks, allConditionTrackers, mConditionTrackerIndex,
- conditionToMetricMap)) {
- return false;
+ if (conditionIdOpt.has_value()) {
+ invalidConfigReason = handleMetricWithConditions(
+ conditionIdOpt.value(), mMetricId, metricIndex, conditionTrackerMap, conditionLinks,
+ allConditionTrackers, mConditionTrackerIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
+ }
}
-
sp<EventMatcherWizard> tmpEventWizard = mEventMatcherWizard;
mEventMatcherWizard = matcherWizard;
- return true;
+ return nullopt;
}
template <typename AggregatedValue, typename DimExtras>
@@ -422,8 +425,9 @@ void ValueMetricProducer<AggregatedValue, DimExtras>::onDumpReportLocked(
for (int i = 0; i < (int)bucket.aggIndex.size(); i++) {
VLOG("\t bucket [%lld - %lld]", (long long)bucket.mBucketStartNs,
(long long)bucket.mBucketEndNs);
+ int sampleSize = !bucket.sampleSizes.empty() ? bucket.sampleSizes[i] : 0;
writePastBucketAggregateToProto(bucket.aggIndex[i], bucket.aggregates[i],
- protoOutput);
+ sampleSize, protoOutput);
}
protoOutput->end(bucketInfoToken);
}
diff --git a/statsd/src/metrics/ValueMetricProducer.h b/statsd/src/metrics/ValueMetricProducer.h
index bf87c543..1c974b52 100644
--- a/statsd/src/metrics/ValueMetricProducer.h
+++ b/statsd/src/metrics/ValueMetricProducer.h
@@ -43,6 +43,7 @@ struct PastBucket {
int64_t mBucketEndNs;
std::vector<int> aggIndex;
std::vector<AggregatedValue> aggregates;
+ std::vector<int> sampleSizes;
/**
* If the metric has no condition, then this field is just wasted.
@@ -117,10 +118,14 @@ public:
virtual ~ValueMetricProducer();
// Process data pulled on bucket boundary.
- virtual void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data, bool pullSuccess,
- int64_t originalPullTimeNs) override {
+ virtual void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
+ PullResult pullResult, int64_t originalPullTimeNs) override {
}
+ // Determine if metric needs to pull
+ virtual bool isPullNeeded() const override {
+ return false;
+ }
// ValueMetric needs special logic if it's a pulled atom.
void onStatsdInitCompleted(const int64_t& eventTimeNs) override;
@@ -211,7 +216,7 @@ protected:
// causes the bucket to be invalidated will not notify StatsdStats.
void skipCurrentBucket(const int64_t dropTimeNs, const BucketDropReason reason);
- bool onConfigUpdatedLocked(
+ optional<InvalidConfigReason> onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -338,6 +343,7 @@ protected:
virtual void writePastBucketAggregateToProto(const int aggIndex,
const AggregatedValue& aggregate,
+ const int sampleSize,
ProtoOutputStream* const protoOutput) const = 0;
static const size_t kBucketSize = sizeof(PastBucket<AggregatedValue>{});
diff --git a/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index e65e4bc7..c3972d9a 100644
--- a/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -31,16 +31,16 @@ namespace os {
namespace statsd {
// Recursive function to determine if a matcher needs to be updated. Populates matcherToUpdate.
-// Returns whether the function was successful or not.
-bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
- 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) {
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> determineMatcherUpdateStatus(
+ const StatsdConfig& config, const int matcherIdx,
+ 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) {
// Have already examined this matcher.
if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) {
- return true;
+ return nullopt;
}
const AtomMatcher& matcher = config.atom_matcher(matcherIdx);
@@ -49,25 +49,27 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
matchersToUpdate[matcherIdx] = UPDATE_NEW;
- return true;
+ return nullopt;
}
// This is an existing matcher. Check if it has changed.
string serializedMatcher;
if (!matcher.SerializeToString(&serializedMatcher)) {
ALOGE("Unable to serialize matcher %lld", (long long)id);
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_SERIALIZATION_FAILED, id);
}
uint64_t newProtoHash = Hash64(serializedMatcher);
if (newProtoHash != oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second]->getProtoHash()) {
matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
+ optional<InvalidConfigReason> invalidConfigReason;
switch (matcher.contents_case()) {
case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
matchersToUpdate[matcherIdx] = UPDATE_PRESERVE;
- return true;
+ return nullopt;
}
case AtomMatcher::ContentsCase::kCombination: {
// Recurse to check if children have changed.
@@ -77,17 +79,25 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
const auto& childIt = newAtomMatchingTrackerMap.find(childMatcherId);
if (childIt == newAtomMatchingTrackerMap.end()) {
ALOGW("Matcher %lld not found in the config", (long long)childMatcherId);
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND, id);
+ invalidConfigReason->matcherIds.push_back(childMatcherId);
+ return invalidConfigReason;
}
const int childIdx = childIt->second;
if (cycleTracker[childIdx]) {
ALOGE("Cycle detected in matcher config");
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_CYCLE, id);
+ invalidConfigReason->matcherIds.push_back(childMatcherId);
+ return invalidConfigReason;
}
- if (!determineMatcherUpdateStatus(
- config, childIdx, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
- newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker)) {
- return false;
+ invalidConfigReason = determineMatcherUpdateStatus(
+ config, childIdx, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker);
+ if (invalidConfigReason.has_value()) {
+ invalidConfigReason->matcherIds.push_back(id);
+ return invalidConfigReason;
}
if (matchersToUpdate[childIdx] == UPDATE_REPLACE) {
@@ -97,34 +107,37 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
}
matchersToUpdate[matcherIdx] = status;
cycleTracker[matcherIdx] = false;
- return true;
+ return nullopt;
}
default: {
ALOGE("Matcher \"%lld\" malformed", (long long)id);
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE, id);
}
}
- return true;
+ return nullopt;
}
-bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
- unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- set<int64_t>& replacedMatchers) {
+optional<InvalidConfigReason> updateAtomMatchingTrackers(
+ const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers, set<int64_t>& replacedMatchers) {
const int atomMatcherCount = config.atom_matcher_size();
vector<AtomMatcher> matcherProtos;
matcherProtos.reserve(atomMatcherCount);
newAtomMatchingTrackers.reserve(atomMatcherCount);
+ optional<InvalidConfigReason> invalidConfigReason;
// Maps matcher id to their position in the config. For fast lookup of dependencies.
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& matcher = config.atom_matcher(i);
if (newAtomMatchingTrackerMap.find(matcher.id()) != newAtomMatchingTrackerMap.end()) {
ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id());
- return false;
+ return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
+ matcher.id());
}
newAtomMatchingTrackerMap[matcher.id()] = i;
matcherProtos.push_back(matcher);
@@ -134,10 +147,11 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN);
vector<bool> cycleTracker(atomMatcherCount, false);
for (int i = 0; i < atomMatcherCount; i++) {
- if (!determineMatcherUpdateStatus(config, i, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker)) {
- return false;
+ invalidConfigReason = determineMatcherUpdateStatus(
+ config, i, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, matchersToUpdate, cycleTracker);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
@@ -151,13 +165,16 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
ALOGE("Could not find AtomMatcher %lld in the previous config, but expected it "
"to be there",
(long long)id);
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_NOT_IN_PREV_CONFIG, id);
}
const sp<AtomMatchingTracker>& tracker =
oldAtomMatchingTrackers[oldAtomMatchingTrackerIt->second];
- if (!tracker->onConfigUpdated(matcherProtos[i], i, newAtomMatchingTrackerMap)) {
+ invalidConfigReason =
+ tracker->onConfigUpdated(matcherProtos[i], i, newAtomMatchingTrackerMap);
+ if (invalidConfigReason.has_value()) {
ALOGW("Config update failed for matcher %lld", (long long)id);
- return false;
+ return invalidConfigReason;
}
newAtomMatchingTrackers.push_back(tracker);
break;
@@ -166,9 +183,10 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
replacedMatchers.insert(id);
[[fallthrough]]; // Intentionally fallthrough to create the new matcher.
case UPDATE_NEW: {
- sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, i, uidMap);
+ sp<AtomMatchingTracker> tracker =
+ createAtomMatchingTracker(matcher, i, uidMap, invalidConfigReason);
if (tracker == nullptr) {
- return false;
+ return invalidConfigReason;
}
newAtomMatchingTrackers.push_back(tracker);
break;
@@ -176,7 +194,8 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
default: {
ALOGE("Matcher \"%lld\" update state is unknown. This should never happen",
(long long)id);
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_UPDATE_STATUS_UNKNOWN, id);
}
}
}
@@ -184,9 +203,10 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
std::fill(cycleTracker.begin(), cycleTracker.end(), false);
for (size_t matcherIndex = 0; matcherIndex < newAtomMatchingTrackers.size(); matcherIndex++) {
auto& matcher = newAtomMatchingTrackers[matcherIndex];
- if (!matcher->init(matcherProtos, newAtomMatchingTrackers, newAtomMatchingTrackerMap,
- cycleTracker)) {
- return false;
+ invalidConfigReason = matcher->init(matcherProtos, newAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, cycleTracker);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
// Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
@@ -207,21 +227,21 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
}
}
- return true;
+ return nullopt;
}
// Recursive function to determine if a condition needs to be updated. Populates conditionsToUpdate.
-// Returns whether the function was successful or not.
-bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
- const unordered_map<int64_t, int>& oldConditionTrackerMap,
- const vector<sp<ConditionTracker>>& oldConditionTrackers,
- const unordered_map<int64_t, int>& newConditionTrackerMap,
- const set<int64_t>& replacedMatchers,
- vector<UpdateStatus>& conditionsToUpdate,
- vector<bool>& cycleTracker) {
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> determineConditionUpdateStatus(
+ const StatsdConfig& config, const int conditionIdx,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& newConditionTrackerMap,
+ const set<int64_t>& replacedMatchers, vector<UpdateStatus>& conditionsToUpdate,
+ vector<bool>& cycleTracker) {
// Have already examined this condition.
if (conditionsToUpdate[conditionIdx] != UPDATE_UNKNOWN) {
- return true;
+ return nullopt;
}
const Predicate& predicate = config.predicate(conditionIdx);
@@ -230,21 +250,23 @@ bool determineConditionUpdateStatus(const StatsdConfig& config, const int condit
const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
conditionsToUpdate[conditionIdx] = UPDATE_NEW;
- return true;
+ return nullopt;
}
// This is an existing condition. Check if it has changed.
string serializedCondition;
if (!predicate.SerializeToString(&serializedCondition)) {
- ALOGE("Unable to serialize matcher %lld", (long long)id);
- return false;
+ ALOGE("Unable to serialize predicate %lld", (long long)id);
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_SERIALIZATION_FAILED, id);
}
uint64_t newProtoHash = Hash64(serializedCondition);
if (newProtoHash != oldConditionTrackers[oldConditionTrackerIt->second]->getProtoHash()) {
conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
+ optional<InvalidConfigReason> invalidConfigReason;
switch (predicate.contents_case()) {
case Predicate::ContentsCase::kSimplePredicate: {
// Need to check if any of the underlying matchers changed.
@@ -252,23 +274,23 @@ bool determineConditionUpdateStatus(const StatsdConfig& config, const int condit
if (simplePredicate.has_start()) {
if (replacedMatchers.find(simplePredicate.start()) != replacedMatchers.end()) {
conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
}
if (simplePredicate.has_stop()) {
if (replacedMatchers.find(simplePredicate.stop()) != replacedMatchers.end()) {
conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
}
if (simplePredicate.has_stop_all()) {
if (replacedMatchers.find(simplePredicate.stop_all()) != replacedMatchers.end()) {
conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
}
conditionsToUpdate[conditionIdx] = UPDATE_PRESERVE;
- return true;
+ return nullopt;
}
case Predicate::ContentsCase::kCombination: {
// Need to recurse on the children to see if any of the child predicates changed.
@@ -278,18 +300,25 @@ bool determineConditionUpdateStatus(const StatsdConfig& config, const int condit
const auto& childIt = newConditionTrackerMap.find(childPredicateId);
if (childIt == newConditionTrackerMap.end()) {
ALOGW("Predicate %lld not found in the config", (long long)childPredicateId);
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_CHILD_NOT_FOUND, id);
+ invalidConfigReason->conditionIds.push_back(childPredicateId);
+ return invalidConfigReason;
}
const int childIdx = childIt->second;
if (cycleTracker[childIdx]) {
ALOGE("Cycle detected in predicate config");
- return false;
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_CYCLE, id);
+ invalidConfigReason->conditionIds.push_back(childPredicateId);
+ return invalidConfigReason;
}
- if (!determineConditionUpdateStatus(config, childIdx, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate,
- cycleTracker)) {
- return false;
+ invalidConfigReason = determineConditionUpdateStatus(
+ config, childIdx, oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, replacedMatchers, conditionsToUpdate, cycleTracker);
+ if (invalidConfigReason.has_value()) {
+ invalidConfigReason->conditionIds.push_back(id);
+ return invalidConfigReason;
}
if (conditionsToUpdate[childIdx] == UPDATE_REPLACE) {
@@ -299,37 +328,41 @@ bool determineConditionUpdateStatus(const StatsdConfig& config, const int condit
}
conditionsToUpdate[conditionIdx] = status;
cycleTracker[conditionIdx] = false;
- return true;
+ return nullopt;
}
default: {
ALOGE("Predicate \"%lld\" malformed", (long long)id);
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_MALFORMED_CONTENTS_CASE, id);
}
}
- return true;
+ return nullopt;
}
-bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap,
- const set<int64_t>& replacedMatchers,
- const unordered_map<int64_t, int>& oldConditionTrackerMap,
- const vector<sp<ConditionTracker>>& oldConditionTrackers,
- unordered_map<int64_t, int>& newConditionTrackerMap,
- vector<sp<ConditionTracker>>& newConditionTrackers,
- unordered_map<int, vector<int>>& trackerToConditionMap,
- vector<ConditionState>& conditionCache, set<int64_t>& replacedConditions) {
+optional<InvalidConfigReason> updateConditions(
+ const ConfigKey& key, const StatsdConfig& config,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int, vector<int>>& trackerToConditionMap,
+ vector<ConditionState>& conditionCache, set<int64_t>& replacedConditions) {
vector<Predicate> conditionProtos;
const int conditionTrackerCount = config.predicate_size();
conditionProtos.reserve(conditionTrackerCount);
newConditionTrackers.reserve(conditionTrackerCount);
conditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
+ optional<InvalidConfigReason> invalidConfigReason;
for (int i = 0; i < conditionTrackerCount; i++) {
const Predicate& condition = config.predicate(i);
if (newConditionTrackerMap.find(condition.id()) != newConditionTrackerMap.end()) {
ALOGE("Duplicate Predicate found!");
- return false;
+ return createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
+ condition.id());
}
newConditionTrackerMap[condition.id()] = i;
conditionProtos.push_back(condition);
@@ -338,10 +371,11 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
vector<UpdateStatus> conditionsToUpdate(conditionTrackerCount, UPDATE_UNKNOWN);
vector<bool> cycleTracker(conditionTrackerCount, false);
for (int i = 0; i < conditionTrackerCount; i++) {
- if (!determineConditionUpdateStatus(config, i, oldConditionTrackerMap, oldConditionTrackers,
- newConditionTrackerMap, replacedMatchers,
- conditionsToUpdate, cycleTracker)) {
- return false;
+ invalidConfigReason = determineConditionUpdateStatus(
+ config, i, oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
@@ -358,7 +392,8 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
ALOGE("Could not find Predicate %lld in the previous config, but expected it "
"to be there",
(long long)id);
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_NOT_IN_PREV_CONFIG, id);
}
const int oldIndex = oldConditionTrackerIt->second;
newConditionTrackers.push_back(oldConditionTrackers[oldIndex]);
@@ -368,10 +403,10 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
replacedConditions.insert(id);
[[fallthrough]]; // Intentionally fallthrough to create the new condition tracker.
case UPDATE_NEW: {
- sp<ConditionTracker> tracker =
- createConditionTracker(key, predicate, i, atomMatchingTrackerMap);
+ sp<ConditionTracker> tracker = createConditionTracker(
+ key, predicate, i, atomMatchingTrackerMap, invalidConfigReason);
if (tracker == nullptr) {
- return false;
+ return invalidConfigReason;
}
newConditionTrackers.push_back(tracker);
break;
@@ -379,19 +414,21 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
default: {
ALOGE("Condition \"%lld\" update state is unknown. This should never happen",
(long long)id);
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_UPDATE_STATUS_UNKNOWN, id);
}
}
}
// Update indices of preserved predicates.
for (const int conditionIndex : preservedConditions) {
- if (!newConditionTrackers[conditionIndex]->onConfigUpdated(
- conditionProtos, conditionIndex, newConditionTrackers, atomMatchingTrackerMap,
- newConditionTrackerMap)) {
+ invalidConfigReason = newConditionTrackers[conditionIndex]->onConfigUpdated(
+ conditionProtos, conditionIndex, newConditionTrackers, atomMatchingTrackerMap,
+ newConditionTrackerMap);
+ if (invalidConfigReason.has_value()) {
ALOGE("Failed to update condition %lld",
(long long)newConditionTrackers[conditionIndex]->getConditionId());
- return false;
+ return invalidConfigReason;
}
}
@@ -399,25 +436,30 @@ bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
for (int conditionIndex = 0; conditionIndex < conditionTrackerCount; conditionIndex++) {
const sp<ConditionTracker>& conditionTracker = newConditionTrackers[conditionIndex];
// Calling init on preserved conditions is OK. It is needed to fill the condition cache.
- if (!conditionTracker->init(conditionProtos, newConditionTrackers, newConditionTrackerMap,
- cycleTracker, conditionCache)) {
- return false;
+ invalidConfigReason =
+ conditionTracker->init(conditionProtos, newConditionTrackers,
+ newConditionTrackerMap, cycleTracker, conditionCache);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
vector<int>& conditionList = trackerToConditionMap[trackerIndex];
conditionList.push_back(conditionIndex);
}
}
- return true;
+ return nullopt;
}
-bool updateStates(const StatsdConfig& config, const map<int64_t, uint64_t>& oldStateProtoHashes,
- unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
- map<int64_t, uint64_t>& newStateProtoHashes, set<int64_t>& replacedStates) {
+optional<InvalidConfigReason> updateStates(
+ const StatsdConfig& config, const map<int64_t, uint64_t>& oldStateProtoHashes,
+ unordered_map<int64_t, int>& stateAtomIdMap,
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ map<int64_t, uint64_t>& newStateProtoHashes, set<int64_t>& replacedStates) {
// Share with metrics_manager_util.
- if (!initStates(config, stateAtomIdMap, allStateGroupMaps, newStateProtoHashes)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason =
+ initStates(config, stateAtomIdMap, allStateGroupMaps, newStateProtoHashes);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
for (const auto& [stateId, stateHash] : oldStateProtoHashes) {
@@ -426,7 +468,7 @@ bool updateStates(const StatsdConfig& config, const map<int64_t, uint64_t>& oldS
replacedStates.insert(stateId);
}
}
- return true;
+ return nullopt;
}
// Returns true if any matchers in the metric activation were replaced.
bool metricActivationDepsChange(const StatsdConfig& config,
@@ -452,7 +494,7 @@ bool metricActivationDepsChange(const StatsdConfig& config,
return false;
}
-bool determineMetricUpdateStatus(
+optional<InvalidConfigReason> determineMetricUpdateStatus(
const StatsdConfig& config, const MessageLite& metric, const int64_t metricId,
const MetricType metricType, const set<int64_t>& matcherDependencies,
const set<int64_t>& conditionDependencies,
@@ -467,19 +509,21 @@ bool determineMetricUpdateStatus(
const auto& oldMetricProducerIt = oldMetricProducerMap.find(metricId);
if (oldMetricProducerIt == oldMetricProducerMap.end()) {
updateStatus = UPDATE_NEW;
- return true;
+ return nullopt;
}
// This is an existing metric, check if it has changed.
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metricId, metricToActivationMap, metricHash)) {
- return false;
+ optional<InvalidConfigReason> invalidConfigReason =
+ getMetricProtoHash(config, metric, metricId, metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
const sp<MetricProducer> oldMetricProducer = oldMetricProducers[oldMetricProducerIt->second];
if (oldMetricProducer->getMetricType() != metricType ||
oldMetricProducer->getProtoHash() != metricHash) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
// Take intersections of the matchers/predicates/states that the metric
@@ -491,60 +535,59 @@ bool determineMetricUpdateStatus(
inserter(intersection, intersection.begin()));
if (intersection.size() > 0) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
set_intersection(conditionDependencies.begin(), conditionDependencies.end(),
replacedConditions.begin(), replacedConditions.end(),
inserter(intersection, intersection.begin()));
if (intersection.size() > 0) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
set_intersection(stateDependencies.begin(), stateDependencies.end(), replacedStates.begin(),
replacedStates.end(), inserter(intersection, intersection.begin()));
if (intersection.size() > 0) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
for (const auto& metricConditionLink : conditionLinks) {
if (replacedConditions.find(metricConditionLink.condition()) != replacedConditions.end()) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
}
if (metricActivationDepsChange(config, metricToActivationMap, metricId, replacedMatchers)) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
updateStatus = UPDATE_PRESERVE;
- return true;
+ return nullopt;
}
-bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
- const unordered_map<int64_t, int>& oldMetricProducerMap,
- const vector<sp<MetricProducer>>& oldMetricProducers,
- const unordered_map<int64_t, int>& metricToActivationMap,
- const set<int64_t>& replacedMatchers,
- const set<int64_t>& replacedConditions,
- const set<int64_t>& replacedStates,
- vector<UpdateStatus>& metricsToUpdate) {
+optional<InvalidConfigReason> determineAllMetricUpdateStatuses(
+ const StatsdConfig& config, const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const set<int64_t>& replacedMatchers, const set<int64_t>& replacedConditions,
+ const set<int64_t>& replacedStates, vector<UpdateStatus>& metricsToUpdate) {
int metricIndex = 0;
+ optional<InvalidConfigReason> invalidConfigReason;
for (int i = 0; i < config.count_metric_size(); i++, metricIndex++) {
const CountMetric& metric = config.count_metric(i);
set<int64_t> conditionDependencies;
if (metric.has_condition()) {
conditionDependencies.insert(metric.condition());
}
- if (!determineMetricUpdateStatus(
- config, metric, metric.id(), METRIC_TYPE_COUNT, {metric.what()},
- conditionDependencies, metric.slice_by_state(), metric.links(),
- oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- replacedMatchers, replacedConditions, replacedStates,
- metricsToUpdate[metricIndex])) {
- return false;
+ invalidConfigReason = determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_COUNT, {metric.what()},
+ conditionDependencies, metric.slice_by_state(), metric.links(),
+ oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
+ replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
for (int i = 0; i < config.duration_metric_size(); i++, metricIndex++) {
@@ -553,13 +596,13 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
if (metric.has_condition()) {
conditionDependencies.insert(metric.condition());
}
- if (!determineMetricUpdateStatus(
- config, metric, metric.id(), METRIC_TYPE_DURATION, /*matcherDependencies=*/{},
- conditionDependencies, metric.slice_by_state(), metric.links(),
- oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- replacedMatchers, replacedConditions, replacedStates,
- metricsToUpdate[metricIndex])) {
- return false;
+ invalidConfigReason = determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_DURATION, /*matcherDependencies=*/{},
+ conditionDependencies, metric.slice_by_state(), metric.links(),
+ oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
+ replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
@@ -568,13 +611,13 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
if (metric.has_condition()) {
conditionDependencies.insert(metric.condition());
}
- if (!determineMetricUpdateStatus(
- config, metric, metric.id(), METRIC_TYPE_EVENT, {metric.what()},
- conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(),
- metric.links(), oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- replacedMatchers, replacedConditions, replacedStates,
- metricsToUpdate[metricIndex])) {
- return false;
+ invalidConfigReason = determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_EVENT, {metric.what()},
+ conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(), metric.links(),
+ oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
+ replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
for (int i = 0; i < config.value_metric_size(); i++, metricIndex++) {
@@ -583,13 +626,13 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
if (metric.has_condition()) {
conditionDependencies.insert(metric.condition());
}
- if (!determineMetricUpdateStatus(
- config, metric, metric.id(), METRIC_TYPE_VALUE, {metric.what()},
- conditionDependencies, metric.slice_by_state(), metric.links(),
- oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- replacedMatchers, replacedConditions, replacedStates,
- metricsToUpdate[metricIndex])) {
- return false;
+ invalidConfigReason = determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_VALUE, {metric.what()},
+ conditionDependencies, metric.slice_by_state(), metric.links(),
+ oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
+ replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
for (int i = 0; i < config.gauge_metric_size(); i++, metricIndex++) {
@@ -602,13 +645,13 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
if (metric.has_trigger_event()) {
matcherDependencies.insert(metric.trigger_event());
}
- if (!determineMetricUpdateStatus(
- config, metric, metric.id(), METRIC_TYPE_GAUGE, matcherDependencies,
- conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(),
- metric.links(), oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- replacedMatchers, replacedConditions, replacedStates,
- metricsToUpdate[metricIndex])) {
- return false;
+ invalidConfigReason = determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_GAUGE, matcherDependencies,
+ conditionDependencies, ::google::protobuf::RepeatedField<int64_t>(), metric.links(),
+ oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
+ replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
@@ -618,17 +661,17 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
if (metric.has_condition()) {
conditionDependencies.insert(metric.condition());
}
- if (!determineMetricUpdateStatus(
- config, metric, metric.id(), METRIC_TYPE_KLL, {metric.what()},
- conditionDependencies, metric.slice_by_state(), metric.links(),
- oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- replacedMatchers, replacedConditions, replacedStates,
- metricsToUpdate[metricIndex])) {
- return false;
+ invalidConfigReason = determineMetricUpdateStatus(
+ config, metric, metric.id(), METRIC_TYPE_KLL, {metric.what()},
+ conditionDependencies, metric.slice_by_state(), metric.links(),
+ oldMetricProducerMap, oldMetricProducers, metricToActivationMap, replacedMatchers,
+ replacedConditions, replacedStates, metricsToUpdate[metricIndex]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
- return true;
+ return nullopt;
}
// Called when a metric is preserved during a config update. Finds the metric in oldMetricProducers
@@ -648,56 +691,58 @@ optional<sp<MetricProducer>> updateMetric(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
const auto& oldMetricProducerIt = oldMetricProducerMap.find(metricId);
if (oldMetricProducerIt == oldMetricProducerMap.end()) {
ALOGE("Could not find Metric %lld in the previous config, but expected it "
"to be there",
(long long)metricId);
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG, metricId);
return nullopt;
}
const int oldIndex = oldMetricProducerIt->second;
sp<MetricProducer> producer = oldMetricProducers[oldIndex];
- if (!producer->onConfigUpdated(config, configIndex, metricIndex, allAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap,
- matcherWizard, allConditionTrackers, conditionTrackerMap, wizard,
- metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
- activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+ invalidConfigReason = producer->onConfigUpdated(
+ config, configIndex, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers, conditionTrackerMap,
+ wizard, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
return {producer};
}
-bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
- const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- const set<int64_t>& replacedMatchers,
- const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- const unordered_map<int64_t, int>& conditionTrackerMap,
- const set<int64_t>& replacedConditions,
- vector<sp<ConditionTracker>>& allConditionTrackers,
- const vector<ConditionState>& initialConditionCache,
- const unordered_map<int64_t, int>& stateAtomIdMap,
- const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
- const set<int64_t>& replacedStates,
- const unordered_map<int64_t, int>& oldMetricProducerMap,
- const vector<sp<MetricProducer>>& oldMetricProducers,
- unordered_map<int64_t, int>& newMetricProducerMap,
- vector<sp<MetricProducer>>& newMetricProducers,
- unordered_map<int, vector<int>>& conditionToMetricMap,
- unordered_map<int, vector<int>>& trackerToMetricMap,
- set<int64_t>& noReportMetricIds,
- unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
- unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation, set<int64_t>& replacedMetrics) {
+optional<InvalidConfigReason> updateMetrics(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const set<int64_t>& replacedConditions, vector<sp<ConditionTracker>>& allConditionTrackers,
+ const vector<ConditionState>& initialConditionCache,
+ const unordered_map<int64_t, int>& stateAtomIdMap,
+ const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ const set<int64_t>& replacedStates, const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ unordered_map<int64_t, int>& newMetricProducerMap,
+ vector<sp<MetricProducer>>& newMetricProducers,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap, set<int64_t>& noReportMetricIds,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation, set<int64_t>& replacedMetrics) {
sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
config.event_metric_size() + config.gauge_metric_size() +
config.value_metric_size() + config.kll_metric_size();
newMetricProducers.reserve(allMetricsCount);
+ optional<InvalidConfigReason> invalidConfigReason;
// Construct map from metric id to metric activation index. The map will be used to determine
// the metric activation corresponding to a metric.
@@ -707,16 +752,18 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
int64_t metricId = metricActivation.metric_id();
if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS,
+ metricId);
}
metricToActivationMap.insert({metricId, i});
}
vector<UpdateStatus> metricsToUpdate(allMetricsCount, UPDATE_UNKNOWN);
- if (!determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap, replacedMatchers,
- replacedConditions, replacedStates, metricsToUpdate)) {
- return false;
+ invalidConfigReason = determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ replacedMatchers, replacedConditions, replacedStates, metricsToUpdate);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
// Now, perform the update. Must iterate the metric types in the same order
@@ -733,7 +780,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
case UPDATE_REPLACE:
@@ -746,17 +794,19 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
default: {
ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
(long long)metric.id());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
+ metric.id());
}
}
if (!producer) {
- return false;
+ return invalidConfigReason;
}
newMetricProducers.push_back(producer.value());
}
@@ -772,7 +822,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
case UPDATE_REPLACE:
@@ -785,17 +836,19 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
default: {
ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
(long long)metric.id());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
+ metric.id());
}
}
if (!producer) {
- return false;
+ return invalidConfigReason;
}
newMetricProducers.push_back(producer.value());
}
@@ -811,7 +864,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
case UPDATE_REPLACE:
@@ -823,17 +877,19 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
newAtomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
default: {
ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
(long long)metric.id());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
+ metric.id());
}
}
if (!producer) {
- return false;
+ return invalidConfigReason;
}
newMetricProducers.push_back(producer.value());
}
@@ -850,7 +906,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
case UPDATE_REPLACE:
@@ -863,17 +920,19 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
stateAtomIdMap, allStateGroupMaps, metricToActivationMap,
trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
default: {
ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
(long long)metric.id());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
+ metric.id());
}
}
if (!producer) {
- return false;
+ return invalidConfigReason;
}
newMetricProducers.push_back(producer.value());
}
@@ -890,7 +949,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
case UPDATE_REPLACE:
@@ -903,17 +963,18 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation);
+ metricsWithActivation, invalidConfigReason);
break;
}
default: {
ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
(long long)metric.id());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
+ metric.id());
}
}
if (!producer) {
- return false;
+ return invalidConfigReason;
}
newMetricProducers.push_back(producer.value());
}
@@ -930,7 +991,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
oldMetricProducers, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
case UPDATE_REPLACE:
@@ -944,17 +1006,19 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
stateAtomIdMap, allStateGroupMaps, metricToActivationMap,
trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ invalidConfigReason);
break;
}
default: {
ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
(long long)metric.id());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_UPDATE_STATUS_UNKNOWN,
+ metric.id());
}
}
if (!producer) {
- return false;
+ return invalidConfigReason;
}
newMetricProducers.push_back(producer.value());
}
@@ -963,7 +1027,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
const int64_t noReportMetric = config.no_report_metric(i);
if (newMetricProducerMap.find(noReportMetric) == newMetricProducerMap.end()) {
ALOGW("no_report_metric %" PRId64 " not exist", noReportMetric);
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND,
+ noReportMetric);
}
noReportMetricIds.insert(noReportMetric);
}
@@ -977,7 +1042,9 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
// Using atoms allowed from any uid as a sliced state atom is not allowed.
// Redo this check for all metrics in case the atoms allowed from any uid changed.
if (atomsAllowedFromAnyUid.find(atomId) != atomsAllowedFromAnyUid.end()) {
- return false;
+ return InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
+ producer->getMetricId());
// Preserved metrics should've already registered.`
} else if (metricsToUpdate[i] != UPDATE_PRESERVE) {
StateManager::getInstance().registerListener(atomId, producer);
@@ -991,62 +1058,66 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
newMetricProducers[i]->prepareFirstBucket();
}
}
- return true;
+ return nullopt;
}
-bool determineAlertUpdateStatus(const Alert& alert,
- const unordered_map<int64_t, int>& oldAlertTrackerMap,
- const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
- const set<int64_t>& replacedMetrics, UpdateStatus& updateStatus) {
+optional<InvalidConfigReason> determineAlertUpdateStatus(
+ const Alert& alert, const unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const vector<sp<AnomalyTracker>>& oldAnomalyTrackers, const set<int64_t>& replacedMetrics,
+ UpdateStatus& updateStatus) {
// Check if new alert.
const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
updateStatus = UPDATE_NEW;
- return true;
+ return nullopt;
}
// This is an existing alert, check if it has changed.
string serializedAlert;
if (!alert.SerializeToString(&serializedAlert)) {
ALOGW("Unable to serialize alert %lld", (long long)alert.id());
- return false;
+ return createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_SERIALIZATION_FAILED,
+ alert.id());
}
uint64_t newProtoHash = Hash64(serializedAlert);
- const auto [success, oldProtoHash] =
+ const auto [invalidConfigReason, oldProtoHash] =
oldAnomalyTrackers[oldAnomalyTrackerIt->second]->getProtoHash();
- if (!success) {
- return false;
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
if (newProtoHash != oldProtoHash) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
// Check if the metric this alert relies on has changed.
if (replacedMetrics.find(alert.metric_id()) != replacedMetrics.end()) {
updateStatus = UPDATE_REPLACE;
- return true;
+ return nullopt;
}
updateStatus = UPDATE_PRESERVE;
- return true;
+ return nullopt;
}
-bool updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
- const unordered_map<int64_t, int>& metricProducerMap,
- const set<int64_t>& replacedMetrics,
- const unordered_map<int64_t, int>& oldAlertTrackerMap,
- const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
- const sp<AlarmMonitor>& anomalyAlarmMonitor,
- vector<sp<MetricProducer>>& allMetricProducers,
- unordered_map<int64_t, int>& newAlertTrackerMap,
- vector<sp<AnomalyTracker>>& newAnomalyTrackers) {
+optional<InvalidConfigReason> updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
+ const unordered_map<int64_t, int>& metricProducerMap,
+ const set<int64_t>& replacedMetrics,
+ const unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ vector<sp<MetricProducer>>& allMetricProducers,
+ unordered_map<int64_t, int>& newAlertTrackerMap,
+ vector<sp<AnomalyTracker>>& newAnomalyTrackers) {
int alertCount = config.alert_size();
vector<UpdateStatus> alertUpdateStatuses(alertCount);
+ optional<InvalidConfigReason> invalidConfigReason;
for (int i = 0; i < alertCount; i++) {
- if (!determineAlertUpdateStatus(config.alert(i), oldAlertTrackerMap, oldAnomalyTrackers,
- replacedMetrics, alertUpdateStatuses[i])) {
- return false;
+ invalidConfigReason =
+ determineAlertUpdateStatus(config.alert(i), oldAlertTrackerMap, oldAnomalyTrackers,
+ replacedMetrics, alertUpdateStatuses[i]);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
}
@@ -1061,7 +1132,8 @@ bool updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
ALOGW("Could not find AnomalyTracker %lld in the previous config, but "
"expected it to be there",
(long long)alert.id());
- return false;
+ return createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_NOT_IN_PREV_CONFIG, alert.id());
}
sp<AnomalyTracker> anomalyTracker = oldAnomalyTrackers[oldAnomalyTrackerIt->second];
anomalyTracker->onConfigUpdated();
@@ -1070,7 +1142,9 @@ bool updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
if (metricProducerIt == metricProducerMap.end()) {
ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
(long long)alert.metric_id());
- return false;
+ return createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND, alert.metric_id(),
+ alert.id());
}
allMetricProducers[metricProducerIt->second]->addAnomalyTracker(anomalyTracker,
currentTimeNs);
@@ -1079,11 +1153,11 @@ bool updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
}
case UPDATE_REPLACE:
case UPDATE_NEW: {
- optional<sp<AnomalyTracker>> anomalyTracker =
- createAnomalyTracker(alert, anomalyAlarmMonitor, alertUpdateStatuses[i],
- currentTimeNs, metricProducerMap, allMetricProducers);
+ optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
+ alert, anomalyAlarmMonitor, alertUpdateStatuses[i], currentTimeNs,
+ metricProducerMap, allMetricProducers, invalidConfigReason);
if (!anomalyTracker) {
- return false;
+ return invalidConfigReason;
}
newAnomalyTrackers.push_back(anomalyTracker.value());
break;
@@ -1091,49 +1165,49 @@ bool updateAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
default: {
ALOGE("Alert \"%lld\" update state is unknown. This should never happen",
(long long)alert.id());
- return false;
+ return createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_UPDATE_STATUS_UNKNOWN, alert.id());
}
}
}
- if (!initSubscribersForSubscriptionType(config, Subscription::ALERT, newAlertTrackerMap,
- newAnomalyTrackers)) {
- return false;
+ invalidConfigReason = initSubscribersForSubscriptionType(
+ config, Subscription::ALERT, newAlertTrackerMap, newAnomalyTrackers);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
- return true;
+ return nullopt;
}
-bool 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 int64_t currentTimeNs,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<ConditionTracker>>& oldConditionTrackers,
- const unordered_map<int64_t, int>& oldConditionTrackerMap,
- const vector<sp<MetricProducer>>& oldMetricProducers,
- const unordered_map<int64_t, int>& oldMetricProducerMap,
- const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
- const unordered_map<int64_t, int>& oldAlertTrackerMap,
- const map<int64_t, uint64_t>& oldStateProtoHashes,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
- vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<sp<ConditionTracker>>& newConditionTrackers,
- unordered_map<int64_t, int>& newConditionTrackerMap,
- vector<sp<MetricProducer>>& newMetricProducers,
- unordered_map<int64_t, int>& newMetricProducerMap,
- vector<sp<AnomalyTracker>>& newAnomalyTrackers,
- unordered_map<int64_t, int>& newAlertTrackerMap,
- vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
- unordered_map<int, vector<int>>& conditionToMetricMap,
- unordered_map<int, vector<int>>& trackerToMetricMap,
- unordered_map<int, vector<int>>& trackerToConditionMap,
- unordered_map<int, vector<int>>& activationTrackerToMetricMap,
- unordered_map<int, vector<int>>& deactivationTrackerToMetricMap,
- vector<int>& metricsWithActivation,
- map<int64_t, uint64_t>& newStateProtoHashes,
- set<int64_t>& noReportMetricIds) {
+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 int64_t currentTimeNs, const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const map<int64_t, uint64_t>& oldStateProtoHashes,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
+ vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ vector<sp<MetricProducer>>& newMetricProducers,
+ unordered_map<int64_t, int>& newMetricProducerMap,
+ vector<sp<AnomalyTracker>>& newAnomalyTrackers,
+ unordered_map<int64_t, int>& newAlertTrackerMap,
+ vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& trackerToConditionMap,
+ unordered_map<int, vector<int>>& activationTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationTrackerToMetricMap,
+ vector<int>& metricsWithActivation, map<int64_t, uint64_t>& newStateProtoHashes,
+ set<int64_t>& noReportMetricIds) {
set<int64_t> replacedMatchers;
set<int64_t> replacedConditions;
set<int64_t> replacedStates;
@@ -1145,56 +1219,63 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
config.package_certificate_hash_size_bytes());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_PACKAGE_CERT_HASH_SIZE_TOO_LARGE);
}
- if (!updateAtomMatchingTrackers(config, uidMap, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, allTagIdsToMatchersMap,
- newAtomMatchingTrackerMap, newAtomMatchingTrackers,
- replacedMatchers)) {
+ optional<InvalidConfigReason> invalidConfigReason = updateAtomMatchingTrackers(
+ config, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
+ allTagIdsToMatchersMap, newAtomMatchingTrackerMap, newAtomMatchingTrackers,
+ replacedMatchers);
+ if (invalidConfigReason.has_value()) {
ALOGE("updateAtomMatchingTrackers failed");
- return false;
+ return invalidConfigReason;
}
- if (!updateConditions(key, config, newAtomMatchingTrackerMap, replacedMatchers,
- oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
- newConditionTrackers, trackerToConditionMap, conditionCache,
- replacedConditions)) {
+ invalidConfigReason = updateConditions(
+ key, config, newAtomMatchingTrackerMap, replacedMatchers, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap, newConditionTrackers,
+ trackerToConditionMap, conditionCache, replacedConditions);
+ if (invalidConfigReason.has_value()) {
ALOGE("updateConditions failed");
- return false;
+ return invalidConfigReason;
}
- if (!updateStates(config, oldStateProtoHashes, stateAtomIdMap, allStateGroupMaps,
- newStateProtoHashes, replacedStates)) {
+ invalidConfigReason = updateStates(config, oldStateProtoHashes, stateAtomIdMap,
+ allStateGroupMaps, newStateProtoHashes, replacedStates);
+ if (invalidConfigReason.has_value()) {
ALOGE("updateStates failed");
- return false;
- }
- if (!updateMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager,
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
- newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
- newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps,
- replacedStates, oldMetricProducerMap, oldMetricProducers,
- newMetricProducerMap, newMetricProducers, conditionToMetricMap,
- trackerToMetricMap, noReportMetricIds, activationTrackerToMetricMap,
- deactivationTrackerToMetricMap, metricsWithActivation, replacedMetrics)) {
+ return invalidConfigReason;
+ }
+
+ invalidConfigReason = updateMetrics(
+ key, config, timeBaseNs, currentTimeNs, pullerManager, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, replacedConditions, newConditionTrackers, conditionCache,
+ stateAtomIdMap, allStateGroupMaps, replacedStates, oldMetricProducerMap,
+ oldMetricProducers, newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationTrackerToMetricMap,
+ deactivationTrackerToMetricMap, metricsWithActivation, replacedMetrics);
+ if (invalidConfigReason.has_value()) {
ALOGE("updateMetrics failed");
- return false;
+ return invalidConfigReason;
}
- if (!updateAlerts(config, currentTimeNs, newMetricProducerMap, replacedMetrics,
- oldAlertTrackerMap, oldAnomalyTrackers, anomalyAlarmMonitor,
- newMetricProducers, newAlertTrackerMap, newAnomalyTrackers)) {
+ invalidConfigReason = updateAlerts(config, currentTimeNs, newMetricProducerMap, replacedMetrics,
+ oldAlertTrackerMap, oldAnomalyTrackers, anomalyAlarmMonitor,
+ newMetricProducers, newAlertTrackerMap, newAnomalyTrackers);
+ if (invalidConfigReason.has_value()) {
ALOGE("updateAlerts failed");
- return false;
+ return invalidConfigReason;
}
+ invalidConfigReason = initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ newPeriodicAlarmTrackers);
// Alarms do not have any state, so we can reuse the initialization logic.
- if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
- newPeriodicAlarmTrackers)) {
+ if (invalidConfigReason.has_value()) {
ALOGE("initAlarms failed");
- return false;
+ return invalidConfigReason;
}
- return true;
+ return nullopt;
}
} // namespace statsd
diff --git a/statsd/src/metrics/parsing_utils/config_update_utils.h b/statsd/src/metrics/parsing_utils/config_update_utils.h
index f311661b..3bd1e800 100644
--- a/statsd/src/metrics/parsing_utils/config_update_utils.h
+++ b/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -44,8 +44,8 @@ namespace statsd {
// [matchersToUpdate]: vector of the update status of each matcher. The matcherIdx index will
// be updated from UPDATE_UNKNOWN after this call.
// [cycleTracker]: intermediate param used during recursion.
-// Returns whether the function was successful or not.
-bool determineMatcherUpdateStatus(
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> determineMatcherUpdateStatus(
const StatsdConfig& config, const int matcherIdx,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
@@ -62,13 +62,15 @@ bool determineMatcherUpdateStatus(
// [newAtomMatchingTrackerMap]: new matcher id to index mapping
// [newAtomMatchingTrackers]: stores the new AtomMatchingTrackers
// [replacedMatchers]: set of matcher ids that changed and have been replaced
-bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
- std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- std::set<int64_t>& replacedMatchers);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> updateAtomMatchingTrackers(
+ const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ std::set<int64_t>& replacedMatchers);
// Recursive function to determine if a condition needs to be updated.
// input:
@@ -82,14 +84,14 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
// [conditionsToUpdate]: vector of the update status of each condition. The conditionIdx index will
// be updated from UPDATE_UNKNOWN after this call.
// [cycleTracker]: intermediate param used during recursion.
-// Returns whether the function was successful or not.
-bool determineConditionUpdateStatus(const StatsdConfig& config, const 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);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> determineConditionUpdateStatus(
+ const StatsdConfig& config, const 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);
// Updates ConditionTrackers
// input:
@@ -105,23 +107,23 @@ bool determineConditionUpdateStatus(const StatsdConfig& config, const int condit
// to indices of condition trackers that use the matcher
// [conditionCache]: stores the current conditions for each ConditionTracker
// [replacedConditions]: set of condition ids that have changed and have been replaced
-bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
- const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
- const std::set<int64_t>& replacedMatchers,
- const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
- const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
- std::unordered_map<int64_t, int>& newConditionTrackerMap,
- std::vector<sp<ConditionTracker>>& newConditionTrackers,
- std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::vector<ConditionState>& conditionCache,
- std::set<int64_t>& replacedConditions);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> updateConditions(
+ const ConfigKey& key, const StatsdConfig& config,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::vector<ConditionState>& conditionCache, std::set<int64_t>& replacedConditions);
-bool updateStates(const StatsdConfig& config,
- const std::map<int64_t, uint64_t>& oldStateProtoHashes,
- std::unordered_map<int64_t, int>& stateAtomIdMap,
- std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
- std::map<int64_t, uint64_t>& newStateProtoHashes,
- std::set<int64_t>& replacedStates);
+optional<InvalidConfigReason> updateStates(
+ const StatsdConfig& config, const std::map<int64_t, uint64_t>& oldStateProtoHashes,
+ std::unordered_map<int64_t, int>& stateAtomIdMap,
+ std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
+ std::map<int64_t, uint64_t>& newStateProtoHashes, std::set<int64_t>& replacedStates);
// Function to determine the update status (preserve/replace/new) of all metrics in the config.
// [config]: the input StatsdConfig
@@ -133,15 +135,13 @@ bool updateStates(const StatsdConfig& config,
// [replacedStates]: set of replaced state ids. metrics using these states must be replaced
// output:
// [metricsToUpdate]: update status of each metric. Will be changed from UPDATE_UNKNOWN
-// Returns whether the function was successful or not.
-bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
- const unordered_map<int64_t, int>& oldMetricProducerMap,
- const vector<sp<MetricProducer>>& oldMetricProducers,
- const unordered_map<int64_t, int>& metricToActivationMap,
- const set<int64_t>& replacedMatchers,
- const set<int64_t>& replacedConditions,
- const set<int64_t>& replacedStates,
- vector<UpdateStatus>& metricsToUpdate);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> determineAllMetricUpdateStatuses(
+ const StatsdConfig& config, const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<MetricProducer>>& oldMetricProducers,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const set<int64_t>& replacedMatchers, const set<int64_t>& replacedConditions,
+ const set<int64_t>& replacedStates, vector<UpdateStatus>& metricsToUpdate);
// Update MetricProducers.
// input:
@@ -162,7 +162,8 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
// [conditionToMetricMap]: contains the mapping from condition tracker index to
// the list of MetricProducer index
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
-bool updateMetrics(
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> updateMetrics(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -194,12 +195,11 @@ bool updateMetrics(
// [replacedMetrics]: set of replaced metric ids. alerts using these metrics must be replaced
// output:
// [updateStatus]: update status of the alert. Will be changed from UPDATE_UNKNOWN
-// Returns whether the function was successful or not.
-bool determineAlertUpdateStatus(const Alert& alert,
- const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
- const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
- const std::set<int64_t>& replacedMetrics,
- UpdateStatus& updateStatus);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> determineAlertUpdateStatus(
+ const Alert& alert, const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const std::set<int64_t>& replacedMetrics, UpdateStatus& updateStatus);
// Update MetricProducers.
// input:
@@ -217,50 +217,51 @@ bool determineAlertUpdateStatus(const Alert& alert,
// output:
// [newAlertTrackerMap]: mapping of alert id to index in the new config
// [newAnomalyTrackers]: contains the list of sp to the AnomalyTrackers created.
-bool updateAlerts(const StatsdConfig& config, const 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,
- const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
- const sp<AlarmMonitor>& anomalyAlarmMonitor,
- std::vector<sp<MetricProducer>>& allMetricProducers,
- std::unordered_map<int64_t, int>& newAlertTrackerMap,
- std::vector<sp<AnomalyTracker>>& newAnomalyTrackers);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> updateAlerts(
+ const StatsdConfig& config, const 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,
+ const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ std::vector<sp<MetricProducer>>& allMetricProducers,
+ std::unordered_map<int64_t, int>& newAlertTrackerMap,
+ std::vector<sp<AnomalyTracker>>& newAnomalyTrackers);
// Updates the existing MetricsManager from a new StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
-bool 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 int64_t currentTimeNs,
- const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
- const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
- const std::vector<sp<MetricProducer>>& oldMetricProducers,
- const std::unordered_map<int64_t, int>& oldMetricProducerMap,
- const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
- const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
- const std::map<int64_t, uint64_t>& oldStateProtoHashes,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
- std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- std::vector<sp<ConditionTracker>>& newConditionTrackers,
- std::unordered_map<int64_t, int>& newConditionTrackerMap,
- std::vector<sp<MetricProducer>>& newMetricProducers,
- std::unordered_map<int64_t, int>& newMetricProducerMap,
- std::vector<sp<AnomalyTracker>>& newAlertTrackers,
- std::unordered_map<int64_t, int>& newAlertTrackerMap,
- std::vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
- std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
- std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
- std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::unordered_map<int, std::vector<int>>& activationTrackerToMetricMap,
- std::unordered_map<int, std::vector<int>>& deactivationTrackerToMetricMap,
- std::vector<int>& metricsWithActivation,
- std::map<int64_t, uint64_t>& newStateProtoHashes,
- std::set<int64_t>& noReportMetricIds);
+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 int64_t currentTimeNs,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<MetricProducer>>& oldMetricProducers,
+ const std::unordered_map<int64_t, int>& oldMetricProducerMap,
+ const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const std::map<int64_t, uint64_t>& oldStateProtoHashes,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
+ std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::vector<sp<MetricProducer>>& newMetricProducers,
+ std::unordered_map<int64_t, int>& newMetricProducerMap,
+ std::vector<sp<AnomalyTracker>>& newAlertTrackers,
+ std::unordered_map<int64_t, int>& newAlertTrackerMap,
+ std::vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::unordered_map<int, std::vector<int>>& activationTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation, std::map<int64_t, uint64_t>& newStateProtoHashes,
+ std::set<int64_t>& noReportMetricIds);
} // namespace statsd
} // namespace os
diff --git a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 915c4aef..c44c8186 100644
--- a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -65,32 +65,42 @@ bool hasLeafNode(const FieldMatcher& matcher) {
} // namespace
-sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
- const sp<UidMap>& uidMap) {
+sp<AtomMatchingTracker> createAtomMatchingTracker(
+ const AtomMatcher& logMatcher, const int index, const sp<UidMap>& uidMap,
+ optional<InvalidConfigReason>& invalidConfigReason) {
string serializedMatcher;
if (!logMatcher.SerializeToString(&serializedMatcher)) {
ALOGE("Unable to serialize matcher %lld", (long long)logMatcher.id());
+ invalidConfigReason = createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_SERIALIZATION_FAILED, logMatcher.id());
return nullptr;
}
uint64_t protoHash = Hash64(serializedMatcher);
switch (logMatcher.contents_case()) {
- case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
- return new SimpleAtomMatchingTracker(logMatcher.id(), index, protoHash,
- logMatcher.simple_atom_matcher(), uidMap);
+ case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
+ sp<AtomMatchingTracker> simpleAtomMatcher = new SimpleAtomMatchingTracker(
+ logMatcher.id(), index, protoHash, logMatcher.simple_atom_matcher(), uidMap);
+ return simpleAtomMatcher;
+ }
case AtomMatcher::ContentsCase::kCombination:
return new CombinationAtomMatchingTracker(logMatcher.id(), index, protoHash);
default:
ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
+ invalidConfigReason = createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE, logMatcher.id());
return nullptr;
}
}
sp<ConditionTracker> createConditionTracker(
const ConfigKey& key, const Predicate& predicate, const int index,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ optional<InvalidConfigReason>& invalidConfigReason) {
string serializedPredicate;
if (!predicate.SerializeToString(&serializedPredicate)) {
ALOGE("Unable to serialize predicate %lld", (long long)predicate.id());
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_SERIALIZATION_FAILED, predicate.id());
return nullptr;
}
uint64_t protoHash = Hash64(serializedPredicate);
@@ -104,17 +114,19 @@ sp<ConditionTracker> createConditionTracker(
}
default:
ALOGE("Predicate \"%lld\" malformed", (long long)predicate.id());
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_MALFORMED_CONTENTS_CASE, predicate.id());
return nullptr;
}
}
-bool getMetricProtoHash(const StatsdConfig& config, const MessageLite& metric, const int64_t id,
- const unordered_map<int64_t, int>& metricToActivationMap,
- uint64_t& metricHash) {
+optional<InvalidConfigReason> getMetricProtoHash(
+ const StatsdConfig& config, const MessageLite& metric, const int64_t id,
+ const unordered_map<int64_t, int>& metricToActivationMap, uint64_t& metricHash) {
string serializedMetric;
if (!metric.SerializeToString(&serializedMetric)) {
ALOGE("Unable to serialize metric %lld", (long long)id);
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SERIALIZATION_FAILED, id);
}
metricHash = Hash64(serializedMetric);
@@ -125,38 +137,41 @@ bool getMetricProtoHash(const StatsdConfig& config, const MessageLite& metric, c
const MetricActivation& activation = config.metric_activation(metricActivationIt->second);
if (!activation.SerializeToString(&serializedActivation)) {
ALOGE("Unable to serialize metric activation for metric %lld", (long long)id);
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_ACTIVATION_SERIALIZATION_FAILED,
+ id);
}
metricHash = Hash64(to_string(metricHash).append(to_string(Hash64(serializedActivation))));
}
- return true;
+ return nullopt;
}
-bool handleMetricWithAtomMatchingTrackers(
- const int64_t matcherId, const int metricIndex, const bool enforceOneAtom,
- const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+optional<InvalidConfigReason> handleMetricWithAtomMatchingTrackers(
+ const int64_t matcherId, const int64_t metricId, const int metricIndex,
+ const bool enforceOneAtom, const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& atomMatchingTrackerMap,
unordered_map<int, vector<int>>& trackerToMetricMap, int& logTrackerIndex) {
auto logTrackerIt = atomMatchingTrackerMap.find(matcherId);
if (logTrackerIt == atomMatchingTrackerMap.end()) {
ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)matcherId);
- return false;
+ return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_METRIC_MATCHER_NOT_FOUND,
+ metricId, matcherId);
}
if (enforceOneAtom && allAtomMatchingTrackers[logTrackerIt->second]->getAtomIds().size() > 1) {
ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
"the \"what\" can only be about one atom type. trigger_event matchers can also only "
"be about one atom type.",
(long long)matcherId);
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_MATCHER_MORE_THAN_ONE_ATOM, metricId, matcherId);
}
logTrackerIndex = logTrackerIt->second;
auto& metric_list = trackerToMetricMap[logTrackerIndex];
metric_list.push_back(metricIndex);
- return true;
+ return nullopt;
}
-bool handleMetricWithConditions(
- const int64_t condition, const int metricIndex,
+optional<InvalidConfigReason> handleMetricWithConditions(
+ const int64_t condition, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& conditionTrackerMap,
const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
links,
@@ -165,14 +180,16 @@ bool handleMetricWithConditions(
auto condition_it = conditionTrackerMap.find(condition);
if (condition_it == conditionTrackerMap.end()) {
ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_METRIC_CONDITION_NOT_FOUND, metricId, condition);
}
-
for (const auto& link : links) {
auto it = conditionTrackerMap.find(link.condition());
if (it == conditionTrackerMap.end()) {
ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
- return false;
+ return createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_METRIC_CONDITION_LINK_NOT_FOUND, metricId,
+ link.condition());
}
}
conditionIndex = condition_it->second;
@@ -180,7 +197,7 @@ bool handleMetricWithConditions(
// will create new vector if not exist before.
auto& metricList = conditionToMetricMap[condition_it->second];
metricList.push_back(metricIndex);
- return true;
+ return nullopt;
}
// Initializes state data structures for a metric.
@@ -195,8 +212,9 @@ bool handleMetricWithConditions(
// [stateGroupMap]: this map should contain the mapping from states ids and state
// values to state group ids for all states that this metric
// is interested in
-bool handleMetricWithStates(
- const StatsdConfig& config, const ::google::protobuf::RepeatedField<int64_t>& stateIds,
+optional<InvalidConfigReason> handleMetricWithStates(
+ const StatsdConfig& config, const int64_t metricId,
+ const ::google::protobuf::RepeatedField<int64_t>& stateIds,
const unordered_map<int64_t, int>& stateAtomIdMap,
const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
vector<int>& slicedStateAtoms,
@@ -205,7 +223,8 @@ bool handleMetricWithStates(
auto it = stateAtomIdMap.find(stateId);
if (it == stateAtomIdMap.end()) {
ALOGW("cannot find State %" PRId64 " in the config", stateId);
- return false;
+ return createInvalidConfigReasonWithState(INVALID_CONFIG_REASON_METRIC_STATE_NOT_FOUND,
+ metricId, stateId);
}
int atomId = it->second;
slicedStateAtoms.push_back(atomId);
@@ -215,22 +234,64 @@ bool handleMetricWithStates(
stateGroupMap[atomId] = stateIt->second;
}
}
- return true;
+ return nullopt;
}
-bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
- const vector<Matcher>& dimensionsInWhat) {
+optional<InvalidConfigReason> handleMetricWithStateLink(const int64_t metricId,
+ const FieldMatcher& stateMatcher,
+ const vector<Matcher>& dimensionsInWhat) {
vector<Matcher> stateMatchers;
translateFieldMatcher(stateMatcher, &stateMatchers);
+ if (!subsetDimensions(stateMatchers, dimensionsInWhat)) {
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINKS_NOT_SUBSET_DIM_IN_WHAT,
+ metricId);
+ }
+ return nullopt;
+}
- return subsetDimensions(stateMatchers, dimensionsInWhat);
+optional<InvalidConfigReason> handleMetricWithSampling(
+ const int64_t metricId, const DimensionalSamplingInfo& dimSamplingInfo,
+ const vector<Matcher>& dimensionsInWhat, SamplingInfo& samplingInfo) {
+ if (!dimSamplingInfo.has_sampled_what_field()) {
+ ALOGE("metric DimensionalSamplingInfo missing sampledWhatField");
+ return InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_MISSING_SAMPLED_FIELD,
+ metricId);
+ }
+
+ if (dimSamplingInfo.shard_count() <= 1) {
+ ALOGE("metric shardCount must be > 1");
+ return InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_INCORRECT_SHARD_COUNT,
+ metricId);
+ }
+ samplingInfo.shardCount = dimSamplingInfo.shard_count();
+
+ if (HasPositionALL(dimSamplingInfo.sampled_what_field()) ||
+ HasPositionANY(dimSamplingInfo.sampled_what_field())) {
+ ALOGE("metric has repeated field with position ALL or ANY as the sampled dimension");
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
+ metricId);
+ }
+
+ translateFieldMatcher(dimSamplingInfo.sampled_what_field(), &samplingInfo.sampledWhatFields);
+ if (samplingInfo.sampledWhatFields.size() != 1) {
+ ALOGE("metric has incorrect number of sampled dimension fields");
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
+ metricId);
+ }
+ if (!subsetDimensions(samplingInfo.sampledWhatFields, dimensionsInWhat)) {
+ return InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELDS_NOT_SUBSET_DIM_IN_WHAT, metricId);
+ }
+ return nullopt;
}
// Validates a metricActivation and populates state.
// EventActivationMap and EventDeactivationMap are supplied to a MetricProducer
// to provide the producer with state about its activators and deactivators.
// Returns false if there are errors.
-bool handleMetricActivation(
+optional<InvalidConfigReason> handleMetricActivation(
const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
const unordered_map<int64_t, int>& atomMatchingTrackerMap,
@@ -242,7 +303,7 @@ bool handleMetricActivation(
// Check if metric has an associated activation
auto itr = metricToActivationMap.find(metricId);
if (itr == metricToActivationMap.end()) {
- return true;
+ return nullopt;
}
int activationIndex = itr->second;
@@ -254,7 +315,9 @@ bool handleMetricActivation(
auto itr = atomMatchingTrackerMap.find(activation.atom_matcher_id());
if (itr == atomMatchingTrackerMap.end()) {
ALOGE("Atom matcher not found for event activation.");
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND, metricId,
+ activation.atom_matcher_id());
}
ActivationType activationType = (activation.has_activation_type())
@@ -271,7 +334,9 @@ bool handleMetricActivation(
itr = atomMatchingTrackerMap.find(activation.deactivation_atom_matcher_id());
if (itr == atomMatchingTrackerMap.end()) {
ALOGE("Atom matcher not found for event deactivation.");
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND, metricId,
+ activation.deactivation_atom_matcher_id());
}
int deactivationAtomMatcherIndex = itr->second;
deactivationAtomTrackerToMetricMap[deactivationAtomMatcherIndex].push_back(metricIndex);
@@ -280,13 +345,13 @@ bool handleMetricActivation(
}
metricsWithActivation.push_back(metricIndex);
- return true;
+ return nullopt;
}
// Validates a metricActivation and populates state.
// Fills the new event activation/deactivation maps, preserving the existing activations
// Returns false if there are errors.
-bool handleMetricActivationOnConfigUpdate(
+optional<InvalidConfigReason> handleMetricActivationOnConfigUpdate(
const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -300,7 +365,7 @@ bool handleMetricActivationOnConfigUpdate(
// Check if metric has an associated activation.
const auto& itr = metricToActivationMap.find(metricId);
if (itr == metricToActivationMap.end()) {
- return true;
+ return nullopt;
}
int activationIndex = itr->second;
@@ -312,7 +377,9 @@ bool handleMetricActivationOnConfigUpdate(
const auto& newActivationIt = newAtomMatchingTrackerMap.find(activationMatcherId);
if (newActivationIt == newAtomMatchingTrackerMap.end()) {
ALOGE("Atom matcher not found in new config for event activation.");
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND_NEW, metricId,
+ activationMatcherId);
}
int newActivationMatcherIndex = newActivationIt->second;
@@ -320,13 +387,17 @@ bool handleMetricActivationOnConfigUpdate(
const auto& oldActivationIt = oldAtomMatchingTrackerMap.find(activationMatcherId);
if (oldActivationIt == oldAtomMatchingTrackerMap.end()) {
ALOGE("Atom matcher not found in existing config for event activation.");
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND_EXISTING, metricId,
+ activationMatcherId);
}
int oldActivationMatcherIndex = oldActivationIt->second;
const auto& oldEventActivationIt = oldEventActivationMap.find(oldActivationMatcherIndex);
if (oldEventActivationIt == oldEventActivationMap.end()) {
ALOGE("Could not find existing event activation to update");
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_NOT_FOUND_EXISTING, metricId,
+ activationMatcherId);
}
newEventActivationMap.emplace(newActivationMatcherIndex, oldEventActivationIt->second);
activationAtomTrackerToMetricMap[newActivationMatcherIndex].push_back(metricIndex);
@@ -337,7 +408,9 @@ bool handleMetricActivationOnConfigUpdate(
const auto& newDeactivationIt = newAtomMatchingTrackerMap.find(deactivationMatcherId);
if (newDeactivationIt == newAtomMatchingTrackerMap.end()) {
ALOGE("Deactivation atom matcher not found in new config for event activation.");
- return false;
+ return createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND_NEW, metricId,
+ deactivationMatcherId);
}
int newDeactivationMatcherIndex = newDeactivationIt->second;
newEventDeactivationMap[newDeactivationMatcherIndex].push_back(
@@ -347,7 +420,7 @@ bool handleMetricActivationOnConfigUpdate(
}
metricsWithActivation.push_back(metricIndex);
- return true;
+ return nullopt;
}
optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
@@ -365,29 +438,34 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
if (!metric.has_id() || !metric.has_what()) {
ALOGE("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
return nullopt;
}
int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), metric.id(), metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
int conditionIndex = -1;
if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, conditionIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else {
if (metric.links_size() > 0) {
ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
return nullopt;
}
}
@@ -395,28 +473,47 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
std::vector<int> slicedStateAtoms;
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
if (metric.slice_by_state_size() > 0) {
- if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
- allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ invalidConfigReason =
+ handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else {
if (metric.state_link_size() > 0) {
ALOGW("CountMetric has a MetricStateLink but doesn't have a slice_by_state");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
+ return nullopt;
+ }
+ }
+
+ // Check that all metric state links are a subset of dimensions_in_what fields.
+ std::vector<Matcher> dimensionsInWhat;
+ translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+ for (const auto& stateLink : metric.state_link()) {
+ invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
+ dimensionsInWhat);
+ if (invalidConfigReason.has_value()) {
+ ALOGW("CountMetric's MetricStateLinks must be a subset of dimensions in what");
return nullopt;
}
}
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
- atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation,
- eventActivationMap, eventDeactivationMap)) {
+ invalidConfigReason = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ invalidConfigReason =
+ getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
@@ -424,12 +521,27 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
(metric.threshold().value_comparison_case() == UploadThreshold::kLtFloat ||
metric.threshold().value_comparison_case() == UploadThreshold::kGtFloat)) {
ALOGW("Count metric incorrect upload threshold type or no type used");
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_BAD_THRESHOLD, metric.id());
return nullopt;
}
- return {new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
+ sp<MetricProducer> metricProducer =
+ new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
metricHash, timeBaseNs, currentTimeNs, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+
+ SamplingInfo samplingInfo;
+ if (metric.has_dimensional_sampling_info()) {
+ invalidConfigReason = handleMetricWithSampling(
+ metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
+ metricProducer->setSamplingInfo(samplingInfo);
+ }
+
+ return metricProducer;
}
optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
@@ -447,15 +559,19 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
if (!metric.has_id() || !metric.has_what()) {
ALOGE("cannot find metric id or \"what\" in DurationMetric \"%lld\"",
(long long)metric.id());
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
return nullopt;
}
const auto& what_it = conditionTrackerMap.find(metric.what());
if (what_it == conditionTrackerMap.end()) {
ALOGE("DurationMetric's \"what\" is not present in the condition trackers");
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_FOUND, metric.id(), metric.what());
return nullopt;
}
@@ -463,6 +579,8 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
const Predicate& durationWhat = config.predicate(whatIndex);
if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
ALOGE("DurationMetric's \"what\" must be a simple condition");
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_SIMPLE, metric.id(), metric.what());
return nullopt;
}
@@ -470,40 +588,52 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
bool nesting = simplePredicate.count_nesting();
int startIndex = -1, stopIndex = -1, stopAllIndex = -1;
- if (!simplePredicate.has_start() ||
- !handleMetricWithAtomMatchingTrackers(
- simplePredicate.start(), metricIndex, metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, startIndex)) {
+ if (!simplePredicate.has_start()) {
ALOGE("Duration metrics must specify a valid start event matcher");
+ invalidConfigReason = createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_MISSING_START, metric.id(), metric.what());
return nullopt;
}
-
- if (simplePredicate.has_stop() &&
- !handleMetricWithAtomMatchingTrackers(
- simplePredicate.stop(), metricIndex, metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, stopIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ simplePredicate.start(), metric.id(), metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, startIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
- if (simplePredicate.has_stop_all() &&
- !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, stopAllIndex)) {
- return nullopt;
+ if (simplePredicate.has_stop()) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ simplePredicate.stop(), metric.id(), metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, stopIndex);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
+ }
+
+ if (simplePredicate.has_stop_all()) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ simplePredicate.stop_all(), metric.id(), metricIndex,
+ metric.has_dimensions_in_what(), allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, stopAllIndex);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
}
FieldMatcher internalDimensions = simplePredicate.dimensions();
int conditionIndex = -1;
if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, conditionIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else if (metric.links_size() > 0) {
ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
return nullopt;
}
@@ -512,14 +642,21 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
if (metric.slice_by_state_size() > 0) {
if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_DURATION_METRIC_MAX_SPARSE_HAS_SLICE_BY_STATE,
+ metric.id());
return nullopt;
}
- if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
- allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ invalidConfigReason =
+ handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else if (metric.state_link_size() > 0) {
ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
return nullopt;
}
@@ -527,7 +664,9 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
std::vector<Matcher> dimensionsInWhat;
translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
for (const auto& stateLink : metric.state_link()) {
- if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+ invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
+ dimensionsInWhat);
+ if (invalidConfigReason.has_value()) {
ALOGW("DurationMetric's MetricStateLinks must be a subset of dimensions in what");
return nullopt;
}
@@ -535,15 +674,18 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
- atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation,
- eventActivationMap, eventDeactivationMap)) {
+ invalidConfigReason = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ invalidConfigReason =
+ getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
@@ -556,20 +698,35 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
break;
default:
ALOGE("Duration metric incorrect upload threshold type or no type used");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_BAD_THRESHOLD, metric.id());
return nullopt;
- break;
}
}
- sp<MetricProducer> producer = new DurationMetricProducer(
+ sp<MetricProducer> metricProducer = new DurationMetricProducer(
key, metric, conditionIndex, initialConditionCache, whatIndex, startIndex, stopIndex,
stopAllIndex, nesting, wizard, metricHash, internalDimensions, timeBaseNs,
currentTimeNs, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
stateGroupMap);
- if (!producer->isValid()) {
+ if (!metricProducer->isValid()) {
+ // TODO: Remove once invalidConfigReason is added to the DurationMetricProducer constructor
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_DURATION_METRIC_PRODUCER_INVALID, metric.id());
return nullopt;
}
- return {producer};
+
+ SamplingInfo samplingInfo;
+ if (metric.has_dimensional_sampling_info()) {
+ invalidConfigReason = handleMetricWithSampling(
+ metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
+ metricProducer->setSamplingInfo(samplingInfo);
+ }
+
+ return metricProducer;
}
optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
@@ -585,42 +742,50 @@ optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
if (!metric.has_id() || !metric.has_what()) {
ALOGE("cannot find the metric name or what in config");
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
return nullopt;
}
int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), metric.id(), metricIndex, false, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
int conditionIndex = -1;
if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, conditionIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else {
if (metric.links_size() > 0) {
ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
return nullopt;
}
}
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
- atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation,
- eventActivationMap, eventDeactivationMap);
- if (!success) return nullptr;
+ invalidConfigReason = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ if (invalidConfigReason.has_value()) return nullptr;
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ invalidConfigReason =
+ getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
@@ -646,32 +811,41 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
if (!metric.has_id() || !metric.has_what()) {
ALOGE("cannot find metric id or \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
return nullopt;
}
if (!metric.has_value_field()) {
ALOGE("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_VALUE_METRIC_MISSING_VALUE_FIELD, metric.id());
return nullopt;
}
if (HasPositionALL(metric.value_field())) {
ALOGE("value field with position ALL is not supported. ValueMetric \"%lld\"",
(long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_VALUE_METRIC_VALUE_FIELD_HAS_POSITION_ALL, metric.id());
return nullopt;
}
std::vector<Matcher> fieldMatchers;
translateFieldMatcher(metric.value_field(), &fieldMatchers);
if (fieldMatchers.size() < 1) {
ALOGE("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_VALUE_METRIC_HAS_INCORRECT_VALUE_FIELD, metric.id());
return nullopt;
}
int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
- /*enforceOneAtom=*/true, allAtomMatchingTrackers,
- atomMatchingTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), metric.id(), metricIndex,
+ /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
@@ -681,25 +855,32 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
int conditionIndex = -1;
if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, conditionIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else if (metric.links_size() > 0) {
ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
return nullopt;
}
std::vector<int> slicedStateAtoms;
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
if (metric.slice_by_state_size() > 0) {
- if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
- allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ invalidConfigReason =
+ handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else if (metric.state_link_size() > 0) {
ALOGE("ValueMetric has a MetricStateLink but doesn't have a sliced state");
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
return nullopt;
}
@@ -707,7 +888,9 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
std::vector<Matcher> dimensionsInWhat;
translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
for (const auto& stateLink : metric.state_link()) {
- if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+ invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
+ dimensionsInWhat);
+ if (invalidConfigReason.has_value()) {
ALOGW("ValueMetric's MetricStateLinks must be a subset of the dimensions in what");
return nullopt;
}
@@ -715,15 +898,18 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
- atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation,
- eventActivationMap, eventDeactivationMap)) {
+ invalidConfigReason = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ invalidConfigReason =
+ getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
@@ -744,7 +930,7 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
? optional<int64_t>(metric.condition_correction_threshold_nanos())
: nullopt;
- return new NumericValueMetricProducer(
+ sp<MetricProducer> metricProducer = new NumericValueMetricProducer(
key, metric, metricHash, {pullTagId, pullerManager},
{timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
conditionCorrectionThresholdNs, getAppUpgradeBucketSplit(metric)},
@@ -753,6 +939,18 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
{conditionIndex, metric.links(), initialConditionCache, wizard},
{metric.state_link(), slicedStateAtoms, stateGroupMap},
{eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit});
+
+ SamplingInfo samplingInfo;
+ if (metric.has_dimensional_sampling_info()) {
+ invalidConfigReason = handleMetricWithSampling(
+ metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
+ metricProducer->setSamplingInfo(samplingInfo);
+ }
+
+ return metricProducer;
}
optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
@@ -772,56 +970,72 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
if (!metric.has_id() || !metric.has_what()) {
ALOGE("cannot find metric id or \"what\" in KllMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
return nullopt;
}
if (!metric.has_kll_field()) {
ALOGE("cannot find \"kll_field\" in KllMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_KLL_METRIC_MISSING_KLL_FIELD, metric.id());
return nullopt;
}
if (HasPositionALL(metric.kll_field())) {
ALOGE("kll field with position ALL is not supported. KllMetric \"%lld\"",
(long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_KLL_METRIC_KLL_FIELD_HAS_POSITION_ALL, metric.id());
return nullopt;
}
std::vector<Matcher> fieldMatchers;
translateFieldMatcher(metric.kll_field(), &fieldMatchers);
if (fieldMatchers.empty()) {
ALOGE("incorrect \"kll_field\" in KllMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_KLL_METRIC_HAS_INCORRECT_KLL_FIELD, metric.id());
return nullopt;
}
int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
- /*enforceOneAtom=*/true, allAtomMatchingTrackers,
- atomMatchingTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), metric.id(), metricIndex,
+ /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
int conditionIndex = -1;
if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, conditionIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else if (metric.links_size() > 0) {
ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
return nullopt;
}
std::vector<int> slicedStateAtoms;
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
if (metric.slice_by_state_size() > 0) {
- if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
- allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ invalidConfigReason =
+ handleMetricWithStates(config, metric.id(), metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else if (metric.state_link_size() > 0) {
ALOGE("KllMetric has a MetricStateLink but doesn't have a sliced state");
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE, metric.id());
return nullopt;
}
@@ -829,7 +1043,9 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
std::vector<Matcher> dimensionsInWhat;
translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
for (const auto& stateLink : metric.state_link()) {
- if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+ invalidConfigReason = handleMetricWithStateLink(metric.id(), stateLink.fields_in_what(),
+ dimensionsInWhat);
+ if (invalidConfigReason.has_value()) {
ALOGW("KllMetric's MetricStateLinks must be a subset of the dimensions in what");
return nullopt;
}
@@ -837,15 +1053,18 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
- atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation,
- eventActivationMap, eventDeactivationMap)) {
+ invalidConfigReason = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ invalidConfigReason =
+ getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
@@ -862,7 +1081,7 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
const auto [dimensionSoftLimit, dimensionHardLimit] =
StatsdStats::getAtomDimensionKeySizeLimits(atomTagId);
- return new KllMetricProducer(
+ sp<MetricProducer> metricProducer = new KllMetricProducer(
key, metric, metricHash, {/*pullTagId=*/-1, pullerManager},
{timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
/*conditionCorrectionThresholdNs=*/nullopt, getAppUpgradeBucketSplit(metric)},
@@ -871,6 +1090,18 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
{conditionIndex, metric.links(), initialConditionCache, wizard},
{metric.state_link(), slicedStateAtoms, stateGroupMap},
{eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit});
+
+ SamplingInfo samplingInfo;
+ if (metric.has_dimensional_sampling_info()) {
+ invalidConfigReason = handleMetricWithSampling(
+ metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
+ metricProducer->setSamplingInfo(samplingInfo);
+ }
+
+ return metricProducer;
}
optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
@@ -888,9 +1119,11 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason) {
if (!metric.has_id() || !metric.has_what()) {
ALOGE("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
+ invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metric.id());
return nullopt;
}
@@ -898,28 +1131,28 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
(metric.gauge_fields_filter().include_all() == false)) &&
!hasLeafNode(metric.gauge_fields_filter().fields())) {
ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_GAUGE_METRIC_INCORRECT_FIELD_FILTER, metric.id());
return nullopt;
}
if ((metric.gauge_fields_filter().has_include_all() &&
metric.gauge_fields_filter().include_all() == true) &&
hasLeafNode(metric.gauge_fields_filter().fields())) {
ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_GAUGE_METRIC_INCORRECT_FIELD_FILTER, metric.id());
return nullopt;
}
int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.what(), metric.id(), metricIndex, true, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, trackerToMetricMap, trackerIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
- // For GaugeMetric atom, it should be simple matcher with one tagId.
- if (atomMatcher->getAtomIds().size() != 1) {
- return nullopt;
- }
int atomTagId = *(atomMatcher->getAtomIds().begin());
int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;
@@ -928,17 +1161,22 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
if (metric.has_trigger_event()) {
if (pullTagId == -1) {
ALOGW("Pull atom not specified for trigger");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_PULL_ATOM, metric.id());
return nullopt;
}
// trigger_event should be used with FIRST_N_SAMPLES
if (metric.sampling_type() != GaugeMetric::FIRST_N_SAMPLES) {
ALOGW("Gauge Metric with trigger event must have sampling type FIRST_N_SAMPLES");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_FIRST_N_SAMPLES, metric.id());
return nullopt;
}
- if (!handleMetricWithAtomMatchingTrackers(metric.trigger_event(), metricIndex,
- /*enforceOneAtom=*/true, allAtomMatchingTrackers,
- atomMatchingTrackerMap, trackerToMetricMap,
- triggerTrackerIndex)) {
+ invalidConfigReason = handleMetricWithAtomMatchingTrackers(
+ metric.trigger_event(), metric.id(), metricIndex,
+ /*enforceOneAtom=*/true, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, triggerTrackerIndex);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
sp<AtomMatchingTracker> triggerAtomMatcher =
@@ -949,65 +1187,94 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
if (!metric.has_trigger_event() && pullTagId != -1 &&
metric.sampling_type() == GaugeMetric::FIRST_N_SAMPLES) {
ALOGW("FIRST_N_SAMPLES is only for pushed event or pull_on_trigger");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_GAUGE_METRIC_FIRST_N_SAMPLES_WITH_WRONG_EVENT, metric.id());
return nullopt;
}
int conditionIndex = -1;
if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
+ invalidConfigReason = handleMetricWithConditions(
+ metric.condition(), metric.id(), metricIndex, conditionTrackerMap, metric.links(),
+ allConditionTrackers, conditionIndex, conditionToMetricMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
} else {
if (metric.links_size() > 0) {
ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION, metric.id());
return nullopt;
}
}
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
- atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation,
- eventActivationMap, eventDeactivationMap)) {
+ invalidConfigReason = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ invalidConfigReason =
+ getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash);
+ if (invalidConfigReason.has_value()) {
return nullopt;
}
const auto [dimensionSoftLimit, dimensionHardLimit] =
StatsdStats::getAtomDimensionKeySizeLimits(pullTagId);
- return {new GaugeMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- metricHash, trackerIndex, matcherWizard, pullTagId,
- triggerAtomId, atomTagId, timeBaseNs, currentTimeNs,
- pullerManager, eventActivationMap, eventDeactivationMap,
- dimensionSoftLimit, dimensionHardLimit)};
+ sp<MetricProducer> metricProducer = new GaugeMetricProducer(
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash, trackerIndex,
+ matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseNs, currentTimeNs,
+ pullerManager, eventActivationMap, eventDeactivationMap, dimensionSoftLimit,
+ dimensionHardLimit);
+
+ SamplingInfo samplingInfo;
+ std::vector<Matcher> dimensionsInWhat;
+ translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+ if (metric.has_dimensional_sampling_info()) {
+ invalidConfigReason = handleMetricWithSampling(
+ metric.id(), metric.dimensional_sampling_info(), dimensionsInWhat, samplingInfo);
+ if (invalidConfigReason.has_value()) {
+ return nullopt;
+ }
+ metricProducer->setSamplingInfo(samplingInfo);
+ }
+
+ return metricProducer;
}
optional<sp<AnomalyTracker>> createAnomalyTracker(
const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
const UpdateStatus& updateStatus, const int64_t currentTimeNs,
const unordered_map<int64_t, int>& metricProducerMap,
- vector<sp<MetricProducer>>& allMetricProducers) {
+ vector<sp<MetricProducer>>& allMetricProducers,
+ optional<InvalidConfigReason>& invalidConfigReason) {
const auto& itr = metricProducerMap.find(alert.metric_id());
if (itr == metricProducerMap.end()) {
ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
(long long)alert.metric_id());
+ invalidConfigReason = createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND, alert.metric_id(), alert.id());
return nullopt;
}
if (!alert.has_trigger_if_sum_gt()) {
ALOGW("invalid alert: missing threshold");
+ invalidConfigReason = createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_THRESHOLD_MISSING, alert.id());
return nullopt;
}
if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
alert.num_buckets());
+ invalidConfigReason = createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_INVALID_TRIGGER_OR_NUM_BUCKETS, alert.id());
return nullopt;
}
const int metricIndex = itr->second;
@@ -1016,30 +1283,36 @@ optional<sp<AnomalyTracker>> createAnomalyTracker(
metric->addAnomalyTracker(alert, anomalyAlarmMonitor, updateStatus, currentTimeNs);
if (anomalyTracker == nullptr) {
// The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
+ invalidConfigReason = createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_CANNOT_ADD_ANOMALY, alert.metric_id(), alert.id());
return nullopt;
}
return {anomalyTracker};
}
-bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- unordered_map<int64_t, int>& atomMatchingTrackerMap,
- vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- unordered_map<int, vector<int>>& allTagIdsToMatchersMap) {
+optional<InvalidConfigReason> initAtomMatchingTrackers(
+ const StatsdConfig& config, const sp<UidMap>& uidMap,
+ unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ unordered_map<int, vector<int>>& allTagIdsToMatchersMap) {
vector<AtomMatcher> matcherConfigs;
const int atomMatcherCount = config.atom_matcher_size();
matcherConfigs.reserve(atomMatcherCount);
allAtomMatchingTrackers.reserve(atomMatcherCount);
+ optional<InvalidConfigReason> invalidConfigReason;
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& logMatcher = config.atom_matcher(i);
- sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, i, uidMap);
+ sp<AtomMatchingTracker> tracker =
+ createAtomMatchingTracker(logMatcher, i, uidMap, invalidConfigReason);
if (tracker == nullptr) {
- return false;
+ return invalidConfigReason;
}
allAtomMatchingTrackers.push_back(tracker);
if (atomMatchingTrackerMap.find(logMatcher.id()) != atomMatchingTrackerMap.end()) {
ALOGE("Duplicate AtomMatcher found!");
- return false;
+ return createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
+ logMatcher.id());
}
atomMatchingTrackerMap[logMatcher.id()] = i;
matcherConfigs.push_back(logMatcher);
@@ -1048,9 +1321,10 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
vector<bool> stackTracker2(allAtomMatchingTrackers.size(), false);
for (size_t matcherIndex = 0; matcherIndex < allAtomMatchingTrackers.size(); matcherIndex++) {
auto& matcher = allAtomMatchingTrackers[matcherIndex];
- if (!matcher->init(matcherConfigs, allAtomMatchingTrackers, atomMatchingTrackerMap,
- stackTracker2)) {
- return false;
+ invalidConfigReason = matcher->init(matcherConfigs, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, stackTracker2);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
// Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
@@ -1071,32 +1345,35 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
}
}
- return true;
+ return nullopt;
}
-bool initConditions(const ConfigKey& key, const StatsdConfig& config,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap,
- unordered_map<int64_t, int>& conditionTrackerMap,
- vector<sp<ConditionTracker>>& allConditionTrackers,
- unordered_map<int, std::vector<int>>& trackerToConditionMap,
- vector<ConditionState>& initialConditionCache) {
+optional<InvalidConfigReason> initConditions(
+ const ConfigKey& key, const StatsdConfig& config,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ unordered_map<int64_t, int>& conditionTrackerMap,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ vector<ConditionState>& initialConditionCache) {
vector<Predicate> conditionConfigs;
const int conditionTrackerCount = config.predicate_size();
conditionConfigs.reserve(conditionTrackerCount);
allConditionTrackers.reserve(conditionTrackerCount);
initialConditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
+ optional<InvalidConfigReason> invalidConfigReason;
for (int i = 0; i < conditionTrackerCount; i++) {
const Predicate& condition = config.predicate(i);
- sp<ConditionTracker> tracker =
- createConditionTracker(key, condition, i, atomMatchingTrackerMap);
+ sp<ConditionTracker> tracker = createConditionTracker(
+ key, condition, i, atomMatchingTrackerMap, invalidConfigReason);
if (tracker == nullptr) {
- return false;
+ return invalidConfigReason;
}
allConditionTrackers.push_back(tracker);
if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
ALOGE("Duplicate Predicate found!");
- return false;
+ return createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
+ condition.id());
}
conditionTrackerMap[condition.id()] = i;
conditionConfigs.push_back(condition);
@@ -1105,21 +1382,24 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
vector<bool> stackTracker(allConditionTrackers.size(), false);
for (size_t i = 0; i < allConditionTrackers.size(); i++) {
auto& conditionTracker = allConditionTrackers[i];
- if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
- stackTracker, initialConditionCache)) {
- return false;
+ invalidConfigReason =
+ conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
+ stackTracker, initialConditionCache);
+ if (invalidConfigReason.has_value()) {
+ return invalidConfigReason;
}
for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
auto& conditionList = trackerToConditionMap[trackerIndex];
conditionList.push_back(i);
}
}
- return true;
+ return nullopt;
}
-bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
- map<int64_t, uint64_t>& stateProtoHashes) {
+optional<InvalidConfigReason> initStates(
+ const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ map<int64_t, uint64_t>& stateProtoHashes) {
for (int i = 0; i < config.state_size(); i++) {
const State& state = config.state(i);
const int64_t stateId = state.id();
@@ -1128,7 +1408,8 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
string serializedState;
if (!state.SerializeToString(&serializedState)) {
ALOGE("Unable to serialize state %lld", (long long)stateId);
- return false;
+ return createInvalidConfigReasonWithState(
+ INVALID_CONFIG_REASON_STATE_SERIALIZATION_FAILED, state.id(), state.atom_id());
}
stateProtoHashes[stateId] = Hash64(serializedState);
@@ -1140,31 +1421,33 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
}
}
- return true;
+ return nullopt;
}
-bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
- const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap,
- const unordered_map<int64_t, int>& conditionTrackerMap,
- const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- const unordered_map<int64_t, int>& stateAtomIdMap,
- const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
- vector<sp<ConditionTracker>>& allConditionTrackers,
- const vector<ConditionState>& initialConditionCache,
- vector<sp<MetricProducer>>& allMetricProducers,
- unordered_map<int, vector<int>>& conditionToMetricMap,
- unordered_map<int, vector<int>>& trackerToMetricMap,
- unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds,
- unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
- unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
+optional<InvalidConfigReason> initMetrics(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& stateAtomIdMap,
+ const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ const vector<ConditionState>& initialConditionCache,
+ vector<sp<MetricProducer>>& allMetricProducers,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap, unordered_map<int64_t, int>& metricMap,
+ std::set<int64_t>& noReportMetricIds,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchingTrackers);
const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
config.event_metric_size() + config.gauge_metric_size() +
config.value_metric_size() + config.kll_metric_size();
allMetricProducers.reserve(allMetricsCount);
+ optional<InvalidConfigReason> invalidConfigReason;
// Construct map from metric id to metric activation index. The map will be used to determine
// the metric activation corresponding to a metric.
@@ -1174,7 +1457,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
int64_t metricId = metricActivation.metric_id();
if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS,
+ metricId);
}
metricToActivationMap.insert({metricId, i});
}
@@ -1191,9 +1475,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation);
+ metricsWithActivation, invalidConfigReason);
if (!producer) {
- return false;
+ return invalidConfigReason;
}
allMetricProducers.push_back(producer.value());
}
@@ -1210,9 +1494,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation);
+ metricsWithActivation, invalidConfigReason);
if (!producer) {
- return false;
+ return invalidConfigReason;
}
allMetricProducers.push_back(producer.value());
}
@@ -1227,9 +1511,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap,
initialConditionCache, wizard, metricToActivationMap, trackerToMetricMap,
conditionToMetricMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, invalidConfigReason);
if (!producer) {
- return false;
+ return invalidConfigReason;
}
allMetricProducers.push_back(producer.value());
}
@@ -1245,9 +1529,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation);
+ metricsWithActivation, invalidConfigReason);
if (!producer) {
- return false;
+ return invalidConfigReason;
}
allMetricProducers.push_back(producer.value());
}
@@ -1263,9 +1547,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation);
+ metricsWithActivation, invalidConfigReason);
if (!producer) {
- return false;
+ return invalidConfigReason;
}
allMetricProducers.push_back(producer.value());
}
@@ -1281,9 +1565,9 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation);
+ metricsWithActivation, invalidConfigReason);
if (!producer) {
- return false;
+ return invalidConfigReason;
}
allMetricProducers.push_back(producer.value());
}
@@ -1291,7 +1575,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
const auto no_report_metric = config.no_report_metric(i);
if (metricMap.find(no_report_metric) == metricMap.end()) {
ALOGW("no_report_metric %" PRId64 " not exist", no_report_metric);
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND,
+ no_report_metric);
}
noReportMetricIds.insert(no_report_metric);
}
@@ -1306,40 +1591,41 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
if (whitelistedAtomIds.find(atomId) == whitelistedAtomIds.end()) {
StateManager::getInstance().registerListener(atomId, it);
} else {
- return false;
+ return InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
+ it->getMetricId());
}
}
}
- return true;
+ return nullopt;
}
-bool initAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
- const unordered_map<int64_t, int>& metricProducerMap,
- unordered_map<int64_t, int>& alertTrackerMap,
- const sp<AlarmMonitor>& anomalyAlarmMonitor,
- vector<sp<MetricProducer>>& allMetricProducers,
- vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
+optional<InvalidConfigReason> initAlerts(const StatsdConfig& config, const int64_t currentTimeNs,
+ const unordered_map<int64_t, int>& metricProducerMap,
+ unordered_map<int64_t, int>& alertTrackerMap,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ vector<sp<MetricProducer>>& allMetricProducers,
+ vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
+ optional<InvalidConfigReason> invalidConfigReason;
for (int i = 0; i < config.alert_size(); i++) {
const Alert& alert = config.alert(i);
alertTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
- optional<sp<AnomalyTracker>> anomalyTracker =
- createAnomalyTracker(alert, anomalyAlarmMonitor, UpdateStatus::UPDATE_NEW,
- currentTimeNs, metricProducerMap, allMetricProducers);
+ optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
+ alert, anomalyAlarmMonitor, UpdateStatus::UPDATE_NEW, currentTimeNs,
+ metricProducerMap, allMetricProducers, invalidConfigReason);
if (!anomalyTracker) {
- return false;
+ return invalidConfigReason;
}
allAnomalyTrackers.push_back(anomalyTracker.value());
}
- if (!initSubscribersForSubscriptionType(config, Subscription::ALERT, alertTrackerMap,
- allAnomalyTrackers)) {
- return false;
- }
- return true;
+ return initSubscribersForSubscriptionType(config, Subscription::ALERT, alertTrackerMap,
+ allAnomalyTrackers);
}
-bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
- const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
- const int64_t currentTimeNs, vector<sp<AlarmTracker>>& allAlarmTrackers) {
+optional<InvalidConfigReason> initAlarms(const StatsdConfig& config, const ConfigKey& key,
+ const sp<AlarmMonitor>& periodicAlarmMonitor,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
+ vector<sp<AlarmTracker>>& allAlarmTrackers) {
unordered_map<int64_t, int> alarmTrackerMap;
int64_t startMillis = timeBaseNs / 1000 / 1000;
int64_t currentTimeMillis = currentTimeNs / 1000 / 1000;
@@ -1347,45 +1633,43 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
const Alarm& alarm = config.alarm(i);
if (alarm.offset_millis() <= 0) {
ALOGW("Alarm offset_millis should be larger than 0.");
- return false;
+ return createInvalidConfigReasonWithAlarm(
+ INVALID_CONFIG_REASON_ALARM_OFFSET_LESS_THAN_OR_EQUAL_ZERO, alarm.id());
}
if (alarm.period_millis() <= 0) {
ALOGW("Alarm period_millis should be larger than 0.");
- return false;
+ return createInvalidConfigReasonWithAlarm(
+ INVALID_CONFIG_REASON_ALARM_PERIOD_LESS_THAN_OR_EQUAL_ZERO, alarm.id());
}
alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
allAlarmTrackers.push_back(
new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
}
- if (!initSubscribersForSubscriptionType(config, Subscription::ALARM, alarmTrackerMap,
- allAlarmTrackers)) {
- return false;
- }
- return true;
+ return initSubscribersForSubscriptionType(config, Subscription::ALARM, alarmTrackerMap,
+ allAlarmTrackers);
}
-bool 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 int64_t currentTimeNs,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
- vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- unordered_map<int64_t, int>& atomMatchingTrackerMap,
- vector<sp<ConditionTracker>>& allConditionTrackers,
- unordered_map<int64_t, int>& conditionTrackerMap,
- vector<sp<MetricProducer>>& allMetricProducers,
- unordered_map<int64_t, int>& metricProducerMap,
- vector<sp<AnomalyTracker>>& allAnomalyTrackers,
- vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
- unordered_map<int, std::vector<int>>& conditionToMetricMap,
- unordered_map<int, std::vector<int>>& trackerToMetricMap,
- unordered_map<int, std::vector<int>>& trackerToConditionMap,
- unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
- unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation, map<int64_t, uint64_t>& stateProtoHashes,
- set<int64_t>& noReportMetricIds) {
+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 int64_t currentTimeNs,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
+ vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ unordered_map<int64_t, int>& conditionTrackerMap,
+ vector<sp<MetricProducer>>& allMetricProducers,
+ unordered_map<int64_t, int>& metricProducerMap,
+ vector<sp<AnomalyTracker>>& allAnomalyTrackers,
+ vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
+ unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ unordered_map<int64_t, int>& alertTrackerMap, vector<int>& metricsWithActivation,
+ map<int64_t, uint64_t>& stateProtoHashes, set<int64_t>& noReportMetricIds) {
vector<ConditionState> initialConditionCache;
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
@@ -1393,47 +1677,59 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
config.package_certificate_hash_size_bytes());
- return false;
+ return InvalidConfigReason(INVALID_CONFIG_REASON_PACKAGE_CERT_HASH_SIZE_TOO_LARGE);
}
- if (!initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap, allAtomMatchingTrackers,
- allTagIdsToMatchersMap)) {
+ optional<InvalidConfigReason> invalidConfigReason =
+ initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap,
+ allAtomMatchingTrackers, allTagIdsToMatchersMap);
+ if (invalidConfigReason.has_value()) {
ALOGE("initAtomMatchingTrackers failed");
- return false;
+ return invalidConfigReason;
}
VLOG("initAtomMatchingTrackers succeed...");
- if (!initConditions(key, config, atomMatchingTrackerMap, conditionTrackerMap,
- allConditionTrackers, trackerToConditionMap, initialConditionCache)) {
+ invalidConfigReason =
+ initConditions(key, config, atomMatchingTrackerMap, conditionTrackerMap,
+ allConditionTrackers, trackerToConditionMap, initialConditionCache);
+ if (invalidConfigReason.has_value()) {
ALOGE("initConditionTrackers failed");
- return false;
+ return invalidConfigReason;
}
- if (!initStates(config, stateAtomIdMap, allStateGroupMaps, stateProtoHashes)) {
+ invalidConfigReason = initStates(config, stateAtomIdMap, allStateGroupMaps, stateProtoHashes);
+ if (invalidConfigReason.has_value()) {
ALOGE("initStates failed");
- return false;
+ return invalidConfigReason;
}
- if (!initMetrics(key, config, timeBaseNs, currentTimeNs, pullerManager, atomMatchingTrackerMap,
- conditionTrackerMap, allAtomMatchingTrackers, stateAtomIdMap,
- allStateGroupMaps, allConditionTrackers, initialConditionCache,
- allMetricProducers, conditionToMetricMap, trackerToMetricMap,
- metricProducerMap, noReportMetricIds, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+
+ invalidConfigReason = initMetrics(
+ key, config, timeBaseNs, currentTimeNs, pullerManager, atomMatchingTrackerMap,
+ conditionTrackerMap, allAtomMatchingTrackers, stateAtomIdMap, allStateGroupMaps,
+ allConditionTrackers, initialConditionCache, allMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, metricProducerMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation);
+ if (invalidConfigReason.has_value()) {
ALOGE("initMetricProducers failed");
- return false;
+ return invalidConfigReason;
}
- if (!initAlerts(config, currentTimeNs, metricProducerMap, alertTrackerMap, anomalyAlarmMonitor,
- allMetricProducers, allAnomalyTrackers)) {
+
+ invalidConfigReason = initAlerts(config, currentTimeNs, metricProducerMap, alertTrackerMap,
+ anomalyAlarmMonitor, allMetricProducers, allAnomalyTrackers);
+ if (invalidConfigReason.has_value()) {
ALOGE("initAlerts failed");
- return false;
+ return invalidConfigReason;
}
- if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
- allPeriodicAlarmTrackers)) {
+
+ invalidConfigReason = initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ allPeriodicAlarmTrackers);
+ if (invalidConfigReason.has_value()) {
ALOGE("initAlarms failed");
- return false;
+ return invalidConfigReason;
}
- return true;
+ return nullopt;
}
} // namespace statsd
diff --git a/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 17e4b66b..c99b886b 100644
--- a/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -37,41 +37,45 @@ namespace statsd {
// 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);
+sp<AtomMatchingTracker> createAtomMatchingTracker(
+ const AtomMatcher& logMatcher, const int index, const sp<UidMap>& uidMap,
+ optional<InvalidConfigReason>& invalidConfigReason);
// Create a ConditionTracker.
// input:
// [predicate]: the input Predicate from the StatsdConfig
// [index]: the index of the condition tracker
// [atomMatchingTrackerMap]: map of atom matcher id to its index in allAtomMatchingTrackers
+// [invalidConfigReason]: logging ids if config is invalid
// 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 unordered_map<int64_t, int>& atomMatchingTrackerMap);
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ optional<InvalidConfigReason>& invalidConfigReason);
// Get the hash of a metric, combining the activation if the metric has one.
-bool getMetricProtoHash(const StatsdConfig& config, const google::protobuf::MessageLite& metric,
- const int64_t id,
- const std::unordered_map<int64_t, int>& metricToActivationMap,
- uint64_t& metricHash);
+optional<InvalidConfigReason> getMetricProtoHash(
+ const StatsdConfig& config, const google::protobuf::MessageLite& metric, const 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
-bool handleMetricWithAtomMatchingTrackers(
- const int64_t matcherId, const int metricIndex, const bool enforceOneAtom,
+optional<InvalidConfigReason> handleMetricWithAtomMatchingTrackers(
+ const int64_t matcherId, const int64_t metricId, const 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);
// 1. Validates condition existence, including those in links
// 2. Gets condition index and updates condition to metric map
-bool handleMetricWithConditions(
- const int64_t condition, const int metricIndex,
+optional<InvalidConfigReason> handleMetricWithConditions(
+ const int64_t condition, const int64_t metricId, const int metricIndex,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
links,
@@ -80,8 +84,8 @@ bool handleMetricWithConditions(
// Validates a metricActivation and populates state.
// Fills the new event activation/deactivation maps, preserving the existing activations.
-// Returns false if there are errors.
-bool handleMetricActivationOnConfigUpdate(
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> handleMetricActivationOnConfigUpdate(
const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const std::unordered_map<int64_t, int>& metricToActivationMap,
const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
@@ -110,7 +114,8 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- std::vector<int>& metricsWithActivation);
+ std::vector<int>& metricsWithActivation,
+ optional<InvalidConfigReason>& invalidConfigReason);
// 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.
@@ -129,7 +134,8 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- std::vector<int>& metricsWithActivation);
+ std::vector<int>& metricsWithActivation,
+ optional<InvalidConfigReason>& invalidConfigReason);
// 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.
@@ -146,7 +152,8 @@ optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- std::vector<int>& metricsWithActivation);
+ std::vector<int>& metricsWithActivation,
+ optional<InvalidConfigReason>& invalidConfigReason);
// 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.
@@ -167,7 +174,8 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- std::vector<int>& metricsWithActivation);
+ std::vector<int>& metricsWithActivation,
+ optional<InvalidConfigReason>& invalidConfigReason);
// 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.
@@ -186,7 +194,8 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- std::vector<int>& metricsWithActivation);
+ std::vector<int>& metricsWithActivation,
+ optional<InvalidConfigReason>& invalidConfigReason);
// 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.
@@ -207,7 +216,7 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation);
+ vector<int>& metricsWithActivation, optional<InvalidConfigReason>& invalidConfigReason);
// Creates an AnomalyTracker and adds it to the appropriate metric.
// Returns an sp to the AnomalyTracker, or nullopt if there was an error.
@@ -215,14 +224,15 @@ optional<sp<AnomalyTracker>> createAnomalyTracker(
const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
const UpdateStatus& updateStatus, const int64_t currentTimeNs,
const std::unordered_map<int64_t, int>& metricProducerMap,
- std::vector<sp<MetricProducer>>& allMetricProducers);
+ std::vector<sp<MetricProducer>>& allMetricProducers,
+ optional<InvalidConfigReason>& invalidConfigReason);
-// Templated function for adding subscriptions to alarms or alerts. Returns true if successful.
+// Templated function for adding subscriptions to alarms or alerts. Returns nullopt if successful
+// and InvalidConfigReason if not.
template <typename T>
-bool initSubscribersForSubscriptionType(const StatsdConfig& config,
- const Subscription_RuleType ruleType,
- const std::unordered_map<int64_t, int>& ruleMap,
- std::vector<T>& allRules) {
+optional<InvalidConfigReason> initSubscribersForSubscriptionType(
+ const StatsdConfig& config, const Subscription_RuleType ruleType,
+ const std::unordered_map<int64_t, int>& ruleMap, std::vector<T>& allRules) {
for (int i = 0; i < config.subscription_size(); ++i) {
const Subscription& subscription = config.subscription(i);
if (subscription.rule_type() != ruleType) {
@@ -231,18 +241,31 @@ bool initSubscribersForSubscriptionType(const StatsdConfig& config,
if (subscription.subscriber_information_case() ==
Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
- return false;
+ return createInvalidConfigReasonWithSubscription(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING, subscription.id());
}
const auto& itr = ruleMap.find(subscription.rule_id());
if (itr == ruleMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
(long long)subscription.id(), (long long)subscription.rule_id());
- return false;
+ switch (subscription.rule_type()) {
+ case Subscription::ALARM:
+ return createInvalidConfigReasonWithSubscriptionAndAlarm(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_RULE_NOT_FOUND, subscription.id(),
+ subscription.rule_id());
+ case Subscription::ALERT:
+ return createInvalidConfigReasonWithSubscriptionAndAlert(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_RULE_NOT_FOUND, subscription.id(),
+ subscription.rule_id());
+ case Subscription::RULE_TYPE_UNSPECIFIED:
+ return createInvalidConfigReasonWithSubscription(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_RULE_NOT_FOUND, subscription.id());
+ }
}
const int ruleIndex = itr->second;
allRules[ruleIndex]->addSubscription(subscription);
}
- return true;
+ return nullopt;
}
// Helper functions for MetricsManager to initialize from StatsdConfig.
@@ -259,10 +282,12 @@ bool initSubscribersForSubscriptionType(const StatsdConfig& config,
// [atomMatchingTrackerMap]: this map should contain matcher name to index mapping
// [allAtomMatchingTrackers]: should store the sp to all the AtomMatchingTracker
// [allTagIdsToMatchersMap]: maps of tag ids to atom matchers
-bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
- std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> initAtomMatchingTrackers(
+ const StatsdConfig& config, const sp<UidMap>& uidMap,
+ std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap);
// Initialize ConditionTrackers
// input:
@@ -275,12 +300,14 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
// [trackerToConditionMap]: contain the mapping from index of
// log tracker to condition trackers that use the log tracker
// [initialConditionCache]: stores the initial conditions for each ConditionTracker
-bool initConditions(const ConfigKey& key, const StatsdConfig& config,
- const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
- std::unordered_map<int64_t, int>& conditionTrackerMap,
- std::vector<sp<ConditionTracker>>& allConditionTrackers,
- std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::vector<ConditionState>& initialConditionCache);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> initConditions(
+ const ConfigKey& key, const StatsdConfig& config,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::unordered_map<int64_t, int>& conditionTrackerMap,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::vector<ConditionState>& initialConditionCache);
// Initialize State maps using State protos in the config. These maps will
// eventually be passed to MetricProducers to initialize their state info.
@@ -291,9 +318,11 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
// [allStateGroupMaps]: this map should contain the mapping from states ids and state
// values to state group ids for all states
// [stateProtoHashes]: contains a map of state id to the hash of the State proto from the config
-bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
- std::map<int64_t, uint64_t>& stateProtoHashes);
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> initStates(
+ const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ std::map<int64_t, uint64_t>& stateProtoHashes);
// Initialize MetricProducers.
// input:
@@ -310,7 +339,8 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
// [conditionToMetricMap]: contains the mapping from condition tracker index to
// the list of MetricProducer index
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
-bool initMetrics(
+// Returns nullopt if successful and InvalidConfigReason if not.
+optional<InvalidConfigReason> initMetrics(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
@@ -330,35 +360,34 @@ bool initMetrics(
// Initialize alarms
// Is called both on initialize new configs and config updates since alarms do not have any state.
-bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
- const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
- const int64_t currentTimeNs, std::vector<sp<AlarmTracker>>& allAlarmTrackers);
+optional<InvalidConfigReason> initAlarms(const StatsdConfig& config, const ConfigKey& key,
+ const sp<AlarmMonitor>& periodicAlarmMonitor,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
+ std::vector<sp<AlarmTracker>>& allAlarmTrackers);
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
-bool 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 int64_t currentTimeNs,
- std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
- std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
- std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
- std::vector<sp<ConditionTracker>>& allConditionTrackers,
- std::unordered_map<int64_t, int>& conditionTrackerMap,
- std::vector<sp<MetricProducer>>& allMetricProducers,
- std::unordered_map<int64_t, int>& metricProducerMap,
- vector<sp<AnomalyTracker>>& allAnomalyTrackers,
- vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
- std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
- std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
- std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
- std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- std::unordered_map<int64_t, int>& alertTrackerMap,
- std::vector<int>& metricsWithActivation,
- std::map<int64_t, uint64_t>& stateProtoHashes,
- std::set<int64_t>& noReportMetricIds);
+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 int64_t currentTimeNs,
+ std::unordered_map<int, std::vector<int>>& allTagIdsToMatchersMap,
+ std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ std::unordered_map<int64_t, int>& conditionTrackerMap,
+ std::vector<sp<MetricProducer>>& allMetricProducers,
+ std::unordered_map<int64_t, int>& metricProducerMap,
+ vector<sp<AnomalyTracker>>& allAnomalyTrackers,
+ vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::unordered_map<int64_t, int>& alertTrackerMap, std::vector<int>& metricsWithActivation,
+ std::map<int64_t, uint64_t>& stateProtoHashes, std::set<int64_t>& noReportMetricIds);
} // namespace statsd
} // namespace os
diff --git a/statsd/src/stats_log.proto b/statsd/src/stats_log.proto
index 89fdb9c7..ef3a60dc 100644
--- a/statsd/src/stats_log.proto
+++ b/statsd/src/stats_log.proto
@@ -22,6 +22,7 @@ option java_package = "com.android.os";
option java_outer_classname = "StatsLog";
import "frameworks/proto_logging/stats/atoms.proto";
+import "packages/modules/StatsD/statsd/src/guardrail/invalid_config_reason_enum.proto";
message DimensionsValue {
optional int32 field = 1;
@@ -141,6 +142,7 @@ message ValueBucketInfo {
int64 value_long = 2;
double value_double = 3;
}
+ optional int32 sample_size = 4;
}
repeated Value values = 9;
@@ -438,6 +440,17 @@ message StatsdStatsReport {
optional int32 stats_end_time_sec = 2;
+ message InvalidConfigReason {
+ optional InvalidConfigReasonEnum reason = 1;
+ optional int64 metric_id = 2;
+ optional int64 state_id = 3;
+ optional int64 alert_id = 4;
+ optional int64 alarm_id = 5;
+ optional int64 subscription_id = 6;
+ repeated int64 matcher_id = 7;
+ repeated int64 condition_id = 8;
+ }
+
message MatcherStats {
optional int64 id = 1;
optional int32 matched_times = 2;
@@ -469,6 +482,7 @@ message StatsdStatsReport {
optional int32 matcher_count = 7;
optional int32 alert_count = 8;
optional bool is_valid = 9;
+ optional InvalidConfigReason invalid_config_reason = 24;
repeated int32 broadcast_sent_time_sec = 10;
repeated int32 data_drop_time_sec = 11;
repeated int64 data_drop_bytes = 21;
diff --git a/statsd/src/statsd_config.proto b/statsd/src/statsd_config.proto
index b75b6702..758a8d11 100644
--- a/statsd/src/statsd_config.proto
+++ b/statsd/src/statsd_config.proto
@@ -214,6 +214,12 @@ message UploadThreshold {
}
}
+message DimensionalSamplingInfo {
+ optional FieldMatcher sampled_what_field = 1;
+
+ optional int32 shard_count = 2;
+}
+
message EventMetric {
optional int64 id = 1;
@@ -250,6 +256,8 @@ message CountMetric {
optional FieldMatcher dimensions_in_condition = 7 [deprecated = true];
+ optional DimensionalSamplingInfo dimensional_sampling_info = 12;
+
reserved 100;
reserved 101;
}
@@ -284,6 +292,8 @@ message DurationMetric {
optional FieldMatcher dimensions_in_condition = 8 [deprecated = true];
+ optional DimensionalSamplingInfo dimensional_sampling_info = 13;
+
reserved 100;
reserved 101;
}
@@ -323,6 +333,8 @@ message GaugeMetric {
optional bool split_bucket_for_app_upgrade = 14;
+ optional DimensionalSamplingInfo dimensional_sampling_info = 15;
+
reserved 100;
reserved 101;
}
@@ -358,6 +370,8 @@ message ValueMetric {
}
optional AggregationType aggregation_type = 8 [default = SUM];
+ optional bool include_sample_size = 22;
+
optional int64 min_bucket_size_nanos = 10;
optional bool use_absolute_value_on_reset = 11 [default = false];
@@ -382,6 +396,8 @@ message ValueMetric {
optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
+ optional DimensionalSamplingInfo dimensional_sampling_info = 23;
+
reserved 100;
reserved 101;
}
@@ -409,6 +425,8 @@ message KllMetric {
repeated MetricStateLink state_link = 11;
+ optional DimensionalSamplingInfo dimensional_sampling_info = 12;
+
reserved 100;
reserved 101;
}
diff --git a/statsd/src/utils/ShardOffsetProvider.cpp b/statsd/src/utils/ShardOffsetProvider.cpp
new file mode 100644
index 00000000..6d847dff
--- /dev/null
+++ b/statsd/src/utils/ShardOffsetProvider.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 "ShardOffsetProvider.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+ShardOffsetProvider::ShardOffsetProvider(const int shardOffset) : mShardOffset(shardOffset) {
+}
+
+ShardOffsetProvider& ShardOffsetProvider::getInstance() {
+ static ShardOffsetProvider sShardOffsetProvider(rand());
+ return sShardOffsetProvider;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/statsd/src/utils/ShardOffsetProvider.h b/statsd/src/utils/ShardOffsetProvider.h
new file mode 100644
index 00000000..0623e0f2
--- /dev/null
+++ b/statsd/src/utils/ShardOffsetProvider.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef SHARD_OFFSET_PROVIDER_H
+#define SHARD_OFFSET_PROVIDER_H
+
+#include <gtest/gtest_prod.h>
+#include <stdlib.h>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/*
+ * Class is not guarded by any mutex. It is currently thread safe.
+ * Thread safety needs to be considered on all future changes to this class.
+ */
+class ShardOffsetProvider final {
+public:
+ ~ShardOffsetProvider(){};
+
+ int getShardOffset() const {
+ return mShardOffset;
+ }
+
+ static ShardOffsetProvider& getInstance();
+
+private:
+ ShardOffsetProvider(const int shardOffset);
+
+ // Only used for testing.
+ void setShardOffset(const int shardOffset) {
+ mShardOffset = shardOffset;
+ }
+
+ int mShardOffset;
+
+ FRIEND_TEST(CountMetricE2eTest, TestDimensionalSampling);
+ FRIEND_TEST(DurationMetricE2eTest, TestDimensionalSampling);
+ FRIEND_TEST(GaugeMetricE2ePushedTest, TestDimensionalSampling);
+ FRIEND_TEST(GaugeMetricProducerTest, TestPullDimensionalSampling);
+ FRIEND_TEST(KllMetricE2eTest, TestDimensionalSampling);
+ FRIEND_TEST(NumericValueMetricProducerTest, TestDimensionalSampling);
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+#endif // METRIC_PRODUCER_H \ No newline at end of file
diff --git a/statsd/tests/ConfigManager_test.cpp b/statsd/tests/ConfigManager_test.cpp
index 7b8f74d0..bfc89685 100644
--- a/statsd/tests/ConfigManager_test.cpp
+++ b/statsd/tests/ConfigManager_test.cpp
@@ -147,6 +147,8 @@ TEST(ConfigManagerTest, TestRemoveUid) {
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, StringToId("xxx"))));
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, StringToId("yyy"))));
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, StringToId("zzz"))));
+ EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(1, StringToId("aaa"))));
+ EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(3, StringToId("bbb"))));
manager->StartupForTest();
manager->UpdateConfig(ConfigKey(1, StringToId("aaa")), config);
@@ -156,4 +158,6 @@ TEST(ConfigManagerTest, TestRemoveUid) {
manager->UpdateConfig(ConfigKey(3, StringToId("bbb")), config);
manager->RemoveConfigs(2);
+ manager->RemoveConfigs(1);
+ manager->RemoveConfigs(3);
}
diff --git a/statsd/tests/FieldValue_test.cpp b/statsd/tests/FieldValue_test.cpp
index ff3e54af..64be5593 100644
--- a/statsd/tests/FieldValue_test.cpp
+++ b/statsd/tests/FieldValue_test.cpp
@@ -132,7 +132,8 @@ TEST(AtomMatcherTest, TestFilter_ALL) {
std::vector<string> attributionTags = {"location1", "location2", "location3"};
LogEvent event(/*uid=*/0, /*pid=*/0);
- makeLogEvent(&event, 10 /*atomId*/, 1012345, attributionUids, attributionTags, "some value");
+ makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
+ "some value");
HashableDimensionKey output;
filterValues(matchers, event.getValues(), &output);
@@ -227,6 +228,142 @@ TEST(AtomMatcherTest, TestFilterRepeated_ALL) {
EXPECT_EQ((int32_t)13, output.getValues()[2].mValue.int_value);
}
+TEST(AtomMatcherTest, TestFilterWithOneMatcher) {
+ FieldMatcher matcher;
+ matcher.set_field(10);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(2);
+
+ vector<Matcher> matchers;
+ translateFieldMatcher(matcher, &matchers);
+
+ std::vector<int> attributionUids = {1111, 2222, 3333};
+ std::vector<string> attributionTags = {"location1", "location2", "location3"};
+
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
+ "some value");
+ FieldValue value;
+
+ EXPECT_TRUE(filterValues(matchers[0], event.getValues(), &value));
+ EXPECT_EQ((int32_t)0x20000, value.mField.getField());
+ EXPECT_EQ("some value", value.mValue.str_value);
+}
+
+TEST(AtomMatcherTest, TestFilterWithOneMatcher_PositionFIRST) {
+ FieldMatcher matcher;
+ matcher.set_field(10);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(1);
+ child->set_position(Position::FIRST);
+ child->add_child()->set_field(1);
+
+ vector<Matcher> matchers;
+ translateFieldMatcher(matcher, &matchers);
+
+ std::vector<int> attributionUids = {1111, 2222, 3333};
+ std::vector<string> attributionTags = {"location1", "location2", "location3"};
+
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
+ "some value");
+ FieldValue value;
+
+ // Should only match the first field.
+ EXPECT_TRUE(filterValues(matchers[0], event.getValues(), &value));
+ EXPECT_EQ((int32_t)0x02010101, value.mField.getField());
+ EXPECT_EQ((int32_t)1111, value.mValue.int_value);
+}
+
+TEST(AtomMatcherTest, TestFilterWithOneMatcher_PositionLAST) {
+ FieldMatcher matcher;
+ matcher.set_field(10);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(1);
+ child->set_position(Position::LAST);
+ child->add_child()->set_field(1);
+
+ vector<Matcher> matchers;
+ translateFieldMatcher(matcher, &matchers);
+
+ std::vector<int> attributionUids = {1111, 2222, 3333};
+ std::vector<string> attributionTags = {"location1", "location2", "location3"};
+
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
+ "some value");
+ FieldValue value;
+
+ // Should only match the last field.
+ EXPECT_TRUE(filterValues(matchers[0], event.getValues(), &value));
+ EXPECT_EQ((int32_t)0x02018301, value.mField.getField());
+ EXPECT_EQ((int32_t)3333, value.mValue.int_value);
+}
+
+TEST(AtomMatcherTest, TestFilterWithOneMatcher_PositionALL) {
+ FieldMatcher matcher;
+ matcher.set_field(10);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(1);
+ child->set_position(Position::ALL);
+ child->add_child()->set_field(1);
+
+ vector<Matcher> matchers;
+ translateFieldMatcher(matcher, &matchers);
+
+ std::vector<int> attributionUids = {1111, 2222, 3333};
+ std::vector<string> attributionTags = {"location1", "location2", "location3"};
+
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event, 10 /*atomId*/, 1012345, attributionUids, attributionTags, "some value");
+ FieldValue value;
+
+ // Can't filter with position ALL matcher.
+ EXPECT_FALSE(filterValues(matchers[0], event.getValues(), &value));
+}
+
+TEST(AtomMatcherTest, TestFilterWithOneMatcher_DifferentField) {
+ FieldMatcher matcher;
+ matcher.set_field(10);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(3);
+
+ vector<Matcher> matchers;
+ translateFieldMatcher(matcher, &matchers);
+
+ std::vector<int> attributionUids = {1111, 2222, 3333};
+ std::vector<string> attributionTags = {"location1", "location2", "location3"};
+
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
+ "some value");
+ FieldValue value;
+
+ // Shouldn't match any fields because matcher is looking for field 3.
+ EXPECT_FALSE(filterValues(matchers[0], event.getValues(), &value));
+}
+
+TEST(AtomMatcherTest, TestFilterWithOneMatcher_EmptyAttributionUids) {
+ FieldMatcher matcher;
+ matcher.set_field(10);
+ FieldMatcher* child = matcher.add_child();
+ child->set_field(1);
+ child->set_position(Position::ALL);
+ child->add_child()->set_field(1);
+
+ vector<Matcher> matchers;
+ translateFieldMatcher(matcher, &matchers);
+
+ std::vector<string> attributionTags = {"location1", "location2", "location3"};
+
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, {}, attributionTags, "some value");
+ FieldValue value;
+
+ // Shouldn't match any fields because field 1 is empty.
+ EXPECT_FALSE(filterValues(matchers[0], event.getValues(), &value));
+}
+
TEST(AtomMatcherTest, TestSubDimension) {
HashableDimensionKey dim;
@@ -792,6 +929,111 @@ TEST(AtomMatcherTest, TestIsPrimitiveRepeatedField) {
EXPECT_FALSE(isPrimitiveRepeatedField(field7));
}
+TEST(FieldValueTest, TestShouldKeepSampleInt) {
+ int shardOffset = 5;
+ int shardCount = 2;
+ int pos1[] = {1, 1, 1};
+
+ Field field(1, pos1, 2);
+
+ Value value1((int32_t)1001);
+ Value value2((int32_t)1002);
+
+ FieldValue fieldValue1(field, value1);
+ FieldValue fieldValue2(field, value2);
+
+ EXPECT_TRUE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
+ EXPECT_FALSE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
+}
+
+TEST(FieldValueTest, TestShouldKeepSampleLong) {
+ int shardOffset = 5;
+ int shardCount = 2;
+ int pos1[] = {1, 1, 1};
+
+ Field field(1, pos1, 2);
+
+ Value value1((int64_t)1001L);
+ Value value2((int64_t)1005L);
+
+ FieldValue fieldValue1(field, value1);
+ FieldValue fieldValue2(field, value2);
+
+ EXPECT_FALSE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
+ EXPECT_TRUE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
+}
+
+TEST(FieldValueTest, TestShouldKeepSampleFloat) {
+ int shardOffset = 5;
+ int shardCount = 2;
+ int pos1[] = {1, 1, 1};
+
+ Field field(1, pos1, 2);
+
+ Value value1((float)10.5);
+ Value value2((float)3.9);
+
+ FieldValue fieldValue1(field, value1);
+ FieldValue fieldValue2(field, value2);
+
+ EXPECT_TRUE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
+ EXPECT_FALSE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
+}
+
+TEST(FieldValueTest, TestShouldKeepSampleDouble) {
+ int shardOffset = 5;
+ int shardCount = 2;
+ int pos1[] = {1, 1, 1};
+
+ Field field(1, pos1, 2);
+
+ Value value1((double)1.5);
+ Value value2((double)3.9);
+
+ FieldValue fieldValue1(field, value1);
+ FieldValue fieldValue2(field, value2);
+
+ EXPECT_TRUE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
+ EXPECT_FALSE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
+}
+
+TEST(FieldValueTest, TestShouldKeepSampleString) {
+ int shardOffset = 5;
+ int shardCount = 2;
+ int pos1[] = {1, 1, 1};
+
+ Field field(1, pos1, 2);
+
+ Value value1("str1");
+ Value value2("str2");
+
+ FieldValue fieldValue1(field, value1);
+ FieldValue fieldValue2(field, value2);
+
+ EXPECT_FALSE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
+ EXPECT_TRUE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
+}
+
+TEST(FieldValueTest, TestShouldKeepSampleByteArray) {
+ int shardOffset = 5;
+ int shardCount = 2;
+ int pos1[] = {1, 1, 1};
+
+ Field field(1, pos1, 2);
+
+ vector<uint8_t> message1 = {'\t', 'e', '\0', 's', 't'};
+ vector<uint8_t> message2 = {'\t', 'e', '\0', 's', 't', 't'};
+
+ Value value1(message1);
+ Value value2(message2);
+
+ FieldValue fieldValue1(field, value1);
+ FieldValue fieldValue2(field, value2);
+
+ EXPECT_FALSE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
+ EXPECT_TRUE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/tests/HashableDimensionKey_test.cpp b/statsd/tests/HashableDimensionKey_test.cpp
index 8fe555e7..b6ddf409 100644
--- a/statsd/tests/HashableDimensionKey_test.cpp
+++ b/statsd/tests/HashableDimensionKey_test.cpp
@@ -129,6 +129,41 @@ TEST(HashableDimensionKeyTest, TestContainsLinkedStateValues_AllConditionsMet) {
EXPECT_TRUE(containsLinkedStateValues(whatKey, primaryKey, mMetric2StateLinks, stateAtomId));
}
+/**
+ * Test that FieldValues with STORAGE values are hashed differently.
+ */
+TEST(HashableDimensionKeyTest, TestHashDimensionStorage) {
+ int pos[] = {1, 1, 1};
+ Field field(1, pos, 1);
+ vector<uint8_t> bytesField1{10, 20, 30};
+ vector<uint8_t> bytesField2{10, 20, 30, 40};
+ FieldValue fieldValue1(field, Value(bytesField1));
+ FieldValue fieldValue2(field, Value(bytesField2));
+ HashableDimensionKey dimKey1;
+ dimKey1.addValue(fieldValue1);
+ HashableDimensionKey dimKey2;
+ dimKey2.addValue(fieldValue2);
+
+ EXPECT_NE(std::hash<HashableDimensionKey>{}(dimKey1),
+ std::hash<HashableDimensionKey>{}(dimKey2));
+}
+/**
+ * Test that FieldValues with DOUBLE values are hashed differently.
+ */
+TEST(HashableDimensionKeyTest, TestHashDimensionDouble) {
+ int pos[] = {1, 1, 1};
+ Field field(1, pos, 1);
+ FieldValue fieldValue1(field, Value((double)100.00));
+ FieldValue fieldValue2(field, Value((double)200.00));
+ HashableDimensionKey dimKey1;
+ dimKey1.addValue(fieldValue1);
+ HashableDimensionKey dimKey2;
+ dimKey2.addValue(fieldValue2);
+
+ EXPECT_NE(std::hash<HashableDimensionKey>{}(dimKey1),
+ std::hash<HashableDimensionKey>{}(dimKey2));
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/tests/StatsLogProcessor_test.cpp b/statsd/tests/StatsLogProcessor_test.cpp
index 4bca4528..32f091f7 100644
--- a/statsd/tests/StatsLogProcessor_test.cpp
+++ b/statsd/tests/StatsLogProcessor_test.cpp
@@ -1748,6 +1748,11 @@ TEST_P(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey1, configAddedTimeNs + NS_PER_SEC, false, true, ADB_DUMP, FAST,
&buffer);
+
+ service->removeConfiguration(configId, uid);
+ service->mProcessor->onDumpReport(cfgKey1, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, true /* erase_data */,
+ ADB_DUMP, NO_TIME_CONSTRAINTS, nullptr);
}
TEST(StatsLogProcessorTest_mapIsolatedUidToHostUid, LogHostUid) {
diff --git a/statsd/tests/StatsService_test.cpp b/statsd/tests/StatsService_test.cpp
index 24cc2f26..bd760814 100644
--- a/statsd/tests/StatsService_test.cpp
+++ b/statsd/tests/StatsService_test.cpp
@@ -22,6 +22,7 @@
#include "config/ConfigKey.h"
#include "packages/UidMap.h"
#include "src/statsd_config.pb.h"
+#include "tests/statsd_test_util.h"
using namespace android;
using namespace testing;
@@ -39,12 +40,19 @@ TEST(StatsServiceTest, TestAddConfig_simple) {
const sp<UidMap> uidMap = new UidMap();
shared_ptr<StatsService> service =
SharedRefBase::make<StatsService>(uidMap, /* queue */ nullptr);
+ const int kConfigKey = 12345;
+ const int kCallingUid = 123;
StatsdConfig config;
- config.set_id(12345);
+ config.set_id(kConfigKey);
string serialized = config.SerializeAsString();
- EXPECT_TRUE(
- service->addConfigurationChecked(123, 12345, {serialized.begin(), serialized.end()}));
+ EXPECT_TRUE(service->addConfigurationChecked(kCallingUid, kConfigKey,
+ {serialized.begin(), serialized.end()}));
+ service->removeConfiguration(kConfigKey, kCallingUid);
+ ConfigKey configKey(kCallingUid, kConfigKey);
+ service->mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, true /* erase_data */,
+ ADB_DUMP, NO_TIME_CONSTRAINTS, nullptr);
}
TEST(StatsServiceTest, TestAddConfig_empty) {
@@ -52,9 +60,15 @@ TEST(StatsServiceTest, TestAddConfig_empty) {
shared_ptr<StatsService> service =
SharedRefBase::make<StatsService>(uidMap, /* queue */ nullptr);
string serialized = "";
-
- EXPECT_TRUE(
- service->addConfigurationChecked(123, 12345, {serialized.begin(), serialized.end()}));
+ const int kConfigKey = 12345;
+ const int kCallingUid = 123;
+ EXPECT_TRUE(service->addConfigurationChecked(kCallingUid, kConfigKey,
+ {serialized.begin(), serialized.end()}));
+ service->removeConfiguration(kConfigKey, kCallingUid);
+ ConfigKey configKey(kCallingUid, kConfigKey);
+ service->mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, true /* erase_data */,
+ ADB_DUMP, NO_TIME_CONSTRAINTS, nullptr);
}
TEST(StatsServiceTest, TestAddConfig_invalid) {
diff --git a/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
index ec74df63..eccaafea 100644
--- a/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
+++ b/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
@@ -54,7 +54,7 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold, int refractory_p
} // namespace
-TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
+TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
const int num_buckets = 1;
const int threshold = 3;
const int refractory_period_sec = 10;
@@ -171,7 +171,7 @@ TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
}
-TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
+TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
const int num_buckets = 3;
const int threshold = 3;
const int refractory_period_sec = 10;
@@ -241,7 +241,7 @@ TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
-TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written) {
+TEST(AnomalyCountDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written) {
const int num_buckets = 1;
const int threshold = 0;
const int refractory_period_sec = 86400 * 365; // 1 year
@@ -266,7 +266,7 @@ TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_wr
ASSERT_EQ(result.stats_metadata_size(), 0);
}
-TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk) {
+TEST(AnomalyCountDetectionE2eTest, TestCountMetric_save_refractory_to_disk) {
const int num_buckets = 1;
const int threshold = 0;
const int refractory_period_sec = 86400 * 365; // 1 year
@@ -329,7 +329,7 @@ TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk) {
EXPECT_EQ(dimKeyInWhat.value_int(), fieldValue1.mValue.int_value);
}
-TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk) {
+TEST(AnomalyCountDetectionE2eTest, TestCountMetric_load_refractory_from_disk) {
const int num_buckets = 1;
const int threshold = 0;
const int refractory_period_sec = 86400 * 365; // 1 year
diff --git a/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 30e8fd75..04b473cc 100644
--- a/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -35,9 +35,6 @@ namespace statsd {
namespace {
-const int kConfigKey = 789130124;
-const int kCallingUid = 0;
-
StatsdConfig CreateStatsdConfig(int num_buckets,
uint64_t threshold_ns,
DurationMetric::AggregationType aggregationType,
@@ -98,25 +95,19 @@ MetricDimensionKey dimensionKey2(
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
-void sendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
- string str;
- config.SerializeToString(&str);
- std::vector<uint8_t> configAsVec(str.begin(), str.end());
- service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
-}
-
} // namespace
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
+// Setup for test fixture.
+class AnomalyDurationDetectionE2eTest : public StatsServiceConfigTest {};
+
+TEST_F(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const int num_buckets = 1;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- sendConfig(service, config);
+ sendConfig(config);
auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
@@ -291,16 +282,14 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
+TEST_F(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
const int num_buckets = 3;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- sendConfig(service, config);
+ sendConfig(config);
auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
@@ -415,16 +404,14 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket) {
+TEST_F(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_partial_bucket) {
const int num_buckets = 1;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- sendConfig(service, config);
+ sendConfig(config);
auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
@@ -505,7 +492,7 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
+TEST_F(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const int num_buckets = 2;
const uint64_t threshold_ns = 3 * NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
@@ -514,9 +501,7 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- sendConfig(service, config);
+ sendConfig(config);
auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
diff --git a/statsd/tests/e2e/ConfigUpdate_e2e_test.cpp b/statsd/tests/e2e/ConfigUpdate_e2e_test.cpp
index 004ddeef..ad706632 100644
--- a/statsd/tests/e2e/ConfigUpdate_e2e_test.cpp
+++ b/statsd/tests/e2e/ConfigUpdate_e2e_test.cpp
@@ -1455,6 +1455,7 @@ TEST_F(ConfigUpdateE2eTest, TestValueMetric) {
EXPECT_FALSE(data.has_dimensions_in_what());
EXPECT_EQ(data.slice_by_state_size(), 0);
ASSERT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(3, data.bucket_info(0).values(0).sample_size());
ValidateValueBucket(data.bucket_info(0), roundedBucketStartNs, roundedUpdateTimeNs, {20}, 0, 0);
// Min screen brightness while screen on. Bucket skipped due to condition unknown.
diff --git a/statsd/tests/e2e/CountMetric_e2e_test.cpp b/statsd/tests/e2e/CountMetric_e2e_test.cpp
index ef183b7a..6212c43d 100644
--- a/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -469,6 +469,8 @@ TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
countMetric->set_what(appCrashMatcher.id());
countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
countMetric->add_slice_by_state(state.id());
+ *countMetric->mutable_dimensions_in_what() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
MetricStateLink* stateLink = countMetric->add_state_link();
stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
auto fieldsInWhat = stateLink->mutable_fields_in_what();
@@ -592,7 +594,7 @@ TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
StatsLogReport::CountMetricDataWrapper countMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- ASSERT_EQ(5, countMetrics.data_size());
+ ASSERT_EQ(6, countMetrics.data_size());
// For each CountMetricData, check StateValue info is correct and buckets
// have correct counts.
@@ -601,6 +603,7 @@ TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_value());
EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
@@ -609,14 +612,16 @@ TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_value());
EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
+ EXPECT_EQ(1, data.bucket_info(0).count());
data = countMetrics.data(2);
ASSERT_EQ(1, data.slice_by_state_size());
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_value());
EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(2, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
EXPECT_EQ(2, data.bucket_info(1).count());
@@ -626,6 +631,7 @@ TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_value());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(2, data.bucket_info(0).count());
@@ -633,7 +639,17 @@ TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
ASSERT_EQ(1, data.slice_by_state_size());
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
+ ASSERT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(1, data.bucket_info(0).count());
+
+ data = countMetrics.data(5);
+ ASSERT_EQ(1, data.slice_by_state_size());
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
}
@@ -663,6 +679,8 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
countMetric->add_slice_by_state(state1.id());
countMetric->add_slice_by_state(state2.id());
+ *countMetric->mutable_dimensions_in_what() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
MetricStateLink* stateLink = countMetric->add_state_link();
stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
auto fieldsInWhat = stateLink->mutable_fields_in_what();
@@ -821,7 +839,7 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
StatsLogReport::CountMetricDataWrapper countMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
- ASSERT_EQ(6, countMetrics.data_size());
+ ASSERT_EQ(7, countMetrics.data_size());
// For each CountMetricData, check StateValue info is correct and buckets
// have correct counts.
@@ -833,6 +851,7 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
EXPECT_TRUE(data.slice_by_state(1).has_value());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
@@ -844,6 +863,7 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
EXPECT_TRUE(data.slice_by_state(1).has_value());
EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
@@ -851,10 +871,11 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
ASSERT_EQ(2, data.slice_by_state_size());
EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_group_id());
- EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
+ EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
+ EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
@@ -865,9 +886,10 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
+ EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
ASSERT_EQ(1, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
+ EXPECT_EQ(1, data.bucket_info(0).count());
data = countMetrics.data(4);
ASSERT_EQ(2, data.slice_by_state_size());
@@ -876,21 +898,35 @@ TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
+ EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 1);
+ ASSERT_EQ(2, data.bucket_info_size());
+ EXPECT_EQ(2, data.bucket_info(0).count());
+ EXPECT_EQ(1, data.bucket_info(1).count());
+
+ data = countMetrics.data(5);
+ ASSERT_EQ(2, data.slice_by_state_size());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+ EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+ EXPECT_TRUE(data.slice_by_state(1).has_value());
+ EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
ASSERT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
- data = countMetrics.data(5);
+ data = countMetrics.data(6);
ASSERT_EQ(2, data.slice_by_state_size());
EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
EXPECT_TRUE(data.slice_by_state(0).has_group_id());
EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
EXPECT_TRUE(data.slice_by_state(1).has_value());
- EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
- ASSERT_EQ(2, data.bucket_info_size());
- EXPECT_EQ(2, data.bucket_info(0).count());
- EXPECT_EQ(1, data.bucket_info(1).count());
+ EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, 2);
+ ASSERT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(1, data.bucket_info(0).count());
}
TEST(CountMetricE2eTest, TestUploadThreshold) {
@@ -1747,9 +1783,92 @@ TEST(CountMetricE2eTest, TestConditionSlicedByRepeatedUidWithUidDimension) {
1);
}
+TEST(CountMetricE2eTest, TestDimensionalSampling) {
+ ShardOffsetProvider::getInstance().setShardOffset(5);
+
+ // Initialize config.
+ 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;
+
+ CountMetric sampledCountMetric =
+ createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *sampledCountMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *sampledCountMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ sampledCountMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = sampledCountMetric;
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ const uint64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
+ bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap());
+
+ int appUid1 = 1001; // odd hash value
+ int appUid2 = 1002; // even hash value
+ int appUid3 = 1003; // odd hash value
+ std::vector<std::unique_ptr<LogEvent>> events;
+ events.push_back(
+ CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, appUid1)); // 0:30
+ events.push_back(
+ CreateAppCrashOccurredEvent(bucketStartTimeNs + 40 * NS_PER_SEC, appUid2)); // 0:50
+ events.push_back(
+ CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, appUid3)); // 1:10
+ events.push_back(
+ CreateAppCrashOccurredEvent(bucketStartTimeNs + 80 * NS_PER_SEC, appUid1)); // 1:20
+ events.push_back(
+ CreateAppCrashOccurredEvent(bucketStartTimeNs + 90 * NS_PER_SEC, appUid2)); // 1:30
+ events.push_back(
+ CreateAppCrashOccurredEvent(bucketStartTimeNs + 100 * NS_PER_SEC, appUid3)); // 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(2, countMetrics.data_size());
+
+ // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
+ CountMetricData data = countMetrics.data(0);
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, appUid1);
+ ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
+ 2);
+
+ data = countMetrics.data(1);
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, appUid3);
+ ValidateCountBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs,
+ 2);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
+#endif \ No newline at end of file
diff --git a/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index 32023688..4a3ab11d 100644
--- a/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -1649,6 +1649,106 @@ TEST(DurationMetricE2eTest, TestConditionOnRepeatedEnumField) {
EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
}
+TEST(DurationMetricE2eTest, TestDimensionalSampling) {
+ ShardOffsetProvider::getInstance().setShardOffset(5);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ *config.add_atom_matcher() = CreateStartScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = CreateFinishScheduledJobAtomMatcher();
+ AtomMatcher stopAllMatcher = CreateScheduleScheduledJobAtomMatcher();
+ *config.add_atom_matcher() = stopAllMatcher;
+
+ Predicate scheduledJobPredicate = CreateScheduledJobPredicate();
+ *scheduledJobPredicate.mutable_simple_predicate()->mutable_dimensions() =
+ CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ SimplePredicate* simplePredicate = scheduledJobPredicate.mutable_simple_predicate();
+ simplePredicate->set_stop_all(stopAllMatcher.id());
+ *config.add_predicate() = scheduledJobPredicate;
+
+ DurationMetric sampledDurationMetric = createDurationMetric(
+ "DurationSampledScheduledJobPerUid", scheduledJobPredicate.id(), nullopt, {});
+ sampledDurationMetric.set_aggregation_type(DurationMetric::SUM);
+ *sampledDurationMetric.mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ *sampledDurationMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateAttributionUidDimensions(util::SCHEDULED_JOB_STATE_CHANGED, {Position::FIRST});
+ sampledDurationMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_duration_metric() = sampledDurationMetric;
+
+ const int64_t configAddedTimeNs = 1 * NS_PER_SEC; // 0:01
+ const int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.duration_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());
+
+ int uid1 = 1001; // odd hash value
+ int uid2 = 1002; // even hash value
+ int uid3 = 1003; // odd hash value
+
+ const int64_t durationStartNs1 = 20 * NS_PER_SEC;
+ const int64_t durationStartNs2 = 40 * NS_PER_SEC;
+ const int64_t durationStartNs3 = 60 * NS_PER_SEC;
+ const int64_t durationStartNs4 = 80 * NS_PER_SEC;
+ const int64_t durationEndNs1 = 100 * NS_PER_SEC;
+ const int64_t durationEndNs2 = 110 * NS_PER_SEC;
+ const int64_t stopAllNs = 130 * NS_PER_SEC;
+ const int64_t durationEndNs3 = 150 * NS_PER_SEC;
+ const int64_t durationEndNs4 = 200 * NS_PER_SEC;
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+ events.push_back(CreateStartScheduledJobEvent(durationStartNs1, {uid1}, {"App1"}, "job1"));
+ events.push_back(CreateStartScheduledJobEvent(durationStartNs2, {uid2}, {"App2"}, "job2"));
+ events.push_back(CreateStartScheduledJobEvent(durationStartNs3, {uid3}, {"App3"}, "job3"));
+ events.push_back(CreateFinishScheduledJobEvent(durationEndNs1, {uid1}, {"App1"}, "job1"));
+ events.push_back(CreateFinishScheduledJobEvent(durationEndNs2, {uid2}, {"App2"}, "job2"));
+ // This event should pass the sample check regardless of the uid.
+ events.push_back(CreateScheduleScheduledJobEvent(stopAllNs, {uid2}, {"App2"}, "job2"));
+ // These events shouldn't do anything since all jobs were stopped with the cancel event.
+ events.push_back(CreateFinishScheduledJobEvent(durationEndNs3, {uid3}, {"App3"}, "job3"));
+
+ // 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);
+ backfillStartEndTimestamp(&reports);
+
+ ASSERT_EQ(1, reports.reports_size());
+ ASSERT_EQ(1, reports.reports(0).metrics_size());
+ EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+ StatsLogReport::DurationMetricDataWrapper durationMetrics;
+ sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
+ &durationMetrics);
+ ASSERT_EQ(2, durationMetrics.data_size());
+
+ // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
+ DurationMetricData data = durationMetrics.data(0);
+ ValidateAttributionUidDimension(data.dimensions_in_what(), util::SCHEDULED_JOB_STATE_CHANGED,
+ uid1);
+ ValidateDurationBucket(data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
+ durationEndNs1 - durationStartNs1);
+
+ data = durationMetrics.data(1);
+ ValidateAttributionUidDimension(data.dimensions_in_what(), util::SCHEDULED_JOB_STATE_CHANGED,
+ uid3);
+ ValidateDurationBucket(data.bucket_info(0), configAddedTimeNs, configAddedTimeNs + bucketSizeNs,
+ stopAllNs - durationStartNs3);
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 984b72e6..fc1db28e 100644
--- a/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -69,9 +69,11 @@ StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,
} // namespaces
// Setup for test fixture.
-class GaugeMetricE2ePulledTest : public ::testing::Test {
+class GaugeMetricE2ePulledTest : public ::testing::TestWithParam<string> {
void SetUp() override {
FlagProvider::getInstance().overrideFuncs(&isAtLeastSFuncTrue);
+ FlagProvider::getInstance().overrideFlag(LIMIT_PULL_FLAG, GetParam(),
+ /*isBootFlag=*/true);
}
void TearDown() override {
@@ -79,7 +81,10 @@ class GaugeMetricE2ePulledTest : public ::testing::Test {
}
};
-TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents) {
+INSTANTIATE_TEST_SUITE_P(LimitPull, GaugeMetricE2ePulledTest,
+ testing::Values(FLAG_FALSE, FLAG_TRUE));
+
+TEST_P(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
@@ -219,7 +224,7 @@ TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents) {
EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
}
-TEST_F(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents) {
+TEST_P(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents) {
auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
@@ -317,7 +322,7 @@ TEST_F(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents) {
EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
}
-TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm) {
+TEST_P(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
@@ -415,7 +420,7 @@ TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm) {
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
}
-TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation) {
+TEST_P(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
int64_t baseTimeNs = getElapsedRealtimeNs();
@@ -460,14 +465,15 @@ TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation) {
// Check no pull occurred on metric initialization when it's not active.
const int64_t metricInitTimeNs = configAddedTimeNs + 1; // 10 mins + 1 ns.
processor->onStatsdInitCompleted(metricInitTimeNs);
- StatsdStatsReport_PulledAtomStats pulledAtomStats = getPulledAtomStats();
+ StatsdStatsReport_PulledAtomStats pulledAtomStats =
+ getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.atom_id(), ATOM_TAG);
EXPECT_EQ(pulledAtomStats.total_pull(), 0);
// Check no pull occurred on app upgrade when metric is not active.
const int64_t appUpgradeTimeNs = metricInitTimeNs + 1; // 10 mins + 2 ns.
processor->notifyAppUpgrade(appUpgradeTimeNs, "appName", 1000 /* uid */, 2 /* version */);
- pulledAtomStats = getPulledAtomStats();
+ pulledAtomStats = getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.atom_id(), ATOM_TAG);
EXPECT_EQ(pulledAtomStats.total_pull(), 0);
@@ -593,7 +599,7 @@ TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation) {
EXPECT_EQ(gaugeMetrics.skipped_size(), 0);
}
-TEST_F(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition) {
+TEST_P(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
int64_t baseTimeNs = getElapsedRealtimeNs();
diff --git a/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index f5a01582..81192b2f 100644
--- a/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -414,6 +414,93 @@ TEST_F(GaugeMetricE2ePushedTest, TestRepeatedFieldsForPushedEvent) {
}
}
+TEST_F(GaugeMetricE2ePushedTest, TestDimensionalSampling) {
+ ShardOffsetProvider::getInstance().setShardOffset(5);
+
+ 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);
+ *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());
+
+ int appUid1 = 1001; // odd hash value
+ int appUid2 = 1002; // even hash value
+ int appUid3 = 1003; // odd hash value
+
+ const int64_t gaugeEventTimeNs1 = configAddedTimeNs + 20 * NS_PER_SEC;
+ const int64_t gaugeEventTimeNs2 = configAddedTimeNs + 40 * NS_PER_SEC;
+ const int64_t gaugeEventTimeNs3 = configAddedTimeNs + 60 * NS_PER_SEC;
+ const int64_t gaugeEventTimeNs4 = configAddedTimeNs + 100 * NS_PER_SEC;
+ const int64_t gaugeEventTimeNs5 = configAddedTimeNs + 110 * NS_PER_SEC;
+ const int64_t gaugeEventTimeNs6 = configAddedTimeNs + 150 * NS_PER_SEC;
+
+ std::vector<std::unique_ptr<LogEvent>> events;
+ events.push_back(CreateAppCrashOccurredEvent(gaugeEventTimeNs1, appUid1)); // 0:30
+ events.push_back(CreateAppCrashOccurredEvent(gaugeEventTimeNs2, appUid2)); // 0:50
+ events.push_back(CreateAppCrashOccurredEvent(gaugeEventTimeNs3, appUid3)); // 1:10
+ events.push_back(CreateAppCrashOccurredEvent(gaugeEventTimeNs4, appUid1)); // 1:50
+ events.push_back(CreateAppCrashOccurredEvent(gaugeEventTimeNs5, appUid2)); // 2:00
+ events.push_back(CreateAppCrashOccurredEvent(gaugeEventTimeNs6, appUid3)); // 2:40
+
+ // 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, appUid1);
+ ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs,
+ configAddedTimeNs + bucketSizeNs,
+ {gaugeEventTimeNs1, gaugeEventTimeNs4});
+
+ data = gaugeMetrics.data(1);
+ ValidateUidDimension(data.dimensions_in_what(), util::APP_CRASH_OCCURRED, appUid3);
+ ValidateGaugeBucketTimes(data.bucket_info(0), configAddedTimeNs,
+ configAddedTimeNs + bucketSizeNs,
+ {gaugeEventTimeNs3, gaugeEventTimeNs6});
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/statsd/tests/e2e/KllMetric_e2e_test.cpp b/statsd/tests/e2e/KllMetric_e2e_test.cpp
index 6f2530f4..a6100c29 100644
--- a/statsd/tests/e2e/KllMetric_e2e_test.cpp
+++ b/statsd/tests/e2e/KllMetric_e2e_test.cpp
@@ -25,6 +25,21 @@ namespace statsd {
using namespace std;
+namespace {
+
+unique_ptr<LogEvent> CreateTestAtomReportedEvent(const uint64_t timestampNs, const long longField,
+ const string& stringField) {
+ return CreateTestAtomReportedEvent(
+ timestampNs, /* attributionUids */ {1001},
+ /* attributionTags */ {"app1"}, /* intField */ 0, longField, /* floatField */ 0.0f,
+ stringField, /* boolField */ false, TestAtomReported::OFF, /* bytesField */ {},
+ /* repeatedIntField */ {}, /* repeatedLongField */ {}, /* repeatedFloatField */ {},
+ /* repeatedStringField */ {}, /* repeatedBoolField */ {},
+ /* repeatedBoolFieldLength */ 0, /* repeatedEnumField */ {});
+}
+
+} // anonymous namespace.
+
class KllMetricE2eTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -90,6 +105,75 @@ TEST_F(KllMetricE2eTest, TestSimpleMetric) {
EXPECT_EQ(metricReport.kll_metrics().skipped_size(), 0);
}
+TEST_F(KllMetricE2eTest, TestMetricWithDimensions) {
+ whatMatcher = CreateSimpleAtomMatcher("TestAtomReported", util::TEST_ATOM_REPORTED);
+ metric = createKllMetric("TestAtomMetric", whatMatcher, /* kllField */ 3,
+ /* condition */ nullopt);
+
+ *metric.mutable_dimensions_in_what() =
+ CreateDimensions(util::TEST_ATOM_REPORTED, {5 /* string_field */});
+
+ config.clear_atom_matcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ config.clear_kll_metric();
+ *config.add_kll_metric() = metric;
+
+ events.clear();
+ events.push_back(CreateTestAtomReportedEvent(bucketStartTimeNs + 5 * NS_PER_SEC, 5l, "dim_1"));
+ events.push_back(CreateTestAtomReportedEvent(bucketStartTimeNs + 15 * NS_PER_SEC, 6l, "dim_2"));
+ events.push_back(CreateTestAtomReportedEvent(bucketStartTimeNs + 25 * NS_PER_SEC, 7l, "dim_1"));
+
+ const sp<StatsLogProcessor> processor =
+ CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, key);
+
+ for (auto& event : events) {
+ processor->OnLogEvent(event.get());
+ }
+
+ uint64_t dumpTimeNs = bucketStartTimeNs + bucketSizeNs;
+ ConfigMetricsReportList reports;
+ vector<uint8_t> buffer;
+ processor->onDumpReport(key, dumpTimeNs, /*include_current_bucket*/ false, true, ADB_DUMP, FAST,
+ &buffer);
+ EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+ backfillDimensionPath(&reports);
+ backfillStringInReport(&reports);
+ backfillStartEndTimestamp(&reports);
+ ASSERT_EQ(reports.reports_size(), 1);
+
+ ConfigMetricsReport report = reports.reports(0);
+ ASSERT_EQ(report.metrics_size(), 1);
+ StatsLogReport metricReport = report.metrics(0);
+ EXPECT_EQ(metricReport.metric_id(), metric.id());
+ EXPECT_TRUE(metricReport.has_kll_metrics());
+ ASSERT_EQ(metricReport.kll_metrics().data_size(), 2);
+
+ KllMetricData data = metricReport.kll_metrics().data(0);
+ ASSERT_EQ(data.bucket_info_size(), 1);
+ KllBucketInfo bucket = data.bucket_info(0);
+ EXPECT_EQ(bucket.start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(bucket.end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(bucket.sketches_size(), 1);
+ EXPECT_EQ(metricReport.kll_metrics().skipped_size(), 0);
+ EXPECT_EQ(data.dimensions_in_what().field(), util::TEST_ATOM_REPORTED);
+ ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 5);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), "dim_1");
+
+ data = metricReport.kll_metrics().data(1);
+ ASSERT_EQ(data.bucket_info_size(), 1);
+ bucket = data.bucket_info(0);
+ EXPECT_EQ(bucket.start_bucket_elapsed_nanos(), bucketStartTimeNs);
+ EXPECT_EQ(bucket.end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+ EXPECT_EQ(bucket.sketches_size(), 1);
+ EXPECT_EQ(metricReport.kll_metrics().skipped_size(), 0);
+ EXPECT_EQ(data.dimensions_in_what().field(), util::TEST_ATOM_REPORTED);
+ ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 5);
+ EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str(), "dim_2");
+}
+
TEST_F(KllMetricE2eTest, TestInitWithKllFieldPositionALL) {
// Create config.
StatsdConfig config;
@@ -120,6 +204,97 @@ TEST_F(KllMetricE2eTest, TestInitWithKllFieldPositionALL) {
ASSERT_EQ(0, processor->mMetricsManagers.size());
}
+TEST_F(KllMetricE2eTest, TestDimensionalSampling) {
+ ShardOffsetProvider::getInstance().setShardOffset(5);
+
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ AtomMatcher bleScanResultReceivedMatcher = CreateSimpleAtomMatcher(
+ "BleScanResultReceivedAtomMatcher", util::BLE_SCAN_RESULT_RECEIVED);
+ *config.add_atom_matcher() = bleScanResultReceivedMatcher;
+
+ // Create kll metric.
+ KllMetric sampledKllMetric =
+ createKllMetric("KllSampledBleScanResultsPerUid", bleScanResultReceivedMatcher,
+ /*num_results=*/2, nullopt);
+ *sampledKllMetric.mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(util::BLE_SCAN_RESULT_RECEIVED, {Position::FIRST});
+ *sampledKllMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateAttributionUidDimensions(util::BLE_SCAN_RESULT_RECEIVED, {Position::FIRST});
+ sampledKllMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_kll_metric() = sampledKllMetric;
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ sp<StatsLogProcessor> processor = CreateStatsLogProcessor(
+ bucketStartTimeNs, bucketStartTimeNs, config, cfgKey, nullptr, 0, new UidMap());
+
+ int appUid1 = 1001; // odd hash value
+ int appUid2 = 1002; // even hash value
+ int appUid3 = 1003; // odd hash value
+ std::vector<std::unique_ptr<LogEvent>> events;
+
+ events.push_back(CreateBleScanResultReceivedEvent(bucketStartTimeNs + 20 * NS_PER_SEC,
+ {appUid1}, {"tag1"}, 10));
+ events.push_back(CreateBleScanResultReceivedEvent(bucketStartTimeNs + 40 * NS_PER_SEC,
+ {appUid2}, {"tag2"}, 10));
+ events.push_back(CreateBleScanResultReceivedEvent(bucketStartTimeNs + 60 * NS_PER_SEC,
+ {appUid3}, {"tag3"}, 10));
+
+ events.push_back(CreateBleScanResultReceivedEvent(bucketStartTimeNs + 120 * NS_PER_SEC,
+ {appUid1}, {"tag1"}, 11));
+ events.push_back(CreateBleScanResultReceivedEvent(bucketStartTimeNs + 140 * NS_PER_SEC,
+ {appUid2}, {"tag2"}, 12));
+ events.push_back(CreateBleScanResultReceivedEvent(bucketStartTimeNs + 160 * NS_PER_SEC,
+ {appUid3}, {"tag3"}, 13));
+
+ // 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);
+
+ ConfigMetricsReport report = reports.reports(0);
+ ASSERT_EQ(report.metrics_size(), 1);
+ StatsLogReport metricReport = report.metrics(0);
+ EXPECT_EQ(metricReport.metric_id(), sampledKllMetric.id());
+ EXPECT_TRUE(metricReport.has_kll_metrics());
+ StatsLogReport::KllMetricDataWrapper kllMetrics;
+ sortMetricDataByDimensionsValue(metricReport.kll_metrics(), &kllMetrics);
+ ASSERT_EQ(kllMetrics.data_size(), 2);
+ EXPECT_EQ(kllMetrics.skipped_size(), 0);
+
+ // Only Uid 1 and 3 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
+ KllMetricData data = kllMetrics.data(0);
+ ValidateAttributionUidDimension(data.dimensions_in_what(), util::BLE_SCAN_RESULT_RECEIVED,
+ appUid1);
+ ValidateKllBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs, {2},
+ 0);
+
+ data = kllMetrics.data(1);
+ ValidateAttributionUidDimension(data.dimensions_in_what(), util::BLE_SCAN_RESULT_RECEIVED,
+ appUid3);
+ ValidateKllBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + bucketSizeNs, {2},
+ 0);
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 176fd9ca..46d0d5d4 100644
--- a/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -24,7 +24,7 @@
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
-using::ndk::SharedRefBase;
+using ::ndk::SharedRefBase;
using std::shared_ptr;
namespace android {
@@ -34,27 +34,6 @@ namespace statsd {
#ifdef __ANDROID__
namespace {
const string kApp1 = "app1.sharing.1";
-const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs.
-const int kCallingUid = 0; // Randomly chosen
-
-void SendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
- string str;
- config.SerializeToString(&str);
- std::vector<uint8_t> configAsVec(str.begin(), str.end());
- service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
-}
-
-ConfigMetricsReport GetReports(sp<StatsLogProcessor> processor, int64_t timestamp,
- bool include_current = false) {
- vector<uint8_t> output;
- ConfigKey configKey(AIBinder_getCallingUid(), kConfigKey);
- processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
- true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output);
- ConfigMetricsReportList reports;
- reports.ParseFromArray(output.data(), output.size());
- EXPECT_EQ(1, reports.reports_size());
- return reports.reports(kCallingUid);
-}
StatsdConfig MakeCountMetricConfig(const std::optional<bool> splitBucket) {
StatsdConfig config;
@@ -122,26 +101,25 @@ StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
}
} // anonymous namespace
-TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- SendConfig(service, MakeCountMetricConfig({true}));
+// Setup for test fixture.
+class PartialBucketE2eTest : public StatsServiceConfigTest {};
+
+TEST_F(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
+ sendConfig(MakeCountMetricConfig({true}));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 2, 100).get());
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
+ ConfigMetricsReport report = getReports(service->mProcessor, start + 3);
// Expect no metrics since the bucket has not finished yet.
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
}
-TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- SendConfig(service, MakeCountMetricConfig({true}));
+TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
+ sendConfig(MakeCountMetricConfig({true}));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -154,15 +132,13 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+ ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
}
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- SendConfig(service, MakeCountMetricConfig({true}));
+TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
+ sendConfig(MakeCountMetricConfig({true}));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
@@ -175,7 +151,7 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+ ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -194,10 +170,8 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- SendConfig(service, MakeCountMetricConfig({true}));
+TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
+ sendConfig(MakeCountMetricConfig({true}));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
@@ -209,7 +183,7 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+ ConfigMetricsReport report = getReports(service->mProcessor, start + 4);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -228,10 +202,8 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
- SendConfig(service, MakeCountMetricConfig(std::nullopt));
+TEST_F(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
+ sendConfig(MakeCountMetricConfig(std::nullopt));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -242,7 +214,7 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3 * NS_PER_SEC, 100).get());
- ConfigMetricsReport report = GetReports(service->mProcessor, start + 4 * NS_PER_SEC);
+ ConfigMetricsReport report = getReports(service->mProcessor, start + 4 * NS_PER_SEC);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -258,11 +230,9 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnBoot) {
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
-TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
StatsdConfig config = MakeCountMetricConfig({false});
- SendConfig(service, config);
+ sendConfig(config);
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
@@ -276,7 +246,7 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
ConfigMetricsReport report =
- GetReports(service->mProcessor, start + 4, /*include_current=*/true);
+ getReports(service->mProcessor, start + 4, /*include_current=*/true);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -287,16 +257,14 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
EXPECT_EQ(bucketInfo.count(), 2);
}
-TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
service->mPullerManager->RegisterPullAtomCallback(
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
/* certificateHash */ {});
- SendConfig(service, MakeValueMetricConfig(0));
+ sendConfig(MakeValueMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -306,7 +274,7 @@ TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
String16(""), /* certificateHash */ {});
ConfigMetricsReport report =
- GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
+ getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -319,16 +287,14 @@ TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
report.metrics(0).value_metrics().data(0).bucket_info(1).end_bucket_elapsed_nanos());
}
-TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
service->mPullerManager->RegisterPullAtomCallback(
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
/* certificateHash */ {});
- SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
+ sendConfig(MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -338,7 +304,7 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
String16(""), /* certificateHash */ {});
ConfigMetricsReport report =
- GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
+ getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -352,11 +318,9 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
}
-TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
// Initial pull will fail since puller is not registered.
- SendConfig(service, MakeValueMetricConfig(0));
+ sendConfig(MakeValueMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -369,7 +333,7 @@ TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
- ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
+ ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
backfillStartEndTimestamp(&report);
// First bucket is dropped due to the initial pull failing
@@ -386,16 +350,14 @@ TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
report.metrics(0).value_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
}
-TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
service->mPullerManager->RegisterPullAtomCallback(
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
/* certificateHash */ {});
- SendConfig(service, MakeGaugeMetricConfig(0));
+ sendConfig(MakeGaugeMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -403,7 +365,7 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
service->mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
String16("v2"), String16(""), /* certificateHash */ {});
- ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
+ ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
@@ -412,16 +374,14 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
ASSERT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
}
-TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
// Partial buckets don't occur when app is first installed.
service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
/* certificateHash */ {});
service->mPullerManager->RegisterPullAtomCallback(
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
- SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
+ sendConfig(MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -431,7 +391,7 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
String16(""), /* certificateHash */ {});
ConfigMetricsReport report =
- GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
+ getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(1, report.metrics(0).gauge_metrics().skipped_size());
@@ -443,11 +403,9 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
}
-TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
// Initial pull will fail since puller hasn't been registered.
- SendConfig(service, MakeGaugeMetricConfig(0));
+ sendConfig(MakeGaugeMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -460,7 +418,7 @@ TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
- ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
+ ConfigMetricsReport report = getReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
@@ -474,11 +432,9 @@ TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
report.metrics(0).gauge_metrics().data(0).bucket_info(0).start_bucket_elapsed_nanos());
}
-TEST(PartialBucketE2eTest, TestCountMetricNoSplitByDefault) {
- shared_ptr<StatsService> service =
- SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+TEST_F(PartialBucketE2eTest, TestCountMetricNoSplitByDefault) {
StatsdConfig config = MakeCountMetricConfig({nullopt}); // Do not set the value in the metric.
- SendConfig(service, config);
+ sendConfig(config);
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
@@ -492,7 +448,7 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitByDefault) {
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
ConfigMetricsReport report =
- GetReports(service->mProcessor, start + 4, /*include_current=*/true);
+ getReports(service->mProcessor, start + 4, /*include_current=*/true);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
diff --git a/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index 385a4730..810b550d 100644
--- a/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -15,12 +15,13 @@
#include <android/binder_interface_utils.h>
#include <gtest/gtest.h>
+#include <vector>
+
+#include "flags/FlagProvider.h"
#include "src/StatsLogProcessor.h"
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
-#include <vector>
-
using ::ndk::SharedRefBase;
namespace android {
@@ -143,6 +144,20 @@ StatsdConfig CreateStatsdConfigWithStates() {
} // namespace
+// Setup for test fixture.
+class ValueMetricE2eTest : public testing::TestWithParam<string> {
+ void SetUp() override {
+ FlagProvider::getInstance().overrideFlag(LIMIT_PULL_FLAG, GetParam(),
+ /*isBootFlag=*/true);
+ }
+
+ void TearDown() override {
+ FlagProvider::getInstance().resetOverrides();
+ }
+};
+
+INSTANTIATE_TEST_SUITE_P(LimitPull, ValueMetricE2eTest, testing::Values(FLAG_FALSE, FLAG_TRUE));
+
/**
* Tests the initial condition and condition after the first log events for
* value metrics with either a combination condition or simple condition.
@@ -202,7 +217,7 @@ TEST(ValueMetricE2eTest, TestInitialConditionChanges) {
EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition);
}
-TEST(ValueMetricE2eTest, TestPulledEvents) {
+TEST_P(ValueMetricE2eTest, TestPulledEvents) {
auto config = CreateStatsdConfig();
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
@@ -303,9 +318,26 @@ TEST(ValueMetricE2eTest, TestPulledEvents) {
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
ASSERT_EQ(1, data.bucket_info(3).values_size());
+
+ valueMetrics = reports.reports(0).metrics(0).value_metrics();
+ ASSERT_EQ(2, valueMetrics.skipped_size());
+
+ StatsLogReport::SkippedBuckets skipped = valueMetrics.skipped(0);
+ EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, skipped.drop_event(0).drop_reason());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 2 * bucketSizeNs)),
+ skipped.start_bucket_elapsed_nanos());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 3 * bucketSizeNs)),
+ skipped.end_bucket_elapsed_nanos());
+
+ skipped = valueMetrics.skipped(1);
+ EXPECT_EQ(BucketDropReason::NO_DATA, skipped.drop_event(0).drop_reason());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
+ skipped.start_bucket_elapsed_nanos());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 6 * bucketSizeNs)),
+ skipped.end_bucket_elapsed_nanos());
}
-TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
+TEST_P(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
auto config = CreateStatsdConfig();
int64_t baseTimeNs = getElapsedRealtimeNs();
// 10 mins == 2 bucket durations.
@@ -406,9 +438,33 @@ TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
ASSERT_EQ(1, data.bucket_info(2).values_size());
+
+ valueMetrics = reports.reports(0).metrics(0).value_metrics();
+ ASSERT_EQ(3, valueMetrics.skipped_size());
+
+ StatsLogReport::SkippedBuckets skipped = valueMetrics.skipped(0);
+ EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, skipped.drop_event(0).drop_reason());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 2 * bucketSizeNs)),
+ skipped.start_bucket_elapsed_nanos());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
+ skipped.end_bucket_elapsed_nanos());
+
+ skipped = valueMetrics.skipped(1);
+ EXPECT_EQ(BucketDropReason::NO_DATA, skipped.drop_event(0).drop_reason());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 6 * bucketSizeNs)),
+ skipped.start_bucket_elapsed_nanos());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 7 * bucketSizeNs)),
+ skipped.end_bucket_elapsed_nanos());
+
+ skipped = valueMetrics.skipped(2);
+ EXPECT_EQ(BucketDropReason::NO_DATA, skipped.drop_event(0).drop_reason());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 7 * bucketSizeNs)),
+ skipped.start_bucket_elapsed_nanos());
+ EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 8 * bucketSizeNs)),
+ skipped.end_bucket_elapsed_nanos());
}
-TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
+TEST_P(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
auto config = CreateStatsdConfig(false);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
@@ -454,7 +510,8 @@ TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
processor->onStatsdInitCompleted(metricInitTimeNs);
// Check no pull occurred since metric not active.
- StatsdStatsReport_PulledAtomStats pulledAtomStats = getPulledAtomStats();
+ StatsdStatsReport_PulledAtomStats pulledAtomStats =
+ getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.atom_id(), util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.total_pull(), 0);
@@ -477,7 +534,7 @@ TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
processor->notifyAppUpgrade(appUpgradeTimeNs, "appName", 1000 /* uid */, 2 /* version */);
// Check no pull occurred since metric not active.
- pulledAtomStats = getPulledAtomStats();
+ pulledAtomStats = getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.atom_id(), util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.total_pull(), 0);
@@ -498,7 +555,7 @@ TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
buffer.clear();
processor->onDumpReport(cfgKey, dumpReportTimeNs, true /* include_current_partial_bucket */,
true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &buffer);
- pulledAtomStats = getPulledAtomStats();
+ pulledAtomStats = getPulledAtomStats(util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.atom_id(), util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(pulledAtomStats.total_pull(), 0);
diff --git a/statsd/tests/guardrail/StatsdStats_test.cpp b/statsd/tests/guardrail/StatsdStats_test.cpp
index 81fcbe95..cc4d7c4d 100644
--- a/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -13,12 +13,15 @@
// limitations under the License.
#include "src/guardrail/StatsdStats.h"
-#include "statslog_statsdtest.h"
-#include "tests/statsd_test_util.h"
#include <gtest/gtest.h>
+
#include <vector>
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
+#include "statslog_statsdtest.h"
+#include "tests/statsd_test_util.h"
+
#ifdef __ANDROID__
namespace android {
@@ -35,7 +38,7 @@ TEST(StatsdStatsTest, TestValidConfigAdd) {
const int matchersCount = 30;
const int alertsCount = 10;
stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
- true /*valid config*/);
+ nullopt /*valid config*/);
vector<uint8_t> output;
stats.dumpStats(&output, false /*reset stats*/);
@@ -51,6 +54,7 @@ TEST(StatsdStatsTest, TestValidConfigAdd) {
EXPECT_EQ(matchersCount, configReport.matcher_count());
EXPECT_EQ(alertsCount, configReport.alert_count());
EXPECT_EQ(true, configReport.is_valid());
+ EXPECT_FALSE(configReport.has_invalid_config_reason());
EXPECT_FALSE(configReport.has_deletion_time_sec());
}
@@ -61,8 +65,99 @@ TEST(StatsdStatsTest, TestInvalidConfigAdd) {
const int conditionsCount = 20;
const int matchersCount = 30;
const int alertsCount = 10;
+ optional<InvalidConfigReason> invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_UNKNOWN, 1);
+ invalidConfigReason->stateId = 2;
+ invalidConfigReason->alertId = 3;
+ invalidConfigReason->alarmId = 4;
+ invalidConfigReason->subscriptionId = 5;
+ invalidConfigReason->matcherIds.push_back(6);
+ invalidConfigReason->matcherIds.push_back(7);
+ invalidConfigReason->conditionIds.push_back(8);
+ invalidConfigReason->conditionIds.push_back(9);
+ invalidConfigReason->conditionIds.push_back(10);
+ stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
+ invalidConfigReason /*bad config*/);
+ vector<uint8_t> output;
+ stats.dumpStats(&output, false);
+
+ StatsdStatsReport report;
+ bool good = report.ParseFromArray(&output[0], output.size());
+ EXPECT_TRUE(good);
+ ASSERT_EQ(1, report.config_stats_size());
+ const auto& configReport = report.config_stats(0);
+ // The invalid config should be put into icebox with a deletion time.
+ EXPECT_TRUE(configReport.has_deletion_time_sec());
+ EXPECT_TRUE(configReport.has_invalid_config_reason());
+ EXPECT_EQ(configReport.invalid_config_reason().reason(), INVALID_CONFIG_REASON_UNKNOWN);
+ EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
+ EXPECT_EQ(configReport.invalid_config_reason().state_id(), 2);
+ EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 3);
+ EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 4);
+ EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 5);
+ EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 2);
+ EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 6);
+ EXPECT_EQ(configReport.invalid_config_reason().matcher_id(1), 7);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 3);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 8);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 9);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id(2), 10);
+}
+
+TEST(StatsdStatsTest, TestInvalidConfigMissingMetricId) {
+ StatsdStats stats;
+ ConfigKey key(0, 12345);
+ const int metricsCount = 10;
+ const int conditionsCount = 20;
+ const int matchersCount = 30;
+ const int alertsCount = 10;
+ optional<InvalidConfigReason> invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
+ invalidConfigReason->stateId = 1;
+ invalidConfigReason->alertId = 2;
+ invalidConfigReason->alarmId = 3;
+ invalidConfigReason->subscriptionId = 4;
+ invalidConfigReason->matcherIds.push_back(5);
+ invalidConfigReason->conditionIds.push_back(6);
+ invalidConfigReason->conditionIds.push_back(7);
+ stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
+ invalidConfigReason /*bad config*/);
+ vector<uint8_t> output;
+ stats.dumpStats(&output, false);
+
+ StatsdStatsReport report;
+ bool good = report.ParseFromArray(&output[0], output.size());
+ EXPECT_TRUE(good);
+ ASSERT_EQ(1, report.config_stats_size());
+ const auto& configReport = report.config_stats(0);
+ // The invalid config should be put into icebox with a deletion time.
+ EXPECT_TRUE(configReport.has_deletion_time_sec());
+ EXPECT_TRUE(configReport.has_invalid_config_reason());
+ EXPECT_EQ(configReport.invalid_config_reason().reason(),
+ INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING);
+ EXPECT_FALSE(configReport.invalid_config_reason().has_metric_id());
+ EXPECT_EQ(configReport.invalid_config_reason().state_id(), 1);
+ EXPECT_EQ(configReport.invalid_config_reason().alert_id(), 2);
+ EXPECT_EQ(configReport.invalid_config_reason().alarm_id(), 3);
+ EXPECT_EQ(configReport.invalid_config_reason().subscription_id(), 4);
+ EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 1);
+ EXPECT_EQ(configReport.invalid_config_reason().matcher_id(0), 5);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 2);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id(0), 6);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id(1), 7);
+}
+
+TEST(StatsdStatsTest, TestInvalidConfigOnlyMetricId) {
+ StatsdStats stats;
+ ConfigKey key(0, 12345);
+ const int metricsCount = 10;
+ const int conditionsCount = 20;
+ const int matchersCount = 30;
+ const int alertsCount = 10;
+ optional<InvalidConfigReason> invalidConfigReason =
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG, 1);
stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
- false /*bad config*/);
+ invalidConfigReason /*bad config*/);
vector<uint8_t> output;
stats.dumpStats(&output, false);
@@ -73,6 +168,16 @@ TEST(StatsdStatsTest, TestInvalidConfigAdd) {
const auto& configReport = report.config_stats(0);
// The invalid config should be put into icebox with a deletion time.
EXPECT_TRUE(configReport.has_deletion_time_sec());
+ EXPECT_TRUE(configReport.has_invalid_config_reason());
+ EXPECT_EQ(configReport.invalid_config_reason().reason(),
+ INVALID_CONFIG_REASON_METRIC_NOT_IN_PREV_CONFIG);
+ EXPECT_EQ(configReport.invalid_config_reason().metric_id(), 1);
+ EXPECT_FALSE(configReport.invalid_config_reason().has_state_id());
+ EXPECT_FALSE(configReport.invalid_config_reason().has_alert_id());
+ EXPECT_FALSE(configReport.invalid_config_reason().has_alarm_id());
+ EXPECT_FALSE(configReport.invalid_config_reason().has_subscription_id());
+ EXPECT_EQ(configReport.invalid_config_reason().matcher_id_size(), 0);
+ EXPECT_EQ(configReport.invalid_config_reason().condition_id_size(), 0);
}
TEST(StatsdStatsTest, TestConfigRemove) {
@@ -83,7 +188,7 @@ TEST(StatsdStatsTest, TestConfigRemove) {
const int matchersCount = 30;
const int alertsCount = 10;
stats.noteConfigReceived(key, metricsCount, conditionsCount, matchersCount, alertsCount, {},
- true);
+ nullopt);
vector<uint8_t> output;
stats.dumpStats(&output, false);
StatsdStatsReport report;
@@ -105,7 +210,7 @@ TEST(StatsdStatsTest, TestConfigRemove) {
TEST(StatsdStatsTest, TestSubStats) {
StatsdStats stats;
ConfigKey key(0, 12345);
- stats.noteConfigReceived(key, 2, 3, 4, 5, {std::make_pair(123, 456)}, true);
+ stats.noteConfigReceived(key, 2, 3, 4, 5, {std::make_pair(123, 456)}, nullopt);
stats.noteMatcherMatched(key, StringToId("matcher1"));
stats.noteMatcherMatched(key, StringToId("matcher1"));
@@ -393,7 +498,7 @@ TEST(StatsdStatsTest, TestTimestampThreshold) {
timestamps.push_back(i);
}
ConfigKey key(0, 12345);
- stats.noteConfigReceived(key, 2, 3, 4, 5, {}, true);
+ stats.noteConfigReceived(key, 2, 3, 4, 5, {}, nullopt);
for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
stats.noteDataDropped(key, timestamps[i]);
diff --git a/statsd/tests/metrics/EventMetricProducer_test.cpp b/statsd/tests/metrics/EventMetricProducer_test.cpp
index 192848ec..d5fe9327 100644
--- a/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -41,11 +41,15 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const uint64_t protoHash = 0x1234567890;
-void makeLogEvent(LogEvent* logEvent, int32_t atomId, int64_t timestampNs, string str) {
+void makeLogEvent(LogEvent* logEvent, int32_t atomId, int64_t timestampNs, string str,
+ vector<uint8_t>* bytesField = nullptr) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeString(statsEvent, str.c_str());
+ if (bytesField != nullptr) {
+ AStatsEvent_writeByteArray(statsEvent, bytesField->data(), bytesField->size());
+ }
parseStatsEventToLogEvent(statsEvent, logEvent);
}
@@ -241,6 +245,58 @@ TEST_F(EventMetricProducerTest, TestOneAtomTagAggregatedEvents) {
}
}
+TEST_F(EventMetricProducerTest, TestBytesFieldAggregatedEvents) {
+ int64_t bucketStartTimeNs = 10000000000;
+ int tagId = 1;
+
+ EventMetric metric;
+ metric.set_id(1);
+
+ vector<uint8_t> bytesField1{10, 20, 30};
+ vector<uint8_t> bytesField2{10, 20, 30, 40};
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event1, tagId, bucketStartTimeNs + 10, "111", &bytesField1);
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event2, tagId, bucketStartTimeNs + 20, "111", &bytesField1);
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event3, tagId, bucketStartTimeNs + 30, "111", &bytesField1);
+
+ LogEvent event4(/*uid=*/0, /*pid=*/0);
+ makeLogEvent(&event4, tagId, bucketStartTimeNs + 40, "111", &bytesField2);
+
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
+ wizard, protoHash, bucketStartTimeNs);
+
+ eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
+ eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
+ eventProducer.onMatchedLogEvent(1 /*matcher index*/, event3);
+ eventProducer.onMatchedLogEvent(1 /*matcher index*/, event4);
+
+ // Check dump report content.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ eventProducer.onDumpReport(bucketStartTimeNs + 50, true /*include current partial bucket*/,
+ true /*erase data*/, FAST, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_event_metrics());
+ ASSERT_EQ(2, report.event_metrics().data_size());
+
+ for (EventMetricData metricData : report.event_metrics().data()) {
+ AggregatedAtomInfo atomInfo = metricData.aggregated_atom_info();
+ if (atomInfo.elapsed_timestamp_nanos_size() == 1) {
+ EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 40);
+ } else if (atomInfo.elapsed_timestamp_nanos_size() == 3) {
+ EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(0), bucketStartTimeNs + 10);
+ EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(1), bucketStartTimeNs + 20);
+ EXPECT_EQ(atomInfo.elapsed_timestamp_nanos(2), bucketStartTimeNs + 30);
+ } else {
+ FAIL();
+ }
+ }
+}
+
TEST_F(EventMetricProducerTest, TestTwoAtomTagAggregatedEvents) {
int64_t bucketStartTimeNs = 10000000000;
int tagId = 1;
diff --git a/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index c64fb7b7..a378393c 100644
--- a/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -150,7 +150,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
allData.clear();
allData.push_back(makeLogEvent(tagId, bucket2StartTimeNs + 1, 10, "some value", 11));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
EXPECT_EQ(INT, it->mValue.getType());
@@ -168,7 +168,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
allData.clear();
allData.push_back(makeLogEvent(tagId, bucket3StartTimeNs + 10, 24, "some value", 25));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
EXPECT_EQ(INT, it->mValue.getType());
@@ -331,7 +331,7 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -361,7 +361,8 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + bucketSizeNs + 1, 3));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucketStartTimeNs + bucketSizeNs);
ASSERT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
@@ -399,7 +400,7 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -462,7 +463,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
@@ -551,7 +552,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1000, 110));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
@@ -598,7 +599,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 13));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -611,7 +612,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
allData.clear();
allData.push_back(event2);
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucketStartTimeNs + bucketSizeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -623,7 +625,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
allData.clear();
allData.push_back(
CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10, 26));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + 2 * bucketSizeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
@@ -635,7 +638,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
// This event does not have the gauge field. Thus the current bucket value is 0.
allData.clear();
allData.push_back(CreateNoValuesLogEvent(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10));
- gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
+ gaugeProducer.onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucketStartTimeNs + 3 * bucketSizeNs);
ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
}
@@ -848,6 +852,96 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
}
+TEST(GaugeMetricProducerTest, TestPullDimensionalSampling) {
+ ShardOffsetProvider::getInstance().setShardOffset(5);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ int triggerId = 5;
+ int shardCount = 2;
+ GaugeMetric sampledGaugeMetric = createGaugeMetric(
+ "GaugePullSampled", metricId, GaugeMetric::FIRST_N_SAMPLES, nullopt, triggerId);
+ sampledGaugeMetric.set_max_pull_delay_sec(INT_MAX);
+ *sampledGaugeMetric.mutable_dimensions_in_what() = CreateDimensions(tagId, {1});
+ *sampledGaugeMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(tagId, {1});
+ sampledGaugeMetric.mutable_dimensional_sampling_info()->set_shard_count(shardCount);
+ *config.add_gauge_metric() = sampledGaugeMetric;
+
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+ sp<EventMatcherWizard> eventMatcherWizard =
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 10, 1001, 5, 10));
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 10, 1002, 10, 10));
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 10, 1003, 15, 10));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 20, 1001, 6, 10));
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 20, 1002, 12, 10));
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 20, 1003, 18, 10));
+ return true;
+ }));
+
+ GaugeMetricProducer gaugeProducer(kConfigKey, sampledGaugeMetric,
+ -1 /*-1 meaning no condition*/, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
+ tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ SamplingInfo samplingInfo;
+ samplingInfo.shardCount = shardCount;
+ translateFieldMatcher(sampledGaugeMetric.dimensional_sampling_info().sampled_what_field(),
+ &samplingInfo.sampledWhatFields);
+ gaugeProducer.setSamplingInfo(samplingInfo);
+ gaugeProducer.prepareFirstBucket();
+
+ LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 10, 5);
+ gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
+
+ triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 20);
+ gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000;
+ gaugeProducer.onDumpReport(dumpReportTimeNs, true /* include current buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ backfillDimensionPath(&report);
+ backfillStartEndTimestamp(&report);
+ backfillAggregatedAtoms(&report);
+
+ EXPECT_TRUE(report.has_gauge_metrics());
+ StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+ sortMetricDataByDimensionsValue(report.gauge_metrics(), &gaugeMetrics);
+ ASSERT_EQ(2, gaugeMetrics.data_size());
+ EXPECT_EQ(0, report.gauge_metrics().skipped_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(), tagId, 1001);
+ ValidateGaugeBucketTimes(data.bucket_info(0), bucketStartTimeNs, dumpReportTimeNs,
+ {bucketStartTimeNs + 10, bucketStartTimeNs + 20});
+
+ data = gaugeMetrics.data(1);
+ ValidateUidDimension(data.dimensions_in_what(), tagId, 1003);
+ ValidateGaugeBucketTimes(data.bucket_info(0), bucketStartTimeNs, dumpReportTimeNs,
+ {bucketStartTimeNs + 10, bucketStartTimeNs + 20});
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/tests/metrics/NumericValueMetricProducer_test.cpp b/statsd/tests/metrics/NumericValueMetricProducer_test.cpp
index f4e7cd9c..f2b50c32 100644
--- a/statsd/tests/metrics/NumericValueMetricProducer_test.cpp
+++ b/statsd/tests/metrics/NumericValueMetricProducer_test.cpp
@@ -147,6 +147,22 @@ public:
stateGroupMap);
}
+ static sp<NumericValueMetricProducer> createValueProducerWithSampling(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
+ const int pullAtomId = tagId) {
+ sp<NumericValueMetricProducer> valueProducer = createValueProducer(
+ pullerManager, metric, pullAtomId, /*conditionAfterFirstBucketPrepared=*/nullopt,
+ /*slicedStateAtoms=*/{}, /*stateGroupMap=*/{}, bucketStartTimeNs, bucketStartTimeNs,
+ /*eventMatcherWizard=*/nullptr);
+
+ SamplingInfo samplingInfo;
+ samplingInfo.shardCount = metric.dimensional_sampling_info().shard_count();
+ translateFieldMatcher(metric.dimensional_sampling_info().sampled_what_field(),
+ &samplingInfo.sampledWhatFields);
+ valueProducer->setSamplingInfo(samplingInfo);
+ return valueProducer;
+ }
+
static sp<NumericValueMetricProducer> createValueProducerWithBucketParams(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
const int64_t timeBaseNs, const int64_t startTimeNs, const int pullAtomId = tagId) {
@@ -349,7 +365,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsNoCondition) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// empty since bucket is flushed
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// dimInfos holds the base
@@ -363,7 +379,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsNoCondition) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// empty since bucket is cleared
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// dimInfos holds the base
@@ -378,7 +394,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsNoCondition) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
// empty since bucket is cleared
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// dimInfos holds the base
@@ -425,7 +441,7 @@ TEST_P(NumericValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 2));
- valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Partial buckets created in 2nd bucket.
switch (GetParam()) {
@@ -474,7 +490,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsWithFiltering) {
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 3, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// empty since bucket is cleared
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// dimInfos holds the base
@@ -488,14 +504,14 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsWithFiltering) {
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket3StartTimeNs + 1, 4, 23));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// No new data seen, so data has been cleared.
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(0UL, valueProducer->mDimInfos.size());
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
curBase = valueProducer->mDimInfos.begin()->second.dimExtras[0];
@@ -525,7 +541,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// empty since bucket is cleared
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// dimInfos holds the base
@@ -539,7 +555,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
allData.clear();
// 10 is less than 11, so we reset and keep 10 as the value.
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// empty since the bucket is flushed.
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -551,7 +567,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
curBase = valueProducer->mDimInfos.begin()->second.dimExtras[0];
@@ -578,7 +594,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// empty since bucket is cleared
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// mDimInfos holds the base
@@ -592,7 +608,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
allData.clear();
// 10 is less than 11, so we reset. 10 only updates the base.
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
curBase = valueProducer->mDimInfos.begin()->second.dimExtras[0];
@@ -602,7 +618,7 @@ TEST(NumericValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
curBase = valueProducer->mDimInfos.begin()->second.dimExtras[0];
@@ -664,7 +680,7 @@ TEST(NumericValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8}, {0},
{bucketStartTimeNs}, {bucket2StartTimeNs});
@@ -777,7 +793,7 @@ TEST_P(NumericValueMetricProducerTest_PartialBucket, TestPulledValue) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
switch (GetParam()) {
@@ -795,7 +811,7 @@ TEST_P(NumericValueMetricProducerTest_PartialBucket, TestPulledValue) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 150));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
EXPECT_EQ(bucket3StartTimeNs, valueProducer->mCurrentBucketStartTimeNs);
EXPECT_EQ(2, valueProducer->getCurrentBucketNum());
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
@@ -823,7 +839,7 @@ TEST(NumericValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -1141,7 +1157,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundaryNoCondition) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// empty since bucket is finished
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -1155,7 +1171,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundaryNoCondition) {
// pull 2 at correct time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// empty since bucket is finished
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -1172,7 +1188,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundaryNoCondition) {
// The new bucket is back to normal.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket6StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
curBase = valueProducer->mDimInfos.begin()->second.dimExtras[0];
@@ -1253,7 +1269,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundaryWithCondition) {
// since the condition turned to off before this pull finish, it has no effect
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8}, {1},
{bucketStartTimeNs}, {bucket2StartTimeNs});
@@ -1339,7 +1355,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
// for the new bucket since it was just pulled.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 50);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -1354,7 +1370,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 160));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
assertPastBucketValuesSingleKey(
valueProducer->mPastBuckets, {20, 30}, {bucketSizeNs - 8, bucketSizeNs - 24}, {1, -1},
@@ -1480,6 +1496,7 @@ TEST(NumericValueMetricProducerTest, TestPushedAggregateAvg) {
EXPECT_TRUE(
std::abs(valueProducer->mPastBuckets.begin()->second.back().aggregates[0].double_value -
12.5) < epsilon);
+ EXPECT_EQ(2, valueProducer->mPastBuckets.begin()->second.back().sampleSizes[0]);
}
TEST(NumericValueMetricProducerTest, TestPushedAggregateSum) {
@@ -1742,7 +1759,7 @@ TEST(NumericValueMetricProducerTest, TestUseZeroDefaultBase) {
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
EXPECT_EQ(true, base1.has_value());
@@ -1808,7 +1825,7 @@ TEST(NumericValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
EXPECT_EQ(true, base1.has_value());
@@ -1831,7 +1848,7 @@ TEST(NumericValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
// This pull is incomplete since it's missing dimension 1. Will cause mDimInfos to be trimmed
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -1845,7 +1862,7 @@ TEST(NumericValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 13));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 1, 5));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket5StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
@@ -1898,7 +1915,7 @@ TEST(NumericValueMetricProducerTest, TestTrimUnusedDimensionKey) {
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 2, 4));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
@@ -1924,7 +1941,7 @@ TEST(NumericValueMetricProducerTest, TestTrimUnusedDimensionKey) {
// next pull somehow did not happen, skip to end of bucket 3
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
// Only one dimension left. One was trimmed.
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -1939,7 +1956,7 @@ TEST(NumericValueMetricProducerTest, TestTrimUnusedDimensionKey) {
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 14));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 1, 14));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket5StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
@@ -1947,7 +1964,7 @@ TEST(NumericValueMetricProducerTest, TestTrimUnusedDimensionKey) {
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket6StartTimeNs + 1, 1, 19));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket6StartTimeNs + 1, 2, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket6StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
@@ -2009,7 +2026,7 @@ TEST(NumericValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange
EXPECT_EQ(0, curInterval.sampleSize);
vector<shared_ptr<LogEvent>> allData;
- valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_FAIL, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
EXPECT_EQ(false, curBase.has_value());
@@ -2197,7 +2214,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditio
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
@@ -2207,7 +2224,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditio
// Bucket end.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
@@ -2275,7 +2292,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHi
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// First bucket added to mSkippedBuckets after flush.
ASSERT_EQ(1UL, valueProducer->mSkippedBuckets.size());
@@ -2335,7 +2352,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPull
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
- valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_FAIL, bucketStartTimeNs);
valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
@@ -2343,7 +2360,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPull
// Bucket end.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
@@ -2412,7 +2429,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFai
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs);
valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
@@ -2420,7 +2437,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFai
// Bucket end.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 140));
- valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_FAIL, bucket2StartTimeNs);
valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
@@ -2474,7 +2491,7 @@ TEST(NumericValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
EXPECT_EQ(valueProducer->mDimInfos.begin()->second.seenNewData, false);
@@ -2484,7 +2501,7 @@ TEST(NumericValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
// Bucket 3 empty.
allData.clear();
allData.push_back(CreateNoValuesLogEvent(tagId, bucket3StartTimeNs + 1));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// Data has been trimmed.
ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
ASSERT_EQ(1UL, valueProducer->mSkippedBuckets.size());
@@ -2494,7 +2511,7 @@ TEST(NumericValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
// Bucket 4 start.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 150));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
ASSERT_EQ(2UL, valueProducer->mSkippedBuckets.size());
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
@@ -2503,7 +2520,7 @@ TEST(NumericValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
// Bucket 5 start.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket5StartTimeNs + 1, 170));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket5StartTimeNs);
assertPastBucketValuesSingleKey(
valueProducer->mPastBuckets, {107, 20}, {bucketSizeNs, bucketSizeNs}, {0, 0},
{bucketStartTimeNs, bucket4StartTimeNs}, {bucket2StartTimeNs, bucket5StartTimeNs});
@@ -2574,7 +2591,7 @@ TEST(NumericValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged)
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
curBase = valueProducer->mDimInfos.begin()->second.dimExtras[0];
@@ -2632,7 +2649,7 @@ TEST(NumericValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
// End of bucket
vector<shared_ptr<LogEvent>> allData;
allData.clear();
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(0UL, valueProducer->mDimInfos.size());
@@ -2669,7 +2686,7 @@ TEST(NumericValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 2));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Key 1 should be removed from mDimInfos since in not present in the most pull.
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
@@ -2737,7 +2754,7 @@ TEST_P(NumericValueMetricProducerTest_PartialBucket, TestFullBucketResetWhenLast
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 4));
// Pull fails and arrives late.
- valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_FAIL, bucket3StartTimeNs + 1);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
{partialBucketSplitTimeNs - bucketStartTimeNs}, {0},
{bucketStartTimeNs}, {partialBucketSplitTimeNs});
@@ -2781,7 +2798,7 @@ TEST(NumericValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
// End of first bucket
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 4));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
@@ -2813,11 +2830,11 @@ TEST(NumericValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs + 30);
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Bucket should have been completed.
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs}, {0},
@@ -2843,11 +2860,11 @@ TEST(NumericValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucketStartTimeNs + 30);
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Bucket should have been completed.
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs}, {0},
@@ -2934,7 +2951,7 @@ TEST(NumericValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged)
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2}, {0}, {bucketStartTimeNs},
{bucket2StartTimeNs});
@@ -2978,18 +2995,18 @@ TEST(NumericValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 3, 10));
- valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_FAIL, bucketStartTimeNs + 3);
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_FAIL, bucket2StartTimeNs);
valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// There was not global base available so all buckets are invalid.
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {}, {});
@@ -3018,7 +3035,7 @@ TEST(NumericValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, tagId, 2, 2));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ProtoOutputStream output;
std::set<string> strSet;
@@ -3083,7 +3100,7 @@ TEST(NumericValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 30);
// Bucket should have been completed.
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs}, {30},
@@ -3134,7 +3151,7 @@ TEST(NumericValueMetricProducerTest, TestPulledData_noDiff_withMultipleCondition
// Now the alarm is delivered. Condition is off though.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8}, {0},
{bucketStartTimeNs}, {bucket2StartTimeNs});
@@ -3166,7 +3183,7 @@ TEST(NumericValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
// Now the alarm is delivered. Condition is on.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8}, {0},
{bucketStartTimeNs}, {bucket2StartTimeNs});
@@ -3188,7 +3205,7 @@ TEST(NumericValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse)
// Now the alarm is delivered. Condition is off though.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Condition was always false.
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}, {}, {}, {});
@@ -3222,7 +3239,7 @@ TEST(NumericValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
// Now the alarm is delivered. Condition is off though.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(0UL, valueProducer->mDimInfos.size());
@@ -3311,7 +3328,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEv
// Bucket boundary pull.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
// Late condition change event.
valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
@@ -3378,7 +3395,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateE
// Bucket boundary pull.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 20));
@@ -3722,7 +3739,7 @@ TEST(NumericValueMetricProducerTest_BucketDrop, TestConditionUnknownMultipleBuck
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 3));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// This bucket is also dropped due to condition unknown.
int64_t conditionChangeTimeNs = bucket2StartTimeNs + 10 * NS_PER_SEC;
@@ -4720,7 +4737,7 @@ TEST(NumericValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensi
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 10));
allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 15));
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
// Ensure the MetricDimensionKeys for the current state are kept.
ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
@@ -5756,7 +5773,7 @@ TEST(NumericValueMetricProducerTest, TestSlicedStateWithMultipleDimensions) {
CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 16 /* tag */));
allData.push_back(
CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 2 /*uid*/, 13, 8 /*tag*/));
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
// Buckets flushed. MetricDimensionKeys not corresponding to the current state are removed.
ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
@@ -5966,7 +5983,7 @@ TEST(NumericValueMetricProducerTest, TestSlicedStateWithCondition) {
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
@@ -6130,7 +6147,7 @@ TEST(NumericValueMetricProducerTest, TestSlicedStateWithConditionFalseMultipleBu
// Pull at end of first bucket.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 11));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(1UL, valueProducer->mDimInfos.size());
@@ -6143,7 +6160,7 @@ TEST(NumericValueMetricProducerTest, TestSlicedStateWithConditionFalseMultipleBu
// Pull at end of second bucket. Since no new data is seen, mDimInfos will be cleared.
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(0UL, valueProducer->mDimInfos.size());
@@ -6339,7 +6356,7 @@ TEST(NumericValueMetricProducerTest, TestSlicedStateWithMultipleDimensionsMissin
CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 14 /* tag */));
allData.push_back(
CreateThreeValueLogEvent(tagId, bucket2StartTimeNs, 1 /*uid*/, 13, 16 /* tag */));
- valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs + 1);
// Buckets flushed. MetricDimensionKeys not corresponding to the current state are removed.
ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
@@ -6527,7 +6544,7 @@ TEST(NumericValueMetricProducerTest, TestUploadThreshold) {
allData.clear();
allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 1 /*uid*/, 21, 21));
allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 2 /*uid*/, 20, 5));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Check dump report.
ProtoOutputStream output;
@@ -6596,7 +6613,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWhileC
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs}, {pullDelayNs},
@@ -6605,7 +6623,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWhileC
// second pull on the bucket #2 boundary on time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// the second pull did close the second bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5, 5},
@@ -6646,7 +6664,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWhileC
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + delayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + delayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + delayNs);
// first delayed pull on the bucket #1 edge
// the delayed pull did close the first bucket with condition duration == conditionDurationNs
@@ -6660,7 +6679,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWhileC
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// second pull on the bucket #2 edge is on time
assertPastBucketValuesSingleKey(
@@ -6716,7 +6735,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestLatePullOnCondition
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 30));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// second pull on the bucket #2 edge is on time
// the pull did close the second bucket with condition where
@@ -6819,7 +6838,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWithCo
vector<shared_ptr<LogEvent>> allData;
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket1LatePullNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket1LatePullNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket1LatePullNs);
// first delayed pull on the bucket #1 edge
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
@@ -6833,7 +6852,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWithCo
// will force delayed pull & bucket #2 close
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2LatePullNs, 25));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2LatePullNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2LatePullNs);
// second delayed pull on the bucket #2 edge
// the pull did close the second bucket with condition true
@@ -6850,7 +6869,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullWithCo
// will force pull on time & bucket #3 close
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs, 40));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
// the pull did close the third bucket with condition true
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5, 10, 15},
@@ -6887,7 +6906,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullNoCond
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs}, {pullDelayNs},
@@ -6896,7 +6916,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullNoCond
// second pull on the bucket #2 boundary on time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// the second pull did close the second bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5, 5},
@@ -6907,7 +6927,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullNoCond
// third pull on the bucket #3 boundary on time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
// the third pull did close the third bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5, 5, 5},
@@ -6939,7 +6959,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullNoCond
// first delayed pull on the bucket #1 edge with delay
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket which is skipped
// skipped due to bucket does not contains any value
@@ -6949,7 +6970,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullNoCond
// second pull on the bucket #2 boundary on time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// the second pull did close the second bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs},
@@ -6958,7 +6979,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestAlarmLatePullNoCond
// third pull on the bucket #3 boundary on time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs, 20));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket4StartTimeNs);
// the third pull did close the third bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(
@@ -6999,7 +7020,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestThresholdNotDefined
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
// and the condition correction == pull delay
@@ -7055,7 +7077,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestThresholdDefinedZer
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs}, {pullDelayNs},
@@ -7112,7 +7135,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestThresholdUploadPass
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs}, {pullDelayNs},
@@ -7121,7 +7145,7 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestThresholdUploadPass
// second pull on the bucket #2 boundary on time
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 15));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket3StartTimeNs);
// the second pull did close the second bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5, 5},
@@ -7182,7 +7206,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestThresholdUploadPass
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs}, {pullDelayNs},
@@ -7239,7 +7264,8 @@ TEST(NumericValueMetricProducerTest_ConditionCorrection, TestThresholdUploadSkip
// first delayed pull on the bucket #1 edge
allData.clear();
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + pullDelayNs, 10));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + pullDelayNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS,
+ bucket2StartTimeNs + pullDelayNs);
// the delayed pull did close the first bucket with condition duration == bucketSizeNs
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {5}, {bucketSizeNs}, {pullDelayNs},
@@ -7422,7 +7448,7 @@ TEST(NumericValueMetricProducerTest, TestSubsetDimensions) {
allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 1 /*uid*/, 11, 7));
allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 2 /*uid*/, 8, 5));
allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, 2 /*uid*/, 9, 7));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
ASSERT_EQ(2UL, valueProducer->mDimInfos.size());
@@ -7501,7 +7527,7 @@ TEST(NumericValueMetricProducerTest, TestRepeatedValueFieldAndDimensions) {
allData.clear();
allData.push_back(makeRepeatedUidLogEvent(tagId, bucket2StartTimeNs + 1, {1, 10}, 5, {5, 7}));
allData.push_back(makeRepeatedUidLogEvent(tagId, bucket2StartTimeNs + 1, {2, 10}, 5, {7, 5}));
- valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, PullResult::PULL_RESULT_SUCCESS, bucket2StartTimeNs);
// Check dump report.
ProtoOutputStream output;
@@ -7538,6 +7564,184 @@ TEST(NumericValueMetricProducerTest, TestRepeatedValueFieldAndDimensions) {
0); // Summed diffs of 7, 14
}
+TEST(NumericValueMetricProducerTest, TestSampleSize) {
+ sp<EventMatcherWizard> eventMatcherWizard =
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetric metric = NumericValueMetricProducerTestHelper::createMetric();
+
+ /*Sample size is added automatically with ValueMetric::AVG*/
+ metric.set_aggregation_type(ValueMetric::AVG);
+ sp<NumericValueMetricProducer> valueProducerAvg =
+ NumericValueMetricProducerTestHelper::createValueProducerNoConditions(
+ pullerManager, metric, /*pullAtomId=*/-1);
+
+ /*Sample size is not added automatically with non-ValueMetric::AVG aggregation types*/
+ metric.set_aggregation_type(ValueMetric::SUM);
+ sp<NumericValueMetricProducer> valueProducerSum =
+ NumericValueMetricProducerTestHelper::createValueProducerNoConditions(
+ pullerManager, metric, /*pullAtomId=*/-1);
+
+ /*Sample size is added when include_sample_size bool is set to true*/
+ metric.set_include_sample_size(true);
+ sp<NumericValueMetricProducer> valueProducerSumWithSampleSize =
+ NumericValueMetricProducerTestHelper::createValueProducerNoConditions(
+ pullerManager, metric, /*pullAtomId=*/-1);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
+ CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
+ CreateRepeatedValueLogEvent(&event3, tagId, bucketStartTimeNs + 20, 20);
+ valueProducerAvg->onMatchedLogEvent(1 /*log matcher index*/, event1);
+ valueProducerAvg->onMatchedLogEvent(1 /*log matcher index*/, event2);
+ valueProducerSum->onMatchedLogEvent(1 /*log matcher index*/, event1);
+ valueProducerSum->onMatchedLogEvent(1 /*log matcher index*/, event2);
+ valueProducerSum->onMatchedLogEvent(1 /*log matcher index*/, event3);
+ valueProducerSumWithSampleSize->onMatchedLogEvent(1 /*log matcher index*/, event1);
+ valueProducerSumWithSampleSize->onMatchedLogEvent(1 /*log matcher index*/, event2);
+ valueProducerSumWithSampleSize->onMatchedLogEvent(1 /*log matcher index*/, event3);
+
+ NumericValueMetricProducer::Interval curInterval;
+ ASSERT_EQ(1UL, valueProducerAvg->mCurrentSlicedBucket.size());
+ curInterval = valueProducerAvg->mCurrentSlicedBucket.begin()->second.intervals[0];
+ EXPECT_EQ(2, curInterval.sampleSize);
+ ASSERT_EQ(1UL, valueProducerSum->mCurrentSlicedBucket.size());
+ curInterval = valueProducerSum->mCurrentSlicedBucket.begin()->second.intervals[0];
+ EXPECT_EQ(3, curInterval.sampleSize);
+ ASSERT_EQ(1UL, valueProducerSumWithSampleSize->mCurrentSlicedBucket.size());
+ curInterval = valueProducerSumWithSampleSize->mCurrentSlicedBucket.begin()->second.intervals[0];
+ EXPECT_EQ(3, curInterval.sampleSize);
+
+ valueProducerAvg->flushIfNeededLocked(bucket2StartTimeNs);
+ valueProducerSum->flushIfNeededLocked(bucket2StartTimeNs);
+ valueProducerSumWithSampleSize->flushIfNeededLocked(bucket2StartTimeNs);
+
+ // Start dump report and check output.
+ ProtoOutputStream outputAvg;
+ std::set<string> strSetAvg;
+ valueProducerAvg->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
+ true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
+ &strSetAvg, &outputAvg);
+
+ StatsLogReport reportAvg = outputStreamToProto(&outputAvg);
+ ASSERT_EQ(1, reportAvg.value_metrics().data_size());
+
+ ValueMetricData data = reportAvg.value_metrics().data(0);
+ ASSERT_EQ(1, data.bucket_info_size());
+ ASSERT_EQ(1, data.bucket_info(0).values_size());
+ EXPECT_EQ(2, data.bucket_info(0).values(0).sample_size());
+ EXPECT_TRUE(std::abs(data.bucket_info(0).values(0).value_double() - 12.5) < epsilon);
+
+ // Start dump report and check output.
+ ProtoOutputStream outputSum;
+ std::set<string> strSetSum;
+ valueProducerSum->onDumpReport(bucket2StartTimeNs + 50 * NS_PER_SEC,
+ true /* include recent buckets */, true, NO_TIME_CONSTRAINTS,
+ &strSetSum, &outputSum);
+
+ StatsLogReport reportSum = outputStreamToProto(&outputSum);
+ ASSERT_EQ(1, reportSum.value_metrics().data_size());
+
+ data = reportSum.value_metrics().data(0);
+ ASSERT_EQ(1, data.bucket_info_size());
+ ASSERT_EQ(1, data.bucket_info(0).values_size());
+ EXPECT_EQ(45, data.bucket_info(0).values(0).value_long());
+ EXPECT_FALSE(data.bucket_info(0).values(0).has_sample_size());
+
+ // Start dump report and check output.
+ ProtoOutputStream outputSumWithSampleSize;
+ std::set<string> strSetSumWithSampleSize;
+ valueProducerSumWithSampleSize->onDumpReport(
+ bucket2StartTimeNs + 50 * NS_PER_SEC, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSetSumWithSampleSize, &outputSumWithSampleSize);
+
+ StatsLogReport reportSumWithSampleSize = outputStreamToProto(&outputSumWithSampleSize);
+ ASSERT_EQ(1, reportSumWithSampleSize.value_metrics().data_size());
+
+ data = reportSumWithSampleSize.value_metrics().data(0);
+ ASSERT_EQ(1, data.bucket_info_size());
+ ASSERT_EQ(1, data.bucket_info(0).values_size());
+ EXPECT_EQ(3, data.bucket_info(0).values(0).sample_size());
+ EXPECT_EQ(45, data.bucket_info(0).values(0).value_long());
+}
+
+TEST(NumericValueMetricProducerTest, TestDimensionalSampling) {
+ ShardOffsetProvider::getInstance().setShardOffset(5);
+
+ int shardCount = 2;
+ ValueMetric sampledValueMetric = NumericValueMetricProducerTestHelper::createMetric();
+ *sampledValueMetric.mutable_dimensions_in_what() = CreateDimensions(tagId, {1 /*uid*/});
+ *sampledValueMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(tagId, {1 /*uid*/});
+ sampledValueMetric.mutable_dimensional_sampling_info()->set_shard_count(shardCount);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ // First field is a dimension field and sampled what field.
+ // Second field is the value field.
+ // NumericValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 1, 1001, 5, 10));
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 1, 1002, 10, 10));
+ data->push_back(makeUidLogEvent(tagId, bucketStartTimeNs + 1, 1003, 15, 10));
+ return true;
+ }))
+ // Dump report pull.
+ .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(
+ makeUidLogEvent(tagId, bucketStartTimeNs + 10000000000, 1001, 6, 10));
+ data->push_back(
+ makeUidLogEvent(tagId, bucketStartTimeNs + 10000000000, 1002, 12, 10));
+ data->push_back(
+ makeUidLogEvent(tagId, bucketStartTimeNs + 10000000000, 1003, 18, 10));
+ return true;
+ }));
+
+ sp<NumericValueMetricProducer> valueProducer =
+ NumericValueMetricProducerTestHelper::createValueProducerWithSampling(
+ pullerManager, sampledValueMetric);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000;
+ valueProducer->onDumpReport(dumpReportTimeNs, true /* include current buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ backfillDimensionPath(&report);
+ backfillStartEndTimestamp(&report);
+ EXPECT_TRUE(report.has_value_metrics());
+ StatsLogReport::ValueMetricDataWrapper valueMetrics;
+ sortMetricDataByDimensionsValue(report.value_metrics(), &valueMetrics);
+ ASSERT_EQ(2, valueMetrics.data_size());
+ EXPECT_EQ(0, report.value_metrics().skipped_size());
+
+ // Only Uid 1, 3, 4 are logged. (odd hash value) + (offset of 5) % (shard count of 2) = 0
+ ValueMetricData data = valueMetrics.data(0);
+ ValidateUidDimension(data.dimensions_in_what(), tagId, 1001);
+ ASSERT_EQ(1, data.bucket_info_size());
+ ValidateValueBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + 10000000000,
+ {1}, -1,
+ 0); // Diff of 5 and 6
+
+ data = valueMetrics.data(1);
+ ValidateUidDimension(data.dimensions_in_what(), tagId, 1003);
+ ASSERT_EQ(1, data.bucket_info_size());
+ ValidateValueBucket(data.bucket_info(0), bucketStartTimeNs, bucketStartTimeNs + 10000000000,
+ {3}, -1,
+ 0); // Diff of 15 and 18
+}
+
} // namespace statsd
} // namespace os
} // namespace android
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 16180c06..e083cab2 100644
--- a/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -25,7 +25,6 @@
#include "src/condition/CombinationConditionTracker.h"
#include "src/condition/SimpleConditionTracker.h"
-#include "src/flags/FlagProvider.h"
#include "src/matchers/CombinationAtomMatchingTracker.h"
#include "src/metrics/DurationMetricProducer.h"
#include "src/metrics/GaugeMetricProducer.h"
@@ -83,14 +82,16 @@ map<int64_t, uint64_t> oldStateHashes;
set<int64_t> noReportMetricIds;
bool initConfig(const StatsdConfig& config) {
- return initStatsdConfig(
- key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseNs, timeBaseNs, allTagIdsToMatchersMap, oldAtomMatchingTrackers,
- oldAtomMatchingTrackerMap, oldConditionTrackers, oldConditionTrackerMap,
- oldMetricProducers, oldMetricProducerMap, oldAnomalyTrackers, oldAlarmTrackers,
- tmpConditionToMetricMap, tmpTrackerToMetricMap, tmpTrackerToConditionMap,
- tmpActivationAtomTrackerToMetricMap, tmpDeactivationAtomTrackerToMetricMap,
- oldAlertTrackerMap, metricsWithActivation, oldStateHashes, noReportMetricIds);
+ // initStatsdConfig returns nullopt if config is valid
+ return !initStatsdConfig(
+ key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseNs, timeBaseNs, allTagIdsToMatchersMap, oldAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, oldConditionTrackers, oldConditionTrackerMap,
+ oldMetricProducers, oldMetricProducerMap, oldAnomalyTrackers, oldAlarmTrackers,
+ tmpConditionToMetricMap, tmpTrackerToMetricMap, tmpTrackerToConditionMap,
+ tmpActivationAtomTrackerToMetricMap, tmpDeactivationAtomTrackerToMetricMap,
+ oldAlertTrackerMap, metricsWithActivation, oldStateHashes, noReportMetricIds)
+ .has_value();
}
vector<int> filterMatcherIndexesById(const vector<sp<AtomMatchingTracker>>& atomMatchingTrackers,
@@ -132,11 +133,6 @@ public:
oldStateHashes.clear();
noReportMetricIds.clear();
StateManager::getInstance().clear();
- FlagProvider::getInstance().overrideFuncs(&isAtLeastSFuncTrue, &getServerFlagFuncTrue);
- }
-
- void TearDown() override {
- FlagProvider::getInstance().resetOverrides();
}
};
@@ -153,9 +149,10 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
newAtomMatchingTrackerMap[matcherId] = 0;
- EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker));
+ EXPECT_EQ(determineMatcherUpdateStatus(config, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
}
@@ -177,9 +174,10 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) {
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
newAtomMatchingTrackerMap[matcherId] = 0;
- EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker));
+ EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
}
@@ -201,9 +199,10 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherNew) {
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
newAtomMatchingTrackerMap[matcherId] = 0;
- EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker));
+ EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(matchersToUpdate[0], UPDATE_NEW);
}
@@ -241,9 +240,10 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) {
vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination. It should recurse the two child matchers and preserve all 3.
- EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker));
+ EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE);
EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE);
@@ -285,9 +285,10 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) {
vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination. The simple matchers should not be evaluated.
- EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker));
+ EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN);
EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN);
@@ -329,9 +330,10 @@ TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) {
vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination.
- EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
- matchersToUpdate, cycleTracker));
+ EXPECT_EQ(determineMatcherUpdateStatus(newConfig, 1, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker),
+ nullopt);
// Matcher 2 and matcher3 must be reevaluated. Matcher 1 might, but does not need to be.
EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
@@ -402,9 +404,11 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
set<int64_t> replacedMatchers;
- EXPECT_TRUE(updateAtomMatchingTrackers(
- newConfig, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newTagIds,
- newAtomMatchingTrackerMap, newAtomMatchingTrackers, replacedMatchers));
+ EXPECT_EQ(updateAtomMatchingTrackers(newConfig, uidMap, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newTagIds,
+ newAtomMatchingTrackerMap, newAtomMatchingTrackers,
+ replacedMatchers),
+ nullopt);
ASSERT_EQ(newTagIds.size(), 3);
EXPECT_EQ(newTagIds.count(10), 1);
@@ -507,9 +511,10 @@ TEST_F(ConfigUpdateTest, TestSimpleConditionPreserve) {
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newConditionTrackerMap;
newConditionTrackerMap[predicate.id()] = 0;
- EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
}
@@ -533,9 +538,10 @@ TEST_F(ConfigUpdateTest, TestSimpleConditionReplace) {
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newConditionTrackerMap;
newConditionTrackerMap[predicate.id()] = 0;
- EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
}
@@ -560,9 +566,10 @@ TEST_F(ConfigUpdateTest, TestSimpleConditionDepsChange) {
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newConditionTrackerMap;
newConditionTrackerMap[predicate.id()] = 0;
- EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
}
@@ -602,9 +609,10 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionPreserve) {
vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination. It should recurse the two child predicates and preserve all 3.
- EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
EXPECT_EQ(conditionsToUpdate[1], UPDATE_PRESERVE);
EXPECT_EQ(conditionsToUpdate[2], UPDATE_PRESERVE);
@@ -648,9 +656,10 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionReplace) {
vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination. The simple conditions should not be evaluated.
- EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
EXPECT_EQ(conditionsToUpdate[1], UPDATE_UNKNOWN);
EXPECT_EQ(conditionsToUpdate[2], UPDATE_UNKNOWN);
@@ -693,9 +702,10 @@ TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) {
vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination. Simple2 and combination1 must be evaluated.
- EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
- oldConditionTrackers, newConditionTrackerMap,
- replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker),
+ nullopt);
EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
EXPECT_EQ(conditionsToUpdate[1], UPDATE_REPLACE);
}
@@ -830,10 +840,11 @@ TEST_F(ConfigUpdateTest, TestUpdateConditions) {
unordered_map<int, vector<int>> trackerToConditionMap;
vector<ConditionState> conditionCache;
set<int64_t> replacedConditions;
- EXPECT_TRUE(updateConditions(key, newConfig, newAtomMatchingTrackerMap, replacedMatchers,
- oldConditionTrackerMap, oldConditionTrackers,
- newConditionTrackerMap, newConditionTrackers,
- trackerToConditionMap, conditionCache, replacedConditions));
+ EXPECT_EQ(updateConditions(key, newConfig, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
+ newConditionTrackers, trackerToConditionMap, conditionCache,
+ replacedConditions),
+ nullopt);
unordered_map<int64_t, int> expectedConditionTrackerMap = {
{simple1Id, simple1Index}, {simple2Id, simple2Index},
@@ -964,8 +975,9 @@ TEST_F(ConfigUpdateTest, TestUpdateStates) {
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
map<int64_t, uint64_t> newStateProtoHashes;
set<int64_t> replacedStates;
- EXPECT_TRUE(updateStates(newConfig, oldStateHashes, stateAtomIdMap, allStateGroupMaps,
- newStateProtoHashes, replacedStates));
+ EXPECT_EQ(updateStates(newConfig, oldStateHashes, stateAtomIdMap, allStateGroupMaps,
+ newStateProtoHashes, replacedStates),
+ nullopt);
EXPECT_THAT(replacedStates, ContainerEq(set({state1Id, state3Id})));
unordered_map<int64_t, int> expectedStateAtomIdMap = {
@@ -1003,10 +1015,11 @@ TEST_F(ConfigUpdateTest, TestEventMetricPreserve) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
}
@@ -1039,10 +1052,11 @@ TEST_F(ConfigUpdateTest, TestEventMetricActivationAdded) {
unordered_map<int64_t, int> metricToActivationMap = {{12345, 0}};
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1068,10 +1082,11 @@ TEST_F(ConfigUpdateTest, TestEventMetricWhatChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1097,10 +1112,11 @@ TEST_F(ConfigUpdateTest, TestEventMetricConditionChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1133,10 +1149,11 @@ TEST_F(ConfigUpdateTest, TestMetricConditionLinkDepsChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{linkPredicate.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{linkPredicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1168,10 +1185,11 @@ TEST_F(ConfigUpdateTest, TestEventMetricActivationDepsChange) {
unordered_map<int64_t, int> metricToActivationMap = {{12345, 0}};
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {startMatcher.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {startMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1201,10 +1219,11 @@ TEST_F(ConfigUpdateTest, TestCountMetricPreserve) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
}
@@ -1234,10 +1253,11 @@ TEST_F(ConfigUpdateTest, TestCountMetricDefinitionChange) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1264,10 +1284,11 @@ TEST_F(ConfigUpdateTest, TestCountMetricWhatChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1294,10 +1315,11 @@ TEST_F(ConfigUpdateTest, TestCountMetricConditionChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1324,10 +1346,11 @@ TEST_F(ConfigUpdateTest, TestCountMetricStateChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{sliceState.id()}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{sliceState.id()}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1350,10 +1373,11 @@ TEST_F(ConfigUpdateTest, TestGaugeMetricPreserve) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
}
@@ -1372,10 +1396,11 @@ TEST_F(ConfigUpdateTest, TestGaugeMetricDefinitionChange) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1391,10 +1416,11 @@ TEST_F(ConfigUpdateTest, TestGaugeMetricWhatChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1417,10 +1443,11 @@ TEST_F(ConfigUpdateTest, TestGaugeMetricConditionChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1438,10 +1465,11 @@ TEST_F(ConfigUpdateTest, TestGaugeMetricTriggerEventChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {triggerEvent.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {triggerEvent.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1466,10 +1494,11 @@ TEST_F(ConfigUpdateTest, TestDurationMetricPreserve) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
}
@@ -1490,10 +1519,11 @@ TEST_F(ConfigUpdateTest, TestDurationMetricDefinitionChange) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap, /*replacedMatchers*/ {},
- /*replacedConditions=*/{}, /*replacedStates=*/{},
- metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap, /*replacedMatchers*/ {},
+ /*replacedConditions=*/{}, /*replacedStates=*/{},
+ metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1512,10 +1542,11 @@ TEST_F(ConfigUpdateTest, TestDurationMetricWhatChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{what.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{what.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1536,10 +1567,11 @@ TEST_F(ConfigUpdateTest, TestDurationMetricConditionChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{condition.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{condition.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1562,10 +1594,11 @@ TEST_F(ConfigUpdateTest, TestDurationMetricStateChange) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{sliceState.id()}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{sliceState.id()}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1589,10 +1622,11 @@ TEST_F(ConfigUpdateTest, TestValueMetricPreserve) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
}
@@ -1609,10 +1643,11 @@ TEST_F(ConfigUpdateTest, TestValueMetricDefinitionChange) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1626,10 +1661,11 @@ TEST_F(ConfigUpdateTest, TestValueMetricWhatChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1650,10 +1686,11 @@ TEST_F(ConfigUpdateTest, TestValueMetricConditionChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1671,10 +1708,11 @@ TEST_F(ConfigUpdateTest, TestValueMetricStateChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{sliceState.id()}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{sliceState.id()}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1696,10 +1734,11 @@ TEST_F(ConfigUpdateTest, TestKllMetricPreserve) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate{UPDATE_UNKNOWN};
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
}
@@ -1717,10 +1756,11 @@ TEST_F(ConfigUpdateTest, TestKllMetricDefinitionChange) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate{UPDATE_UNKNOWN};
- EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
- metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+ metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1734,10 +1774,11 @@ TEST_F(ConfigUpdateTest, TestKllMetricWhatChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate{UPDATE_UNKNOWN};
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1759,10 +1800,11 @@ TEST_F(ConfigUpdateTest, TestKllMetricConditionChanged) {
unordered_map<int64_t, int> metricToActivationMap;
vector<UpdateStatus> metricsToUpdate{UPDATE_UNKNOWN};
- EXPECT_TRUE(determineAllMetricUpdateStatuses(
- config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
- /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
- /*replacedStates=*/{}, metricsToUpdate));
+ EXPECT_EQ(determineAllMetricUpdateStatuses(
+ config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+ /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+ /*replacedStates=*/{}, metricsToUpdate),
+ nullopt);
EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
}
@@ -1915,15 +1957,17 @@ TEST_F(ConfigUpdateTest, TestUpdateEventMetrics) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
- newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
- newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
- /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
- newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, replacedConditions, newConditionTrackers,
+ conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{event1Id, event1Index}, {event2Id, event2Index}, {event3Id, event3Index},
@@ -2133,7 +2177,7 @@ TEST_F(ConfigUpdateTest, TestUpdateCountMetrics) {
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
map<int64_t, uint64_t> stateProtoHashes;
- EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes));
+ EXPECT_EQ(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes), nullopt);
EXPECT_EQ(stateAtomIdMap[state2Id], util::BATTERY_SAVER_MODE_STATE_CHANGED);
// Output data structures to validate.
@@ -2146,15 +2190,17 @@ TEST_F(ConfigUpdateTest, TestUpdateCountMetrics) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
- newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{},
- newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
- oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers,
- conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, /*replacedConditions=*/{}, newConditionTrackers,
+ conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
+ oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap,
+ noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{count1Id, count1Index}, {count2Id, count2Index}, {count3Id, count3Index},
@@ -2357,15 +2403,17 @@ TEST_F(ConfigUpdateTest, TestUpdateGaugeMetrics) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
- newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{},
- newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
- /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
- newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, /*replacedConditions=*/{}, newConditionTrackers,
+ conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{gauge1Id, gauge1Index}, {gauge2Id, gauge2Index}, {gauge3Id, gauge3Index},
@@ -2630,16 +2678,18 @@ TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) {
vector<Predicate> conditionProtos(5);
reverse_copy(config.predicate().begin(), config.predicate().end(), conditionProtos.begin());
for (int i = 0; i < newConditionTrackers.size(); i++) {
- EXPECT_TRUE(newConditionTrackers[i]->onConfigUpdated(
- conditionProtos, i, newConditionTrackers, newAtomMatchingTrackerMap,
- newConditionTrackerMap));
+ EXPECT_EQ(newConditionTrackers[i]->onConfigUpdated(conditionProtos, i, newConditionTrackers,
+ newAtomMatchingTrackerMap,
+ newConditionTrackerMap),
+ nullopt);
}
vector<bool> cycleTracker(5, false);
fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated);
for (int i = 0; i < newConditionTrackers.size(); i++) {
- EXPECT_TRUE(newConditionTrackers[i]->init(conditionProtos, newConditionTrackers,
- newConditionTrackerMap, cycleTracker,
- conditionCache));
+ EXPECT_EQ(
+ newConditionTrackers[i]->init(conditionProtos, newConditionTrackers,
+ newConditionTrackerMap, cycleTracker, conditionCache),
+ nullopt);
}
// Predicate5 should be true since 2 uids have wakelocks
EXPECT_EQ(conditionCache, vector({kTrue, kFalse, kUnknown, kUnknown, kUnknown}));
@@ -2664,7 +2714,7 @@ TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) {
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
map<int64_t, uint64_t> stateProtoHashes;
- EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes));
+ EXPECT_EQ(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes), nullopt);
// Output data structures to validate.
unordered_map<int64_t, int> newMetricProducerMap;
@@ -2676,15 +2726,17 @@ TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
- newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
- newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
- oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers,
- conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
+ newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+ newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps,
+ replacedStates, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{duration1Id, duration1Index}, {duration2Id, duration2Index},
@@ -2930,7 +2982,7 @@ TEST_F(ConfigUpdateTest, TestUpdateValueMetrics) {
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
map<int64_t, uint64_t> stateProtoHashes;
- EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes));
+ EXPECT_EQ(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes), nullopt);
// Output data structures to validate.
unordered_map<int64_t, int> newMetricProducerMap;
@@ -2942,15 +2994,17 @@ TEST_F(ConfigUpdateTest, TestUpdateValueMetrics) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
- newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
- newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
- oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers,
- conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
+ newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+ newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps,
+ replacedStates, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{value1Id, value1Index}, {value2Id, value2Index}, {value3Id, value3Index},
@@ -3157,15 +3211,17 @@ TEST_F(ConfigUpdateTest, TestUpdateKllMetrics) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
- newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
- newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
- /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
- newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(
+ key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, /*replacedMatchers=*/{}, newAtomMatchingTrackers,
+ newConditionTrackerMap, replacedConditions, newConditionTrackers,
+ conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{kll1Id, kll1Index}, {kll2Id, kll2Index}, {kll3Id, kll3Index},
@@ -3328,15 +3384,17 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
- newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
- newConditionTrackers, conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
- /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
- newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, replacedConditions, newConditionTrackers,
+ conditionCache, /*stateAtomIdMap=*/{}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
// Verify event activation/deactivation maps.
ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 3);
@@ -3488,15 +3546,17 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
- EXPECT_TRUE(updateMetrics(
- key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
- newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{},
- newConditionTrackers, conditionCache, /*stateAtomIdMap*/ {}, /*allStateGroupMaps=*/{},
- /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
- newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, /*replacedConditions=*/{}, newConditionTrackers,
+ conditionCache, /*stateAtomIdMap*/ {}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ nullopt);
unordered_map<int64_t, int> expectedMetricProducerMap = {
{countMetricId, countMetricIndex}, {durationMetricId, durationMetricIndex},
@@ -3581,8 +3641,9 @@ TEST_F(ConfigUpdateTest, TestAlertPreserve) {
EXPECT_TRUE(initConfig(config));
UpdateStatus updateStatus = UPDATE_UNKNOWN;
- EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
- /*replacedMetrics*/ {}, updateStatus));
+ EXPECT_EQ(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+ /*replacedMetrics*/ {}, updateStatus),
+ nullopt);
EXPECT_EQ(updateStatus, UPDATE_PRESERVE);
}
@@ -3599,8 +3660,9 @@ TEST_F(ConfigUpdateTest, TestAlertMetricChanged) {
EXPECT_TRUE(initConfig(config));
UpdateStatus updateStatus = UPDATE_UNKNOWN;
- EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
- /*replacedMetrics*/ {metric.id()}, updateStatus));
+ EXPECT_EQ(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+ /*replacedMetrics*/ {metric.id()}, updateStatus),
+ nullopt);
EXPECT_EQ(updateStatus, UPDATE_REPLACE);
}
@@ -3618,8 +3680,9 @@ TEST_F(ConfigUpdateTest, TestAlertDefinitionChanged) {
alert.set_num_buckets(2);
UpdateStatus updateStatus = UPDATE_UNKNOWN;
- EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
- /*replacedMetrics*/ {}, updateStatus));
+ EXPECT_EQ(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+ /*replacedMetrics*/ {}, updateStatus),
+ nullopt);
EXPECT_EQ(updateStatus, UPDATE_REPLACE);
}
@@ -3714,24 +3777,26 @@ TEST_F(ConfigUpdateTest, TestUpdateAlerts) {
vector<int> metricsWithActivation;
set<int64_t> replacedMetrics;
int64_t currentTimeNs = 12345;
- EXPECT_TRUE(updateMetrics(
- key, config, /*timeBaseNs=*/123, currentTimeNs, new StatsPullerManager(),
- oldAtomMatchingTrackerMap, oldAtomMatchingTrackerMap, /*replacedMatchers*/ {},
- oldAtomMatchingTrackers, oldConditionTrackerMap, /*replacedConditions=*/{},
- oldConditionTrackers, {ConditionState::kUnknown}, /*stateAtomIdMap*/ {},
- /*allStateGroupMaps=*/{},
- /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
- newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, replacedMetrics));
+ EXPECT_EQ(updateMetrics(
+ key, config, /*timeBaseNs=*/123, currentTimeNs, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, oldAtomMatchingTrackerMap, /*replacedMatchers*/ {},
+ oldAtomMatchingTrackers, oldConditionTrackerMap, /*replacedConditions=*/{},
+ oldConditionTrackers, {ConditionState::kUnknown}, /*stateAtomIdMap*/ {},
+ /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, replacedMetrics),
+ nullopt);
EXPECT_EQ(replacedMetrics, set<int64_t>({countMetricId}));
unordered_map<int64_t, int> newAlertTrackerMap;
vector<sp<AnomalyTracker>> newAnomalyTrackers;
- EXPECT_TRUE(updateAlerts(config, currentTimeNs, newMetricProducerMap, replacedMetrics,
- oldAlertTrackerMap, oldAnomalyTrackers, anomalyAlarmMonitor,
- newMetricProducers, newAlertTrackerMap, newAnomalyTrackers));
+ EXPECT_EQ(updateAlerts(config, currentTimeNs, newMetricProducerMap, replacedMetrics,
+ oldAlertTrackerMap, oldAnomalyTrackers, anomalyAlarmMonitor,
+ newMetricProducers, newAlertTrackerMap, newAnomalyTrackers),
+ nullopt);
unordered_map<int64_t, int> expectedAlertMap = {
{alert1Id, alert1Index},
@@ -3826,8 +3891,9 @@ TEST_F(ConfigUpdateTest, TestUpdateAlarms) {
// Update time is 2 seconds after the base time.
int64_t currentTimeNs = timeBaseNs + 2 * NS_PER_SEC;
vector<sp<AlarmTracker>> newAlarmTrackers;
- EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
- newAlarmTrackers));
+ EXPECT_EQ(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ newAlarmTrackers),
+ nullopt);
ASSERT_EQ(newAlarmTrackers.size(), 3);
// Config is updated 2 seconds after statsd start
@@ -3857,8 +3923,9 @@ TEST_F(ConfigUpdateTest, TestUpdateAlarms) {
// Do another update 60 seconds after config creation time, after the offsets of each alarm.
currentTimeNs = timeBaseNs + 60 * NS_PER_SEC;
newAlarmTrackers.clear();
- EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
- newAlarmTrackers));
+ EXPECT_EQ(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ newAlarmTrackers),
+ nullopt);
ASSERT_EQ(newAlarmTrackers.size(), 3);
// Config is updated one minute after statsd start.
@@ -3868,6 +3935,175 @@ TEST_F(ConfigUpdateTest, TestUpdateAlarms) {
EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10 + 10000);
}
+TEST_F(ConfigUpdateTest, TestMetricHasMultipleActivations) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ auto metric_activation1 = config.add_metric_activation();
+ metric_activation1->set_metric_id(metricId);
+ metric_activation1->set_activation_type(ACTIVATE_IMMEDIATELY);
+ EXPECT_TRUE(initConfig(config));
+
+ auto metric_activation2 = config.add_metric_activation();
+ metric_activation2->set_metric_id(metricId);
+ metric_activation2->set_activation_type(ACTIVATE_IMMEDIATELY);
+
+ unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ unordered_map<int64_t, int> newMetricProducerMap;
+ unordered_map<int64_t, int> stateAtomIdMap;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ vector<int> metricsWithActivation;
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ vector<sp<MetricProducer>> newMetricProducers;
+ vector<ConditionState> conditionCache;
+ set<int64_t> replacedMetrics;
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ set<int64_t> replacedStates;
+ EXPECT_EQ(updateMetrics(key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, replacedConditions, newConditionTrackers,
+ conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
+ oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap,
+ noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS, metricId));
+}
+
+TEST_F(ConfigUpdateTest, TestNoReportMetricNotFound) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ config.add_no_report_metric(metricId);
+
+ unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ unordered_map<int64_t, int> newMetricProducerMap;
+ unordered_map<int64_t, int> stateAtomIdMap;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ vector<int> metricsWithActivation;
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ vector<sp<MetricProducer>> newMetricProducers;
+ vector<ConditionState> conditionCache;
+ set<int64_t> replacedMetrics;
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ set<int64_t> replacedStates;
+ EXPECT_EQ(updateMetrics(key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, replacedMatchers, newAtomMatchingTrackers,
+ newConditionTrackerMap, replacedConditions, newConditionTrackers,
+ conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
+ oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap,
+ noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ replacedMetrics),
+ InvalidConfigReason(INVALID_CONFIG_REASON_NO_REPORT_METRIC_NOT_FOUND, metricId));
+}
+
+TEST_F(ConfigUpdateTest, TestMetricSlicedStateAtomAllowedFromAnyUid) {
+ StatsdConfig config;
+ CountMetric* metric = config.add_count_metric();
+ *metric = createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_state() = CreateScreenState();
+ metric->add_slice_by_state(StringToId("ScreenState"));
+ EXPECT_TRUE(initConfig(config));
+
+ config.add_whitelisted_atom_ids(util::SCREEN_STATE_CHANGED);
+
+ unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ unordered_map<int64_t, int> newMetricProducerMap;
+ unordered_map<int64_t, int> stateAtomIdMap;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ vector<int> metricsWithActivation;
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ vector<sp<MetricProducer>> newMetricProducers;
+ vector<ConditionState> conditionCache;
+ set<int64_t> replacedMetrics;
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ set<int64_t> replacedStates;
+
+ newAtomMatchingTrackerMap[StringToId("ScreenTurnedOn")] = 0;
+ stateAtomIdMap[StringToId("ScreenState")] = util::SCREEN_STATE_CHANGED;
+ EXPECT_EQ(
+ updateMetrics(
+ key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345,
+ new StatsPullerManager(), oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap,
+ replacedMatchers, newAtomMatchingTrackers, newConditionTrackerMap,
+ replacedConditions, newConditionTrackers, conditionCache, stateAtomIdMap,
+ allStateGroupMaps, replacedStates, oldMetricProducerMap, oldMetricProducers,
+ newMetricProducerMap, newMetricProducers, conditionToMetricMap,
+ trackerToMetricMap, noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, replacedMetrics),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
+ StringToId("Count")));
+}
+
+TEST_F(ConfigUpdateTest, TestMatcherDuplicate) {
+ StatsdConfig config;
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ EXPECT_TRUE(initConfig(config));
+
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ unordered_map<int, vector<int>> newTagIds;
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
+ set<int64_t> replacedMatchers;
+ EXPECT_EQ(updateAtomMatchingTrackers(
+ config, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newTagIds,
+ newAtomMatchingTrackerMap, newAtomMatchingTrackers, replacedMatchers),
+ createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
+ StringToId("ScreenTurnedOn")));
+}
+
+TEST_F(ConfigUpdateTest, TestConditionDuplicate) {
+ StatsdConfig config;
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+ EXPECT_TRUE(initConfig(config));
+
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int, vector<int>> trackerToConditionMap;
+ vector<ConditionState> conditionCache;
+ set<int64_t> replacedConditions;
+ set<int64_t> replacedMatchers;
+ EXPECT_EQ(updateConditions(key, config, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
+ newConditionTrackers, trackerToConditionMap, conditionCache,
+ replacedConditions),
+ createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
+ StringToId("ScreenIsOn")));
+}
+
} // namespace statsd
} // namespace os
} // namespace android
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 8aa7f469..a5732b30 100644
--- a/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
+++ b/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -51,9 +51,43 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
+const long timeBaseSec = 1000;
const long kAlertId = 3;
-const long timeBaseSec = 1000;
+sp<UidMap> uidMap = new UidMap();
+sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+sp<AlarmMonitor> anomalyAlarmMonitor;
+sp<AlarmMonitor> periodicAlarmMonitor;
+unordered_map<int, vector<int>> allTagIdsToMatchersMap;
+vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
+unordered_map<int64_t, int> atomMatchingTrackerMap;
+vector<sp<ConditionTracker>> allConditionTrackers;
+unordered_map<int64_t, int> conditionTrackerMap;
+vector<sp<MetricProducer>> allMetricProducers;
+unordered_map<int64_t, int> metricProducerMap;
+vector<sp<AnomalyTracker>> allAnomalyTrackers;
+unordered_map<int64_t, int> alertTrackerMap;
+vector<sp<AlarmTracker>> allAlarmTrackers;
+unordered_map<int, vector<int>> conditionToMetricMap;
+unordered_map<int, vector<int>> trackerToMetricMap;
+unordered_map<int, vector<int>> trackerToConditionMap;
+unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+vector<int> metricsWithActivation;
+map<int64_t, uint64_t> stateProtoHashes;
+set<int64_t> noReportMetricIds;
+
+optional<InvalidConfigReason> initConfig(const StatsdConfig& config) {
+ // initStatsdConfig returns nullopt if config is valid
+ return initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
+ atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
+ metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
+ trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds);
+}
StatsdConfig buildGoodConfig() {
StatsdConfig config;
@@ -63,7 +97,7 @@ StatsdConfig buildGoodConfig() {
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
@@ -73,7 +107,7 @@ StatsdConfig buildGoodConfig() {
eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
@@ -91,7 +125,7 @@ StatsdConfig buildGoodConfig() {
metric->set_id(3);
metric->set_what(StringToId("SCREEN_IS_ON"));
metric->set_bucket(ONE_MINUTE);
- metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+ metric->mutable_dimensions_in_what()->set_field(SCREEN_STATE_ATOM_ID);
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
config.add_no_report_metric(3);
@@ -113,7 +147,7 @@ StatsdConfig buildCircleMatchers() {
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
@@ -135,14 +169,13 @@ StatsdConfig buildAlertWithUnknownMetric() {
StatsdConfig config;
config.set_id(12345);
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
CountMetric* metric = config.add_count_metric();
metric->set_id(3);
- metric->set_what(StringToId("SCREEN_IS_ON"));
+ metric->set_what(StringToId("ScreenTurnedOn"));
metric->set_bucket(ONE_MINUTE);
- metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+ metric->mutable_dimensions_in_what()->set_field(SCREEN_STATE_ATOM_ID);
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
auto alert = config.add_alert();
@@ -162,7 +195,7 @@ StatsdConfig buildMissingMatchers() {
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
@@ -246,7 +279,7 @@ StatsdConfig buildCirclePredicates() {
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
@@ -256,7 +289,7 @@ StatsdConfig buildCirclePredicates() {
eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
@@ -378,39 +411,34 @@ StatsdConfig buildConfigWithDifferentPredicates() {
}
} // anonymous namespace
-TEST(MetricsManagerTest, TestInitialConditions) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildConfigWithDifferentPredicates();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_TRUE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+class MetricsManagerUtilTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ allTagIdsToMatchersMap.clear();
+ allAtomMatchingTrackers.clear();
+ atomMatchingTrackerMap.clear();
+ allConditionTrackers.clear();
+ conditionTrackerMap.clear();
+ allMetricProducers.clear();
+ metricProducerMap.clear();
+ allAnomalyTrackers.clear();
+ allAlarmTrackers.clear();
+ conditionToMetricMap.clear();
+ trackerToMetricMap.clear();
+ trackerToConditionMap.clear();
+ activationAtomTrackerToMetricMap.clear();
+ deactivationAtomTrackerToMetricMap.clear();
+ alertTrackerMap.clear();
+ metricsWithActivation.clear();
+ stateProtoHashes.clear();
+ noReportMetricIds.clear();
+ StateManager::getInstance().clear();
+ }
+};
+
+TEST_F(MetricsManagerUtilTest, TestInitialConditions) {
+ // initConfig returns nullopt if config is valid
+ EXPECT_EQ(initConfig(buildConfigWithDifferentPredicates()), nullopt);
ASSERT_EQ(4u, allMetricProducers.size());
ASSERT_EQ(5u, allConditionTrackers.size());
@@ -431,44 +459,15 @@ TEST(MetricsManagerTest, TestInitialConditions) {
EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
EXPECT_EQ(allTagIdsToMatchersMap.size(), 3);
- EXPECT_EQ(allTagIdsToMatchersMap[util::SCREEN_STATE_CHANGED].size(), 2);
+ EXPECT_EQ(allTagIdsToMatchersMap[SCREEN_STATE_ATOM_ID].size(), 2);
EXPECT_EQ(allTagIdsToMatchersMap[util::PLUGGED_STATE_CHANGED].size(), 2);
EXPECT_EQ(allTagIdsToMatchersMap[util::SUBSYSTEM_SLEEP_STATE].size(), 1);
}
-TEST(MetricsManagerTest, TestGoodConfig) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
+TEST_F(MetricsManagerUtilTest, TestGoodConfig) {
StatsdConfig config = buildGoodConfig();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_TRUE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+ // initConfig returns nullopt if config is valid
+ EXPECT_EQ(initConfig(config), nullopt);
ASSERT_EQ(1u, allMetricProducers.size());
EXPECT_THAT(metricProducerMap, UnorderedElementsAre(Pair(config.count_metric(0).id(), 0)));
ASSERT_EQ(1u, allAnomalyTrackers.size());
@@ -478,247 +477,744 @@ TEST(MetricsManagerTest, TestGoodConfig) {
EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
}
-TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildDimensionMetricsWithMultiTags();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+TEST_F(MetricsManagerUtilTest, TestDimensionMetricsWithMultiTags) {
+ EXPECT_EQ(initConfig(buildDimensionMetricsWithMultiTags()),
+ createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_MATCHER_MORE_THAN_ONE_ATOM, /*metric id=*/3,
+ StringToId("BATTERY_LOW")));
}
-TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildCircleMatchers();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+TEST_F(MetricsManagerUtilTest, TestCircleLogMatcherDependency) {
+ optional<InvalidConfigReason> expectedInvalidConfigReason =
+ createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_CYCLE,
+ StringToId("SCREEN_ON_OR_OFF"));
+ expectedInvalidConfigReason->matcherIds.push_back(StringToId("SCREEN_ON_OR_OFF"));
+
+ EXPECT_EQ(initConfig(buildCircleMatchers()), expectedInvalidConfigReason);
}
-TEST(MetricsManagerTest, TestMissingMatchers) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildMissingMatchers();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
- EXPECT_FALSE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+TEST_F(MetricsManagerUtilTest, TestMissingMatchers) {
+ optional<InvalidConfigReason> expectedInvalidConfigReason =
+ createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_CHILD_NOT_FOUND,
+ StringToId("SCREEN_ON_OR_OFF"));
+ expectedInvalidConfigReason->matcherIds.push_back(StringToId("ABC"));
+
+ EXPECT_EQ(initConfig(buildMissingMatchers()), expectedInvalidConfigReason);
}
-TEST(MetricsManagerTest, TestMissingPredicate) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildMissingPredicate();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
- EXPECT_FALSE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+TEST_F(MetricsManagerUtilTest, TestMissingPredicate) {
+ EXPECT_EQ(
+ initConfig(buildMissingPredicate()),
+ createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_METRIC_CONDITION_NOT_FOUND,
+ /*metric id=*/3, StringToId("SOME_CONDITION")));
}
-TEST(MetricsManagerTest, TestCirclePredicateDependency) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildCirclePredicates();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+TEST_F(MetricsManagerUtilTest, TestCirclePredicateDependency) {
+ optional<InvalidConfigReason> expectedInvalidConfigReason =
+ createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_CYCLE,
+ StringToId("SCREEN_IS_EITHER_ON_OFF"));
+ expectedInvalidConfigReason->conditionIds.push_back(StringToId("SCREEN_IS_EITHER_ON_OFF"));
+
+ EXPECT_EQ(initConfig(buildCirclePredicates()), expectedInvalidConfigReason);
}
-TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
- sp<UidMap> uidMap = new UidMap();
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildAlertWithUnknownMetric();
- unordered_map<int, vector<int>> allTagIdsToMatchersMap;
- vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> atomMatchingTrackerMap;
- vector<sp<ConditionTracker>> allConditionTrackers;
- unordered_map<int64_t, int> conditionTrackerMap;
- vector<sp<MetricProducer>> allMetricProducers;
- unordered_map<int64_t, int> metricProducerMap;
- vector<sp<AnomalyTracker>> allAnomalyTrackers;
- vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, vector<int>> conditionToMetricMap;
- unordered_map<int, vector<int>> trackerToMetricMap;
- unordered_map<int, vector<int>> trackerToConditionMap;
- unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- map<int64_t, uint64_t> stateProtoHashes;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIdsToMatchersMap, allAtomMatchingTrackers,
- atomMatchingTrackerMap, allConditionTrackers, conditionTrackerMap, allMetricProducers,
- metricProducerMap, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- stateProtoHashes, noReportMetricIds));
+TEST_F(MetricsManagerUtilTest, TestAlertWithUnknownMetric) {
+ EXPECT_EQ(initConfig(buildAlertWithUnknownMetric()),
+ createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND,
+ /*metric id=*/2, /*matcher id=*/3));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricWithMultipleActivations) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ auto metric_activation1 = config.add_metric_activation();
+ metric_activation1->set_metric_id(metricId);
+ metric_activation1->set_activation_type(ACTIVATE_IMMEDIATELY);
+ auto metric_activation2 = config.add_metric_activation();
+ metric_activation2->set_metric_id(metricId);
+ metric_activation2->set_activation_type(ACTIVATE_IMMEDIATELY);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_HAS_MULTIPLE_ACTIVATIONS, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestCountMetricMissingIdOrWhat) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(metricId);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestCountMetricConditionlinkNoCondition) {
+ StatsdConfig config;
+ CountMetric* metric = config.add_count_metric();
+ *metric = createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ auto link = metric->add_links();
+ link->set_condition(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION,
+ StringToId("Count")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestDurationMetricMissingIdOrWhat) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ DurationMetric* metric = config.add_duration_metric();
+ metric->set_id(metricId);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestDurationMetricConditionlinkNoCondition) {
+ StatsdConfig config;
+ DurationMetric* metric = config.add_duration_metric();
+ *metric = createDurationMetric(/*name=*/"Duration", /*what=*/StringToId("ScreenIsOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+
+ auto link = metric->add_links();
+ link->set_condition(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION,
+ StringToId("Duration")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestGaugeMetricMissingIdOrWhat) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ GaugeMetric* metric = config.add_gauge_metric();
+ metric->set_id(metricId);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestGaugeMetricConditionlinkNoCondition) {
+ StatsdConfig config;
+ GaugeMetric* metric = config.add_gauge_metric();
+ *metric = createGaugeMetric(/*name=*/"Gauge", /*what=*/StringToId("ScreenTurnedOn"),
+ /*samplingType=*/GaugeMetric_SamplingType_FIRST_N_SAMPLES,
+ /*condition=*/nullopt, /*triggerEvent=*/nullopt);
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ auto link = metric->add_links();
+ link->set_condition(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION,
+ StringToId("Gauge")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestEventMetricMissingIdOrWhat) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ EventMetric* metric = config.add_event_metric();
+ metric->set_id(metricId);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestEventMetricConditionlinkNoCondition) {
+ StatsdConfig config;
+ EventMetric* metric = config.add_event_metric();
+ *metric = createEventMetric(/*name=*/"Event", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt);
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ auto link = metric->add_links();
+ link->set_condition(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION,
+ StringToId("Event")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestNumericValueMetricMissingIdOrWhat) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ ValueMetric* metric = config.add_value_metric();
+ metric->set_id(metricId);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestNumericValueMetricConditionlinkNoCondition) {
+ StatsdConfig config;
+ ValueMetric* metric = config.add_value_metric();
+ *metric = createValueMetric(/*name=*/"NumericValue", /*what=*/CreateScreenTurnedOnAtomMatcher(),
+ /*valueField=*/2, /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ auto link = metric->add_links();
+ link->set_condition(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION,
+ StringToId("NumericValue")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestKllMetricMissingIdOrWhat) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ KllMetric* metric = config.add_kll_metric();
+ metric->set_id(metricId);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_MISSING_ID_OR_WHAT, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestKllMetricConditionlinkNoCondition) {
+ StatsdConfig config;
+ KllMetric* metric = config.add_kll_metric();
+ *metric = createKllMetric(/*name=*/"Kll", /*what=*/CreateScreenTurnedOnAtomMatcher(),
+ /*valueField=*/2, /*condition=*/nullopt);
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ auto link = metric->add_links();
+ link->set_condition(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_CONDITIONLINK_NO_CONDITION,
+ StringToId("Kll")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricMatcherNotFound) {
+ StatsdConfig config;
+ *config.add_count_metric() =
+ createCountMetric(/*name=*/"Count", /*what=*/StringToId("SOME MATCHER"),
+ /*condition=*/nullopt, /*states=*/{});
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_MATCHER_NOT_FOUND,
+ StringToId("Count"), StringToId("SOME MATCHER")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricConditionLinkNotFound) {
+ StatsdConfig config;
+ CountMetric* metric = config.add_count_metric();
+ *metric = createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/StringToId("ScreenIsOn"), /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+
+ auto link = metric->add_links();
+ link->set_condition(StringToId("SOME CONDITION"));
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_METRIC_CONDITION_LINK_NOT_FOUND,
+ StringToId("Count"), StringToId("SOME CONDITION")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricStateNotFound) {
+ StatsdConfig config;
+ *config.add_count_metric() =
+ createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{StringToId("SOME STATE")});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithState(INVALID_CONFIG_REASON_METRIC_STATE_NOT_FOUND,
+ StringToId("Count"), StringToId("SOME STATE")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricStatelinkNoState) {
+ StatsdConfig config;
+ CountMetric* metric = config.add_count_metric();
+ *metric = createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ auto link = metric->add_state_link();
+ link->set_state_atom_id(2);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_STATELINK_NO_STATE,
+ StringToId("Count")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricBadThreshold) {
+ StatsdConfig config;
+ CountMetric* metric = config.add_count_metric();
+ *metric = createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ metric->mutable_threshold()->set_lt_float(1.0);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_BAD_THRESHOLD, StringToId("Count")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricActivationMatcherNotFound) {
+ StatsdConfig config;
+ *config.add_count_metric() =
+ createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ auto metric_activation = config.add_metric_activation();
+ metric_activation->set_metric_id(StringToId("Count"));
+ metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+ auto event_activation = metric_activation->add_event_activation();
+
+ event_activation->set_atom_matcher_id(StringToId("SOME_MATCHER"));
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_ACTIVATION_MATCHER_NOT_FOUND,
+ StringToId("Count"), StringToId("SOME_MATCHER")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricDeactivationMatcherNotFound) {
+ StatsdConfig config;
+ *config.add_count_metric() =
+ createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ auto metric_activation = config.add_metric_activation();
+ metric_activation->set_metric_id(StringToId("Count"));
+ metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+ auto event_activation = metric_activation->add_event_activation();
+ event_activation->set_atom_matcher_id(StringToId("ScreenTurnedOn"));
+
+ event_activation->set_deactivation_atom_matcher_id(StringToId("SOME_MATCHER"));
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_METRIC_DEACTIVATION_MATCHER_NOT_FOUND,
+ StringToId("Count"), StringToId("SOME_MATCHER")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricSlicedStateAtomAllowedFromAnyUid) {
+ StatsdConfig config;
+ CountMetric* metric = config.add_count_metric();
+ *metric = createCountMetric(/*name=*/"Count", /*what=*/StringToId("ScreenTurnedOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ *config.add_state() = CreateScreenState();
+ metric->add_slice_by_state(StringToId("ScreenState"));
+ config.add_whitelisted_atom_ids(util::SCREEN_STATE_CHANGED);
+
+ EXPECT_EQ(
+ initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SLICED_STATE_ATOM_ALLOWED_FROM_ANY_UID,
+ StringToId("Count")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestDurationMetricWhatNotSimple) {
+ StatsdConfig config;
+ *config.add_duration_metric() =
+ createDurationMetric(/*name=*/"Duration", /*what=*/StringToId("ScreenIsEitherOnOff"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+ *config.add_predicate() = CreateScreenIsOffPredicate();
+
+ auto condition = config.add_predicate();
+ condition->set_id(StringToId("ScreenIsEitherOnOff"));
+ Predicate_Combination* combination = condition->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_predicate(StringToId("ScreenIsOn"));
+ combination->add_predicate(StringToId("ScreenIsOff"));
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_SIMPLE, StringToId("Duration"),
+ StringToId("ScreenIsEitherOnOff")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestDurationMetricWhatNotFound) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ DurationMetric* metric = config.add_duration_metric();
+ metric->set_id(metricId);
+
+ metric->set_what(StringToId("SOME WHAT"));
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_WHAT_NOT_FOUND,
+ metricId, StringToId("SOME WHAT")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestDurationMetricMissingStart) {
+ StatsdConfig config;
+ *config.add_duration_metric() =
+ createDurationMetric(/*name=*/"Duration", /*what=*/StringToId("SCREEN_IS_ON"),
+ /*condition=*/nullopt, /*states=*/{});
+ auto condition = config.add_predicate();
+ condition->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
+ simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_DURATION_METRIC_MISSING_START,
+ StringToId("Duration"), StringToId("SCREEN_IS_ON")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestDurationMetricMaxSparseHasSpliceByState) {
+ StatsdConfig config;
+ DurationMetric* metric = config.add_duration_metric();
+ *metric = createDurationMetric(/*name=*/"Duration", /*what=*/StringToId("ScreenIsOn"),
+ /*condition=*/nullopt, /*states=*/{});
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+ *config.add_state() = CreateScreenState();
+
+ metric->add_slice_by_state(StringToId("ScreenState"));
+ metric->set_aggregation_type(DurationMetric::MAX_SPARSE);
+
+ EXPECT_EQ(
+ initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_DURATION_METRIC_MAX_SPARSE_HAS_SLICE_BY_STATE,
+ StringToId("Duration")));
}
-TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerInvalidMatcher) {
+TEST_F(MetricsManagerUtilTest, TestValueMetricMissingValueField) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ ValueMetric* metric = config.add_value_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ EXPECT_EQ(
+ initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_VALUE_METRIC_MISSING_VALUE_FIELD, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestValueMetricValueFieldHasPositionAll) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ ValueMetric* metric = config.add_value_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ metric->mutable_value_field()->set_position(ALL);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_VALUE_METRIC_VALUE_FIELD_HAS_POSITION_ALL,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestValueMetricHasIncorrectValueField) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ ValueMetric* metric = config.add_value_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ metric->mutable_value_field()->set_position(ANY);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_VALUE_METRIC_HAS_INCORRECT_VALUE_FIELD,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestKllMetricMissingKllField) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ KllMetric* metric = config.add_kll_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_KLL_METRIC_MISSING_KLL_FIELD, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestKllMetricKllFieldHasPositionAll) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ KllMetric* metric = config.add_kll_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ metric->mutable_kll_field()->set_position(ALL);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_KLL_METRIC_KLL_FIELD_HAS_POSITION_ALL,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestKllMetricHasIncorrectKllField) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ KllMetric* metric = config.add_kll_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ metric->mutable_kll_field()->set_position(ANY);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_KLL_METRIC_HAS_INCORRECT_KLL_FIELD,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestGaugeMetricIncorrectFieldFilter) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ GaugeMetric* metric = config.add_gauge_metric();
+ metric->set_id(metricId);
+ metric->set_what(1);
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_GAUGE_METRIC_INCORRECT_FIELD_FILTER,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestGaugeMetricTriggerNoPullAtom) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ GaugeMetric* metric = config.add_gauge_metric();
+ metric->set_id(metricId);
+ metric->set_what(StringToId("ScreenTurnedOn"));
+ metric->mutable_gauge_fields_filter()->set_include_all(true);
+ metric->set_trigger_event(1);
+
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ EXPECT_EQ(
+ initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_PULL_ATOM, metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestGaugeMetricTriggerNoFirstNSamples) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ GaugeMetric* metric = config.add_gauge_metric();
+ metric->set_id(metricId);
+ metric->set_what(StringToId("Matcher"));
+ *config.add_atom_matcher() =
+ CreateSimpleAtomMatcher(/*name=*/"Matcher", /*atomId=*/util::SUBSYSTEM_SLEEP_STATE);
+
+ metric->mutable_gauge_fields_filter()->set_include_all(true);
+ metric->set_trigger_event(StringToId("Matcher"));
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_GAUGE_METRIC_TRIGGER_NO_FIRST_N_SAMPLES,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestGaugeMetricFirstNSamplesWithWrongEvent) {
+ StatsdConfig config;
+ int64_t metricId = 1;
+ GaugeMetric* metric = config.add_gauge_metric();
+ metric->set_id(metricId);
+ metric->set_what(StringToId("Matcher"));
+ *config.add_atom_matcher() =
+ CreateSimpleAtomMatcher(/*name=*/"Matcher", /*atomId=*/util::SUBSYSTEM_SLEEP_STATE);
+
+ metric->mutable_gauge_fields_filter()->set_include_all(true);
+ metric->set_sampling_type(GaugeMetric_SamplingType_FIRST_N_SAMPLES);
+
+ EXPECT_EQ(
+ initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_GAUGE_METRIC_FIRST_N_SAMPLES_WITH_WRONG_EVENT,
+ metricId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMatcherDuplicate) {
+ StatsdConfig config;
+
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithMatcher(INVALID_CONFIG_REASON_MATCHER_DUPLICATE,
+ StringToId("ScreenTurnedOn")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMatcherNoOperation) {
+ StatsdConfig config;
+ int64_t matcherId = 1;
+
+ AtomMatcher* matcher = config.add_atom_matcher();
+ matcher->set_id(matcherId);
+ matcher->mutable_combination()->add_matcher(StringToId("ScreenTurnedOn"));
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_NO_OPERATION, matcherId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMatcherNotOperationIsNotUnary) {
+ StatsdConfig config;
+ int64_t matcherId = 1;
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+
+ AtomMatcher* matcher = config.add_atom_matcher();
+ matcher->set_id(matcherId);
+ matcher->mutable_combination()->set_operation(LogicalOperation::NOT);
+ matcher->mutable_combination()->add_matcher(StringToId("ScreenTurnedOn"));
+ matcher->mutable_combination()->add_matcher(StringToId("ScreenTurnedOff"));
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_NOT_OPERATION_IS_NOT_UNARY, matcherId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestConditionChildNotFound) {
+ StatsdConfig config;
+ int64_t conditionId = 1;
+ int64_t childConditionId = 2;
+
+ Predicate* condition = config.add_predicate();
+ condition->set_id(conditionId);
+ condition->mutable_combination()->set_operation(LogicalOperation::NOT);
+ condition->mutable_combination()->add_predicate(childConditionId);
+
+ optional<InvalidConfigReason> expectedInvalidConfigReason =
+ createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_CHILD_NOT_FOUND,
+ conditionId);
+ expectedInvalidConfigReason->conditionIds.push_back(childConditionId);
+ EXPECT_EQ(initConfig(config), expectedInvalidConfigReason);
+}
+
+TEST_F(MetricsManagerUtilTest, TestConditionDuplicate) {
+ StatsdConfig config;
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_DUPLICATE,
+ StringToId("ScreenIsOn")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestConditionNoOperation) {
+ StatsdConfig config;
+ int64_t conditionId = 1;
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+
+ Predicate* condition = config.add_predicate();
+ condition->set_id(conditionId);
+ condition->mutable_combination()->add_predicate(StringToId("ScreenIsOn"));
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithPredicate(INVALID_CONFIG_REASON_CONDITION_NO_OPERATION,
+ conditionId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestConditionNotOperationIsNotUnary) {
+ StatsdConfig config;
+ int64_t conditionId = 1;
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+ *config.add_predicate() = CreateScreenIsOffPredicate();
+
+ Predicate* condition = config.add_predicate();
+ condition->set_id(conditionId);
+ condition->mutable_combination()->set_operation(LogicalOperation::NOT);
+ condition->mutable_combination()->add_predicate(StringToId("ScreenIsOn"));
+ condition->mutable_combination()->add_predicate(StringToId("ScreenIsOff"));
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_NOT_OPERATION_IS_NOT_UNARY, conditionId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestSubscriptionRuleNotFoundAlert) {
+ StatsdConfig config;
+ int64_t alertId = 1;
+ *config.add_subscription() = createSubscription("Subscription", Subscription::ALERT, alertId);
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithSubscriptionAndAlert(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_RULE_NOT_FOUND,
+ StringToId("Subscription"), alertId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestSubscriptionRuleNotFoundAlarm) {
+ StatsdConfig config;
+ int64_t alarmId = 1;
+ *config.add_subscription() = createSubscription("Subscription", Subscription::ALARM, alarmId);
+
+ EXPECT_EQ(initConfig(config), createInvalidConfigReasonWithSubscriptionAndAlarm(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_RULE_NOT_FOUND,
+ StringToId("Subscription"), alarmId));
+}
+
+TEST_F(MetricsManagerUtilTest, TestSubscriptionSubscriberInfoMissing) {
+ StatsdConfig config;
+ Subscription subscription =
+ createSubscription("Subscription", Subscription::ALERT, /*alert id=*/1);
+ subscription.clear_subscriber_information();
+ *config.add_subscription() = subscription;
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithSubscription(
+ INVALID_CONFIG_REASON_SUBSCRIPTION_SUBSCRIBER_INFO_MISSING,
+ StringToId("Subscription")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestAlarmPeriodLessThanOrEqualZero) {
+ StatsdConfig config;
+ *config.add_alarm() = createAlarm("Alarm", /*offset=*/1, /*period=*/-1);
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithAlarm(
+ INVALID_CONFIG_REASON_ALARM_PERIOD_LESS_THAN_OR_EQUAL_ZERO,
+ StringToId("Alarm")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestAlarmOffsetLessThanOrEqualZero) {
+ StatsdConfig config;
+ *config.add_alarm() = createAlarm("Alarm", /*offset=*/-1, /*period=*/1);
+
+ EXPECT_EQ(initConfig(config),
+ createInvalidConfigReasonWithAlarm(
+ INVALID_CONFIG_REASON_ALARM_OFFSET_LESS_THAN_OR_EQUAL_ZERO,
+ StringToId("Alarm")));
+}
+
+TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerInvalidMatcher) {
sp<UidMap> uidMap = new UidMap();
AtomMatcher matcher;
// Matcher has no contents_case (simple/combination), so it is invalid.
matcher.set_id(21);
- EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap), nullptr);
+ optional<InvalidConfigReason> invalidConfigReason;
+ EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap, invalidConfigReason), nullptr);
+ EXPECT_EQ(invalidConfigReason,
+ createInvalidConfigReasonWithMatcher(
+ INVALID_CONFIG_REASON_MATCHER_MALFORMED_CONTENTS_CASE, matcher.id()));
}
-TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerSimple) {
+TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerSimple) {
int index = 1;
int64_t id = 123;
sp<UidMap> uidMap = new UidMap();
AtomMatcher matcher;
matcher.set_id(id);
SimpleAtomMatcher* simpleAtomMatcher = matcher.mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(util::SCREEN_STATE_CHANGED);
+ simpleAtomMatcher->set_atom_id(SCREEN_STATE_ATOM_ID);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, index, uidMap);
+ optional<InvalidConfigReason> invalidConfigReason;
+ sp<AtomMatchingTracker> tracker =
+ createAtomMatchingTracker(matcher, index, 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(util::SCREEN_STATE_CHANGED), 1);
+ EXPECT_EQ(atomIds.count(SCREEN_STATE_ATOM_ID), 1);
}
-TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) {
+TEST_F(MetricsManagerUtilTest, TestCreateAtomMatchingTrackerCombination) {
int index = 1;
int64_t id = 123;
sp<UidMap> uidMap = new UidMap();
@@ -729,8 +1225,11 @@ TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) {
combination->add_matcher(123);
combination->add_matcher(223);
- sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, index, uidMap);
+ optional<InvalidConfigReason> invalidConfigReason;
+ sp<AtomMatchingTracker> tracker =
+ createAtomMatchingTracker(matcher, index, uidMap, invalidConfigReason);
EXPECT_NE(tracker, nullptr);
+ EXPECT_EQ(invalidConfigReason, nullopt);
// Combination matchers need to be initialized first.
EXPECT_FALSE(tracker->mInitialized);
@@ -740,16 +1239,21 @@ TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) {
ASSERT_EQ(atomIds.size(), 0);
}
-TEST(MetricsManagerTest, TestCreateConditionTrackerInvalid) {
+TEST_F(MetricsManagerUtilTest, TestCreateConditionTrackerInvalid) {
const ConfigKey key(123, 456);
// Predicate has no contents_case (simple/combination), so it is invalid.
Predicate predicate;
predicate.set_id(21);
unordered_map<int64_t, int> atomTrackerMap;
- EXPECT_EQ(createConditionTracker(key, predicate, 0, atomTrackerMap), nullptr);
+ optional<InvalidConfigReason> invalidConfigReason;
+ EXPECT_EQ(createConditionTracker(key, predicate, 0, atomTrackerMap, invalidConfigReason),
+ nullptr);
+ EXPECT_EQ(invalidConfigReason,
+ createInvalidConfigReasonWithPredicate(
+ INVALID_CONFIG_REASON_CONDITION_MALFORMED_CONTENTS_CASE, predicate.id()));
}
-TEST(MetricsManagerTest, TestCreateConditionTrackerSimple) {
+TEST_F(MetricsManagerUtilTest, TestCreateConditionTrackerSimple) {
int index = 1;
int64_t id = 987;
const ConfigKey key(123, 456);
@@ -769,7 +1273,10 @@ TEST(MetricsManagerTest, TestCreateConditionTrackerSimple) {
atomTrackerMap[stopMatcherId] = stopMatcherIndex;
atomTrackerMap[stopAllMatcherId] = stopAllMatcherIndex;
- sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ optional<InvalidConfigReason> invalidConfigReason;
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, predicate, index, atomTrackerMap, invalidConfigReason);
+ EXPECT_EQ(invalidConfigReason, nullopt);
EXPECT_EQ(tracker->getConditionId(), id);
EXPECT_EQ(tracker->isSliced(), false);
EXPECT_TRUE(tracker->IsSimpleCondition());
@@ -780,7 +1287,7 @@ TEST(MetricsManagerTest, TestCreateConditionTrackerSimple) {
ASSERT_EQ(interestedMatchers.count(stopAllMatcherIndex), 1);
}
-TEST(MetricsManagerTest, TestCreateConditionTrackerCombination) {
+TEST_F(MetricsManagerUtilTest, TestCreateConditionTrackerCombination) {
int index = 1;
int64_t id = 987;
const ConfigKey key(123, 456);
@@ -794,12 +1301,15 @@ TEST(MetricsManagerTest, TestCreateConditionTrackerCombination) {
// Combination conditions must be initialized to set most state.
unordered_map<int64_t, int> atomTrackerMap;
- sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ optional<InvalidConfigReason> invalidConfigReason;
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, predicate, index, atomTrackerMap, invalidConfigReason);
+ EXPECT_EQ(invalidConfigReason, nullopt);
EXPECT_EQ(tracker->getConditionId(), id);
EXPECT_FALSE(tracker->IsSimpleCondition());
}
-TEST(MetricsManagerTest, TestCreateAnomalyTrackerInvalidMetric) {
+TEST_F(MetricsManagerUtilTest, TestCreateAnomalyTrackerInvalidMetric) {
Alert alert;
alert.set_id(123);
alert.set_metric_id(1);
@@ -808,13 +1318,17 @@ TEST(MetricsManagerTest, TestCreateAnomalyTrackerInvalidMetric) {
sp<AlarmMonitor> anomalyAlarmMonitor;
vector<sp<MetricProducer>> metricProducers;
+ optional<InvalidConfigReason> invalidConfigReason;
// Pass in empty metric producers, causing an error.
EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, UPDATE_NEW, /*updateTime=*/123, {},
- metricProducers),
+ metricProducers, invalidConfigReason),
nullopt);
+ EXPECT_EQ(invalidConfigReason,
+ createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_METRIC_NOT_FOUND,
+ alert.metric_id(), alert.id()));
}
-TEST(MetricsManagerTest, TestCreateAnomalyTrackerNoThreshold) {
+TEST_F(MetricsManagerUtilTest, TestCreateAnomalyTrackerNoThreshold) {
int64_t metricId = 1;
Alert alert;
alert.set_id(123);
@@ -828,12 +1342,16 @@ TEST(MetricsManagerTest, TestCreateAnomalyTrackerNoThreshold) {
vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
sp<AlarmMonitor> anomalyAlarmMonitor;
+ optional<InvalidConfigReason> invalidConfigReason;
EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, UPDATE_NEW, /*updateTime=*/123,
- {{1, 0}}, metricProducers),
+ {{1, 0}}, metricProducers, invalidConfigReason),
nullopt);
+ EXPECT_EQ(invalidConfigReason,
+ createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_THRESHOLD_MISSING,
+ alert.id()));
}
-TEST(MetricsManagerTest, TestCreateAnomalyTrackerMissingBuckets) {
+TEST_F(MetricsManagerUtilTest, TestCreateAnomalyTrackerMissingBuckets) {
int64_t metricId = 1;
Alert alert;
alert.set_id(123);
@@ -847,12 +1365,16 @@ TEST(MetricsManagerTest, TestCreateAnomalyTrackerMissingBuckets) {
vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
sp<AlarmMonitor> anomalyAlarmMonitor;
+ optional<InvalidConfigReason> invalidConfigReason;
EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, UPDATE_NEW, /*updateTime=*/123,
- {{1, 0}}, metricProducers),
+ {{1, 0}}, metricProducers, invalidConfigReason),
nullopt);
+ EXPECT_EQ(invalidConfigReason,
+ createInvalidConfigReasonWithAlert(
+ INVALID_CONFIG_REASON_ALERT_INVALID_TRIGGER_OR_NUM_BUCKETS, alert.id()));
}
-TEST(MetricsManagerTest, TestCreateAnomalyTrackerGood) {
+TEST_F(MetricsManagerUtilTest, TestCreateAnomalyTrackerGood) {
int64_t metricId = 1;
Alert alert;
alert.set_id(123);
@@ -867,12 +1389,14 @@ TEST(MetricsManagerTest, TestCreateAnomalyTrackerGood) {
vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
sp<AlarmMonitor> anomalyAlarmMonitor;
+ optional<InvalidConfigReason> invalidConfigReason;
EXPECT_NE(createAnomalyTracker(alert, anomalyAlarmMonitor, UPDATE_NEW, /*updateTime=*/123,
- {{1, 0}}, metricProducers),
+ {{1, 0}}, metricProducers, invalidConfigReason),
nullopt);
+ EXPECT_EQ(invalidConfigReason, nullopt);
}
-TEST(MetricsManagerTest, TestCreateAnomalyTrackerDurationTooLong) {
+TEST_F(MetricsManagerUtilTest, TestCreateAnomalyTrackerDurationTooLong) {
int64_t metricId = 1;
Alert alert;
alert.set_id(123);
@@ -892,12 +1416,16 @@ TEST(MetricsManagerTest, TestCreateAnomalyTrackerDurationTooLong) {
1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/,
wizard, 0x0123456789, dimensions, 0, 0)});
sp<AlarmMonitor> anomalyAlarmMonitor;
+ optional<InvalidConfigReason> invalidConfigReason;
EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, UPDATE_NEW, /*updateTime=*/123,
- {{1, 0}}, metricProducers),
+ {{1, 0}}, metricProducers, invalidConfigReason),
nullopt);
+ EXPECT_EQ(invalidConfigReason,
+ createInvalidConfigReasonWithAlert(INVALID_CONFIG_REASON_ALERT_CANNOT_ADD_ANOMALY,
+ alert.metric_id(), alert.id()));
}
-TEST(MetricsManagerTest, TestCreateDurationProducerDimensionsInWhatInvalid) {
+TEST_F(MetricsManagerUtilTest, TestCreateDurationProducerDimensionsInWhatInvalid) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT");
*config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
@@ -934,6 +1462,326 @@ TEST(MetricsManagerTest, TestCreateDurationProducerDimensionsInWhatInvalid) {
EXPECT_FALSE(metricsManager->isConfigValid());
}
+TEST_F(MetricsManagerUtilTest, TestSampledMetrics) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+
+ AtomMatcher appCrashMatcher =
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
+ *config.add_atom_matcher() = appCrashMatcher;
+
+ *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+ *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+
+ AtomMatcher bleScanResultReceivedMatcher = CreateSimpleAtomMatcher(
+ "BleScanResultReceivedAtomMatcher", util::BLE_SCAN_RESULT_RECEIVED);
+ *config.add_atom_matcher() = bleScanResultReceivedMatcher;
+
+ Predicate holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+ *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ *config.add_predicate() = holdingWakelockPredicate;
+
+ CountMetric sampledCountMetric =
+ createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *sampledCountMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *sampledCountMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ sampledCountMetric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = sampledCountMetric;
+
+ CountMetric unsampledCountMetric =
+ createCountMetric("CountAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *unsampledCountMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *config.add_count_metric() = unsampledCountMetric;
+
+ DurationMetric sampledDurationMetric = createDurationMetric(
+ "DurationSampledWakelockPerUid", holdingWakelockPredicate.id(), nullopt, {});
+ *sampledDurationMetric.mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ *sampledDurationMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ sampledDurationMetric.mutable_dimensional_sampling_info()->set_shard_count(4);
+ *config.add_duration_metric() = sampledDurationMetric;
+
+ DurationMetric unsampledDurationMetric = createDurationMetric(
+ "DurationWakelockPerUid", holdingWakelockPredicate.id(), nullopt, {});
+ unsampledDurationMetric.set_aggregation_type(DurationMetric::SUM);
+ *unsampledDurationMetric.mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ *config.add_duration_metric() = unsampledDurationMetric;
+
+ ValueMetric sampledValueMetric =
+ createValueMetric("ValueSampledBleScanResultsPerUid", bleScanResultReceivedMatcher,
+ /*num_results=*/2, nullopt, {});
+ *sampledValueMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::BLE_SCAN_RESULT_RECEIVED, {1 /* uid */});
+ *sampledValueMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::BLE_SCAN_RESULT_RECEIVED, {1 /*uid*/});
+ sampledValueMetric.mutable_dimensional_sampling_info()->set_shard_count(6);
+ *config.add_value_metric() = sampledValueMetric;
+
+ ValueMetric unsampledValueMetric =
+ createValueMetric("ValueBleScanResultsPerUid", bleScanResultReceivedMatcher,
+ /*num_results=*/2, nullopt, {});
+ *unsampledValueMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::BLE_SCAN_RESULT_RECEIVED, {1 /* uid */});
+ *config.add_value_metric() = unsampledValueMetric;
+
+ KllMetric sampledKllMetric =
+ createKllMetric("KllSampledBleScanResultsPerUid", bleScanResultReceivedMatcher,
+ /*num_results=*/2, nullopt);
+ *sampledKllMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::BLE_SCAN_RESULT_RECEIVED, {1 /* uid */});
+ *sampledKllMetric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::BLE_SCAN_RESULT_RECEIVED, {1 /*uid*/});
+ sampledKllMetric.mutable_dimensional_sampling_info()->set_shard_count(8);
+ *config.add_kll_metric() = sampledKllMetric;
+
+ KllMetric unsampledKllMetric = createKllMetric(
+ "KllBleScanResultsPerUid", bleScanResultReceivedMatcher, /*num_results=*/2, nullopt);
+ *unsampledKllMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::BLE_SCAN_RESULT_RECEIVED, {1 /* uid */});
+ *config.add_kll_metric() = unsampledKllMetric;
+
+ 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(10);
+ *config.add_gauge_metric() = sampledGaugeMetric;
+
+ GaugeMetric unsampledGaugeMetric =
+ createGaugeMetric("GaugeAppCrashesPerUid", appCrashMatcher.id(),
+ GaugeMetric::FIRST_N_SAMPLES, nullopt, nullopt);
+ *unsampledGaugeMetric.mutable_dimensions_in_what() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /* uid */});
+ *config.add_gauge_metric() = unsampledGaugeMetric;
+
+ ConfigKey key(123, 987);
+ uint64_t timeNs = 456;
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ sp<UidMap> uidMap;
+ sp<MetricsManager> metricsManager =
+ new MetricsManager(key, config, timeNs, timeNs, uidMap, pullerManager,
+ anomalyAlarmMonitor, periodicAlarmMonitor);
+ ASSERT_TRUE(metricsManager->isConfigValid());
+ ASSERT_EQ(10, metricsManager->mAllMetricProducers.size());
+
+ sp<MetricProducer> sampledCountMetricProducer = metricsManager->mAllMetricProducers[0];
+ sp<MetricProducer> unsampledCountMetricProducer = metricsManager->mAllMetricProducers[1];
+ sp<MetricProducer> sampledDurationMetricProducer = metricsManager->mAllMetricProducers[2];
+ sp<MetricProducer> unsampledDurationMetricProducer = metricsManager->mAllMetricProducers[3];
+ sp<MetricProducer> sampledValueMetricProducer = metricsManager->mAllMetricProducers[4];
+ sp<MetricProducer> unsampledValueMetricProducer = metricsManager->mAllMetricProducers[5];
+ sp<MetricProducer> sampledKllMetricProducer = metricsManager->mAllMetricProducers[6];
+ sp<MetricProducer> unsampledKllMetricProducer = metricsManager->mAllMetricProducers[7];
+ sp<MetricProducer> sampledGaugeMetricProducer = metricsManager->mAllMetricProducers[8];
+ sp<MetricProducer> unsampledGaugeMetricProducer = metricsManager->mAllMetricProducers[9];
+
+ // Check shard count is set correctly for sampled metrics or set to default.
+ EXPECT_EQ(2, sampledCountMetricProducer->mShardCount);
+ EXPECT_EQ(0, unsampledCountMetricProducer->mShardCount);
+ EXPECT_EQ(4, sampledDurationMetricProducer->mShardCount);
+ EXPECT_EQ(0, unsampledDurationMetricProducer->mShardCount);
+ EXPECT_EQ(6, sampledValueMetricProducer->mShardCount);
+ EXPECT_EQ(0, unsampledValueMetricProducer->mShardCount);
+ EXPECT_EQ(8, sampledKllMetricProducer->mShardCount);
+ EXPECT_EQ(0, unsampledKllMetricProducer->mShardCount);
+ EXPECT_EQ(10, sampledGaugeMetricProducer->mShardCount);
+ EXPECT_EQ(0, unsampledGaugeMetricProducer->mShardCount);
+
+ // Check sampled what fields is set correctly or empty.
+ EXPECT_EQ(1, sampledCountMetricProducer->mSampledWhatFields.size());
+ EXPECT_EQ(true, unsampledCountMetricProducer->mSampledWhatFields.empty());
+ EXPECT_EQ(1, sampledDurationMetricProducer->mSampledWhatFields.size());
+ EXPECT_EQ(true, unsampledDurationMetricProducer->mSampledWhatFields.empty());
+ EXPECT_EQ(1, sampledValueMetricProducer->mSampledWhatFields.size());
+ EXPECT_EQ(true, unsampledValueMetricProducer->mSampledWhatFields.empty());
+ EXPECT_EQ(1, sampledKllMetricProducer->mSampledWhatFields.size());
+ EXPECT_EQ(true, unsampledKllMetricProducer->mSampledWhatFields.empty());
+ EXPECT_EQ(1, sampledGaugeMetricProducer->mSampledWhatFields.size());
+ EXPECT_EQ(true, unsampledGaugeMetricProducer->mSampledWhatFields.empty());
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasShardCountButNoSampledField) {
+ AtomMatcher appCrashMatcher =
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = appCrashMatcher;
+
+ CountMetric metric =
+ createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_MISSING_SAMPLED_FIELD,
+ metric.id()));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasSampledFieldIncorrectShardCount) {
+ AtomMatcher appCrashMatcher =
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = appCrashMatcher;
+
+ CountMetric metric =
+ createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(
+ INVALID_CONFIG_REASON_METRIC_DIMENSIONAL_SAMPLING_INFO_INCORRECT_SHARD_COUNT,
+ metric.id()));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasMultipleSampledFields) {
+ AtomMatcher appCrashMatcher =
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = appCrashMatcher;
+
+ CountMetric metric =
+ createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/, 2 /*event_type*/});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
+ metric.id()));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasRepeatedSampledField_PositionALL) {
+ AtomMatcher testAtomReportedMatcher =
+ CreateSimpleAtomMatcher("TEST_ATOM_REPORTED", util::TEST_ATOM_REPORTED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = testAtomReportedMatcher;
+
+ CountMetric metric = createCountMetric("CountSampledTestAtomReportedPerRepeatedIntField",
+ testAtomReportedMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateRepeatedDimensions(
+ util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/}, {Position::ALL});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateRepeatedDimensions(util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/},
+ {Position::ALL});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
+ metric.id()));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasRepeatedSampledField_PositionFIRST) {
+ AtomMatcher testAtomReportedMatcher =
+ CreateSimpleAtomMatcher("TEST_ATOM_REPORTED", util::TEST_ATOM_REPORTED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = testAtomReportedMatcher;
+
+ CountMetric metric = createCountMetric("CountSampledTestAtomReportedPerRepeatedIntField",
+ testAtomReportedMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateRepeatedDimensions(
+ util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/}, {Position::FIRST});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateRepeatedDimensions(util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/},
+ {Position::FIRST});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config), nullopt);
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasRepeatedSampledField_PositionLAST) {
+ AtomMatcher testAtomReportedMatcher =
+ CreateSimpleAtomMatcher("TEST_ATOM_REPORTED", util::TEST_ATOM_REPORTED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = testAtomReportedMatcher;
+
+ CountMetric metric = createCountMetric("CountSampledTestAtomReportedPerRepeatedIntField",
+ testAtomReportedMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateRepeatedDimensions(
+ util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/}, {Position::LAST});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateRepeatedDimensions(util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/},
+ {Position::LAST});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config), nullopt);
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricHasRepeatedSampledField_PositionANY) {
+ AtomMatcher testAtomReportedMatcher =
+ CreateSimpleAtomMatcher("TEST_ATOM_REPORTED", util::TEST_ATOM_REPORTED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = testAtomReportedMatcher;
+
+ CountMetric metric = createCountMetric("CountSampledTestAtomReportedPerRepeatedIntField",
+ testAtomReportedMatcher.id(), nullopt, {});
+ *metric.mutable_dimensions_in_what() = CreateRepeatedDimensions(
+ util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/}, {Position::ANY});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateRepeatedDimensions(util::TEST_ATOM_REPORTED, {9 /*repeated_int_field*/},
+ {Position::ALL});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELD_INCORRECT_SIZE,
+ metric.id()));
+}
+
+TEST_F(MetricsManagerUtilTest, TestMetricSampledFieldNotSubsetDimension) {
+ AtomMatcher appCrashMatcher =
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
+
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT");
+ *config.add_atom_matcher() = appCrashMatcher;
+
+ CountMetric metric =
+ createCountMetric("CountSampledAppCrashesPerUid", appCrashMatcher.id(), nullopt, {});
+ *metric.mutable_dimensional_sampling_info()->mutable_sampled_what_field() =
+ CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ metric.mutable_dimensional_sampling_info()->set_shard_count(2);
+ *config.add_count_metric() = metric;
+
+ EXPECT_EQ(
+ initConfig(config),
+ InvalidConfigReason(INVALID_CONFIG_REASON_METRIC_SAMPLED_FIELDS_NOT_SUBSET_DIM_IN_WHAT,
+ metric.id()));
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/tests/statsd_test_util.cpp b/statsd/tests/statsd_test_util.cpp
index 33b6b568..832c0416 100644
--- a/statsd/tests/statsd_test_util.cpp
+++ b/statsd/tests/statsd_test_util.cpp
@@ -34,6 +34,25 @@ namespace android {
namespace os {
namespace statsd {
+void StatsServiceConfigTest::sendConfig(const StatsdConfig& config) {
+ string str;
+ config.SerializeToString(&str);
+ std::vector<uint8_t> configAsVec(str.begin(), str.end());
+ service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
+}
+
+ConfigMetricsReport StatsServiceConfigTest::getReports(sp<StatsLogProcessor> processor,
+ int64_t timestamp, bool include_current) {
+ vector<uint8_t> output;
+ ConfigKey configKey(kCallingUid, kConfigKey);
+ processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
+ true /* erase_data */, ADB_DUMP, NO_TIME_CONSTRAINTS, &output);
+ ConfigMetricsReportList reports;
+ reports.ParseFromArray(output.data(), output.size());
+ EXPECT_EQ(1, reports.reports_size());
+ return reports.reports(kCallingUid);
+}
+
StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
vector<uint8_t> bytes;
bytes.resize(proto->size());
@@ -86,6 +105,11 @@ AtomMatcher CreateFinishScheduledJobAtomMatcher() {
ScheduledJobStateChanged::FINISHED);
}
+AtomMatcher CreateScheduleScheduledJobAtomMatcher() {
+ return CreateScheduledJobStateChangedAtomMatcher("ScheduledJobSchedule",
+ ScheduledJobStateChanged::SCHEDULED);
+}
+
AtomMatcher CreateScreenBrightnessChangedAtomMatcher() {
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId("ScreenBrightnessChanged"));
@@ -255,10 +279,8 @@ AtomMatcher CreateAppStartOccurredAtomMatcher() {
AtomMatcher CreateTestAtomRepeatedStateAtomMatcher(const string& name,
TestAtomReported::State state,
Position position) {
- AtomMatcher atom_matcher;
- atom_matcher.set_id(StringToId(name));
+ AtomMatcher atom_matcher = CreateSimpleAtomMatcher(name, util::TEST_ATOM_REPORTED);
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(util::TEST_ATOM_REPORTED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(14); // Repeated enum field.
field_value_matcher->set_eq_int(state);
@@ -319,7 +341,7 @@ Predicate CreateScreenIsOnPredicate() {
Predicate CreateScreenIsOffPredicate() {
Predicate predicate;
- predicate.set_id(1111123);
+ predicate.set_id(StringToId("ScreenIsOff"));
predicate.mutable_simple_predicate()->set_start(StringToId("ScreenTurnedOff"));
predicate.mutable_simple_predicate()->set_stop(StringToId("ScreenTurnedOn"));
return predicate;
@@ -335,7 +357,7 @@ Predicate CreateHoldingWakelockPredicate() {
Predicate CreateIsSyncingPredicate() {
Predicate predicate;
- predicate.set_id(33333333333333);
+ predicate.set_id(StringToId("IsSyncing"));
predicate.mutable_simple_predicate()->set_start(StringToId("SyncStart"));
predicate.mutable_simple_predicate()->set_stop(StringToId("SyncEnd"));
return predicate;
@@ -592,14 +614,14 @@ ValueMetric createValueMetric(const string& name, const AtomMatcher& what, const
return metric;
}
-KllMetric createKllMetric(const string& name, const AtomMatcher& what, const int valueField,
+KllMetric createKllMetric(const string& name, const AtomMatcher& what, const int kllField,
const optional<int64_t>& condition) {
KllMetric metric;
metric.set_id(StringToId(name));
metric.set_what(what.id());
metric.set_bucket(TEN_MINUTES);
metric.mutable_kll_field()->set_field(what.simple_atom_matcher().atom_id());
- metric.mutable_kll_field()->add_child()->set_field(valueField);
+ metric.mutable_kll_field()->add_child()->set_field(kllField);
if (condition) {
metric.set_condition(condition.value());
}
@@ -1020,6 +1042,15 @@ std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(uint64_t timestampNs,
ScheduledJobStateChanged::FINISHED, timestampNs);
}
+// Create log event when scheduled job is scheduled.
+std::unique_ptr<LogEvent> CreateScheduleScheduledJobEvent(uint64_t timestampNs,
+ const vector<int>& attributionUids,
+ const vector<string>& attributionTags,
+ const string& jobName) {
+ return CreateScheduledJobStateChangedEvent(attributionUids, attributionTags, jobName,
+ ScheduledJobStateChanged::SCHEDULED, timestampNs);
+}
+
std::unique_ptr<LogEvent> CreateTestAtomReportedEventVariableRepeatedFields(
uint64_t timestampNs, const vector<int>& repeatedIntField,
const vector<int64_t>& repeatedLongField, const vector<float>& repeatedFloatField,
@@ -1313,6 +1344,22 @@ std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
return logEvent;
}
+std::unique_ptr<LogEvent> CreateBleScanResultReceivedEvent(uint64_t timestampNs,
+ const vector<int>& attributionUids,
+ const vector<string>& attributionTags,
+ const int numResults) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, util::BLE_SCAN_RESULT_RECEIVED);
+ AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
+
+ writeAttribution(statsEvent, attributionUids, attributionTags);
+ AStatsEvent_writeInt32(statsEvent, numResults);
+
+ std::unique_ptr<LogEvent> logEvent = std::make_unique<LogEvent>(/*uid=*/0, /*pid=*/0);
+ parseStatsEventToLogEvent(statsEvent, logEvent.get());
+ return logEvent;
+}
+
sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
const StatsdConfig& config, const ConfigKey& key,
const shared_ptr<IPullAtomCallback>& puller,
@@ -1692,6 +1739,8 @@ void backfillStringInReport(ConfigMetricsReport *config_report) {
backfillStringInDimension(str_map, metric_report->mutable_gauge_metrics());
} else if (metric_report->has_value_metrics()) {
backfillStringInDimension(str_map, metric_report->mutable_value_metrics());
+ } else if (metric_report->has_kll_metrics()) {
+ backfillStringInDimension(str_map, metric_report->mutable_kll_metrics());
}
}
// Backfill the package names.
@@ -1764,20 +1813,20 @@ bool backfillDimensionPath(const DimensionsValue& path,
}
void backfillDimensionPath(StatsLogReport* report) {
- if (report->has_dimensions_path_in_what() || report->has_dimensions_path_in_condition()) {
+ if (report->has_dimensions_path_in_what()) {
auto whatPath = report->dimensions_path_in_what();
- auto conditionPath = report->dimensions_path_in_condition();
if (report->has_count_metrics()) {
- backfillDimensionPath(whatPath, conditionPath, report->mutable_count_metrics());
+ backfillDimensionPath(whatPath, report->mutable_count_metrics());
} else if (report->has_duration_metrics()) {
- backfillDimensionPath(whatPath, conditionPath, report->mutable_duration_metrics());
+ backfillDimensionPath(whatPath, report->mutable_duration_metrics());
} else if (report->has_gauge_metrics()) {
- backfillDimensionPath(whatPath, conditionPath, report->mutable_gauge_metrics());
+ backfillDimensionPath(whatPath, report->mutable_gauge_metrics());
} else if (report->has_value_metrics()) {
- backfillDimensionPath(whatPath, conditionPath, report->mutable_value_metrics());
+ backfillDimensionPath(whatPath, report->mutable_value_metrics());
+ } else if (report->has_kll_metrics()) {
+ backfillDimensionPath(whatPath, report->mutable_kll_metrics());
}
report->clear_dimensions_path_in_what();
- report->clear_dimensions_path_in_condition();
}
}
@@ -2038,7 +2087,7 @@ vector<PackageInfo> buildPackageInfos(
return packageInfos;
}
-StatsdStatsReport_PulledAtomStats getPulledAtomStats() {
+StatsdStatsReport_PulledAtomStats getPulledAtomStats(int32_t atom_id) {
vector<uint8_t> statsBuffer;
StatsdStats::getInstance().dumpStats(&statsBuffer, false /*reset stats*/);
StatsdStatsReport statsReport;
@@ -2049,7 +2098,12 @@ StatsdStatsReport_PulledAtomStats getPulledAtomStats() {
if (statsReport.pulled_atom_stats_size() == 0) {
return pulledAtomStats;
}
- return statsReport.pulled_atom_stats(0);
+ for (size_t i = 0; i < statsReport.pulled_atom_stats_size(); i++) {
+ if (statsReport.pulled_atom_stats(i).atom_id() == atom_id) {
+ return statsReport.pulled_atom_stats(i);
+ }
+ }
+ return pulledAtomStats;
}
} // namespace statsd
diff --git a/statsd/tests/statsd_test_util.h b/statsd/tests/statsd_test_util.h
index c4fa1fe4..e262c0c9 100644
--- a/statsd/tests/statsd_test_util.h
+++ b/statsd/tests/statsd_test_util.h
@@ -23,6 +23,7 @@
#include <gtest/gtest.h>
#include "src/StatsLogProcessor.h"
+#include "src/StatsService.h"
#include "src/flags/FlagProvider.h"
#include "src/hash.h"
#include "src/logd/LogEvent.h"
@@ -48,6 +49,7 @@ using google::protobuf::util::MessageDifferencer;
using Status = ::ndk::ScopedAStatus;
using PackageInfoSnapshot = UidMapping_PackageInfoSnapshot;
using PackageInfo = UidMapping_PackageInfoSnapshot_PackageInfo;
+using ::ndk::SharedRefBase;
// Wrapper for assertion helpers called from tests to keep track of source location of failures.
// Example usage:
@@ -89,6 +91,36 @@ public:
const StatsDimensionsValueParcel& dimensionsValueParcel));
};
+class StatsServiceConfigTest : public ::testing::Test {
+protected:
+ shared_ptr<StatsService> service;
+ const int kConfigKey = 789130123; // Randomly chosen
+ const int kCallingUid = 0; // Randomly chosen
+ void SetUp() override {
+ service = SharedRefBase::make<StatsService>(new UidMap(), /* queue */ nullptr);
+ // Removing config file from data/misc/stats-service and data/misc/stats-data if present
+ ConfigKey configKey(kCallingUid, kConfigKey);
+ service->removeConfiguration(kConfigKey, kCallingUid);
+ service->mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, true /* erase_data */,
+ ADB_DUMP, NO_TIME_CONSTRAINTS, nullptr);
+ }
+
+ void TearDown() override {
+ // Cleaning up data/misc/stats-service and data/misc/stats-data
+ ConfigKey configKey(kCallingUid, kConfigKey);
+ service->removeConfiguration(kConfigKey, kCallingUid);
+ service->mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, true /* erase_data */,
+ ADB_DUMP, NO_TIME_CONSTRAINTS, nullptr);
+ }
+
+ void sendConfig(const StatsdConfig& config);
+
+ ConfigMetricsReport getReports(sp<StatsLogProcessor> processor, int64_t timestamp,
+ bool include_current = false);
+};
+
// Converts a ProtoOutputStream to a StatsLogReport proto.
StatsLogReport outputStreamToProto(ProtoOutputStream* proto);
@@ -107,6 +139,9 @@ AtomMatcher CreateStartScheduledJobAtomMatcher();
// Create AtomMatcher proto for a scheduled job is done.
AtomMatcher CreateFinishScheduledJobAtomMatcher();
+// Create AtomMatcher proto for cancelling a scheduled job.
+AtomMatcher CreateScheduleScheduledJobAtomMatcher();
+
// Create AtomMatcher proto for screen brightness state changed.
AtomMatcher CreateScreenBrightnessChangedAtomMatcher();
@@ -272,7 +307,7 @@ GaugeMetric createGaugeMetric(const string& name, const int64_t what,
ValueMetric createValueMetric(const string& name, const AtomMatcher& what, const int valueField,
const optional<int64_t>& condition, const vector<int64_t>& states);
-KllMetric createKllMetric(const string& name, const AtomMatcher& what, const int valueField,
+KllMetric createKllMetric(const string& name, const AtomMatcher& what, const int kllField,
const optional<int64_t>& condition);
Alert createAlert(const string& name, const int64_t metricId, const int buckets,
@@ -378,6 +413,12 @@ std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(uint64_t timestampNs,
const vector<string>& attributionTags,
const string& jobName);
+// Create log event when scheduled job schedules.
+std::unique_ptr<LogEvent> CreateScheduleScheduledJobEvent(uint64_t timestampNs,
+ const vector<int>& attributionUids,
+ const vector<string>& attributionTags,
+ const string& jobName);
+
// Create log event when battery saver starts.
std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs);
// Create log event when battery saver stops.
@@ -441,6 +482,11 @@ std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
AppStartOccurred::TransitionType type, const string& activity_name,
const string& calling_pkg_name, const bool is_instant_app, int64_t activity_start_msec);
+std::unique_ptr<LogEvent> CreateBleScanResultReceivedEvent(uint64_t timestampNs,
+ const vector<int>& attributionUids,
+ const vector<string>& attributionTags,
+ const int numResults);
+
std::unique_ptr<LogEvent> CreateTestAtomReportedEventVariableRepeatedFields(
uint64_t timestampNs, const vector<int>& repeatedIntField,
const vector<int64_t>& repeatedLongField, const vector<float>& repeatedFloatField,
@@ -535,9 +581,6 @@ void backfillStringInDimension(const std::map<uint64_t, string>& str_map,
if (data->has_dimensions_in_what()) {
backfillStringInDimension(str_map, data->mutable_dimensions_in_what());
}
- if (data->has_dimensions_in_condition()) {
- backfillStringInDimension(str_map, data->mutable_dimensions_in_condition());
- }
}
}
@@ -560,9 +603,7 @@ public:
};
template <typename T>
-void backfillDimensionPath(const DimensionsValue& whatPath,
- const DimensionsValue& conditionPath,
- T* metricData) {
+void backfillDimensionPath(const DimensionsValue& whatPath, T* metricData) {
for (int i = 0; i < metricData->data_size(); ++i) {
auto data = metricData->mutable_data(i);
if (data->dimension_leaf_values_in_what_size() > 0) {
@@ -570,11 +611,6 @@ void backfillDimensionPath(const DimensionsValue& whatPath,
data->mutable_dimensions_in_what());
data->clear_dimension_leaf_values_in_what();
}
- if (data->dimension_leaf_values_in_condition_size() > 0) {
- backfillDimensionPath(conditionPath, data->dimension_leaf_values_in_condition(),
- data->mutable_dimensions_in_condition());
- data->clear_dimension_leaf_values_in_condition();
- }
}
}
@@ -722,7 +758,7 @@ std::vector<T> concatenate(const vector<T>& a, const vector<T>& b) {
return result;
}
-StatsdStatsReport_PulledAtomStats getPulledAtomStats();
+StatsdStatsReport_PulledAtomStats getPulledAtomStats(int atom_id);
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/tools/localtools/Android.bp b/statsd/tools/localtools/Android.bp
index f89e635f..c07cb4ee 100644
--- a/statsd/tools/localtools/Android.bp
+++ b/statsd/tools/localtools/Android.bp
@@ -50,6 +50,9 @@ java_test_host {
"guava",
],
data: [
- "test/external-atoms.proto",
+ "test/data/**/*.*",
+ ],
+ data_native_bins: [
+ "aprotoc",
],
}
diff --git a/statsd/tools/localtools/TEST_MAPPING b/statsd/tools/localtools/TEST_MAPPING
index 6862ad43..866c77e6 100644
--- a/statsd/tools/localtools/TEST_MAPPING
+++ b/statsd/tools/localtools/TEST_MAPPING
@@ -7,8 +7,16 @@
"exclude-annotation": "org.junit.Ignore"
},
{
- // Exclude test methods that require aprotoc host dependencies
- "exclude-filter": "com.android.statsd.shelltools.testdrive.ConfigurationTest#testOnePushedFromExternalAtomsProto"
+ // Exclude test methods that require aprotoc host dependencies - see http://b/118691442
+ "exclude-filter": "com.android.statsd.shelltools.testdrive.ConfigurationTest.testOnePushedFromExternalAtomsProto"
+ },
+ {
+ // Exclude test methods that require aprotoc host dependencies - see http://b/118691442
+ "exclude-filter": "com.android.statsd.shelltools.testdrive.ConfigurationTest.testOnePushedFromExternalAtomsProtoWithImportedAtom"
+ },
+ {
+ // Exclude test methods that require aprotoc host dependencies - see http://b/118691442
+ "exclude-filter": "com.android.statsd.shelltools.testdrive.ConfigurationTest.testOnePushedFromExternalAtomsProtoWithImportedEnum"
}
]
}
diff --git a/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index cc3b0ddf..a2236743 100644
--- a/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -81,6 +81,8 @@ public class TestDrive {
"com.google.android.cellbroadcastreceiver",
"com.google.android.apps.nexuslauncher",
"com.google.android.markup",
+ "com.android.art",
+ "com.google.android.art",
"AID_KEYSTORE",
"AID_VIRTUALIZATIONSERVICE",
"com.google.android.permissioncontroller",
@@ -143,6 +145,8 @@ public class TestDrive {
LOGGER.severe("\tWait for Enter key press before collecting report");
LOGGER.severe("-d delay_ms");
LOGGER.severe("\tWait for delay_ms before collecting report, default is 60000 ms");
+ LOGGER.severe("-v");
+ LOGGER.severe("\tDebug logging level");
}
boolean processArgs(
@@ -174,6 +178,8 @@ public class TestDrive {
mDeviceSerial = args[++first_arg];
} else if (remaining_args >= 2 && arg.equals("-e")) {
mPressToContinue = true;
+ } else if (remaining_args >= 2 && arg.equals("-v")) {
+ Utils.setUpLogger(LOGGER, true);
} else if (remaining_args >= 2 && arg.equals("-d")) {
mPressToContinue = false;
mReportCollectionDelayMillis = Integer.parseInt(args[++first_arg]);
@@ -189,11 +195,6 @@ public class TestDrive {
mProtoIncludes.add(HW_ATOMS_PROTO_FILEPATH);
}
- mDeviceSerial = Utils.chooseDevice(mDeviceSerial, connectedDevices, defaultDevice, LOGGER);
- if (mDeviceSerial == null) {
- return false;
- }
-
for (; first_arg < args.length; ++first_arg) {
String atom = args[first_arg];
try {
@@ -203,6 +204,11 @@ public class TestDrive {
}
}
+ mDeviceSerial = Utils.chooseDevice(mDeviceSerial, connectedDevices, defaultDevice, LOGGER);
+ if (mDeviceSerial == null) {
+ return false;
+ }
+
return configuration.hasPulledAtoms() || configuration.hasPushedAtoms();
}
@@ -315,8 +321,10 @@ public class TestDrive {
private String compileProtoFileIntoDescriptorSet(String protoFileName) {
final String protoCompilerBinary = "aprotoc";
final String descSetFlag = "--descriptor_set_out";
-
+ final String includeImportsFlag = "--include_imports";
+ final String includeSourceInfoFlag = "--include_source_info";
final String dsFileName = generateDescriptorSetFileName(protoFileName);
+
if (dsFileName == null) return null;
LOGGER.log(Level.FINE, "Target DescriptorSet File " + dsFileName);
@@ -326,11 +334,17 @@ public class TestDrive {
cmdArgs.add(protoCompilerBinary);
cmdArgs.add(descSetFlag);
cmdArgs.add(dsFileName);
+ cmdArgs.add(includeImportsFlag);
+ cmdArgs.add(includeSourceInfoFlag);
// populate the proto_path argument
if (mAndroidBuildTop != null) {
cmdArgs.add("-I");
cmdArgs.add(mAndroidBuildTop);
+
+ Path protoBufSrcPath = Paths.get(mAndroidBuildTop, "external/protobuf/src");
+ cmdArgs.add("-I");
+ cmdArgs.add(protoBufSrcPath.toString());
}
Path protoPath = Paths.get(protoFileName);
@@ -346,10 +360,8 @@ public class TestDrive {
commands = cmdArgs.toArray(commands);
Utils.runCommand(null, LOGGER, commands);
return dsFileName;
- } catch (IOException e) {
- LOGGER.log(Level.SEVERE, "Error while performing proto compilation: " + e);
- } catch (InterruptedException e) {
- LOGGER.log(Level.SEVERE, "Error while performing proto compilation: " + e);
+ } catch (InterruptedException | IOException e) {
+ LOGGER.severe("Error while performing proto compilation: " + e.getMessage());
}
return null;
}
@@ -379,7 +391,7 @@ public class TestDrive {
dsPath = dsPath.resolve(protoPath.getFileName().toString() + ".ds.tmp");
return dsPath.toString();
} catch (IOException e) {
- LOGGER.log(Level.INFO, "Could not find file " + protoFileName);
+ LOGGER.severe("Could not find file " + protoFileName);
}
return null;
}
@@ -394,17 +406,54 @@ public class TestDrive {
try (InputStream input = new FileInputStream(dsFileName)) {
DescriptorProtos.FileDescriptorSet fileDescriptorSet =
DescriptorProtos.FileDescriptorSet.parseFrom(input);
-
Descriptors.FileDescriptor fieldOptionsDesc =
DescriptorProtos.FieldOptions.getDescriptor().getFile();
- Descriptors.Descriptor atomMsgDesc = Descriptors.FileDescriptor.buildFrom(
- fileDescriptorSet.getFile(0),
- new Descriptors.FileDescriptor[]{fieldOptionsDesc}).findMessageTypeByName(
- "Atom");
+ LOGGER.fine("Files count is " + fileDescriptorSet.getFileCount());
+
+ // preparing dependencies list
+ List<Descriptors.FileDescriptor> dependencies =
+ new ArrayList<Descriptors.FileDescriptor>();
+ for (int fileIndex = 0; fileIndex < fileDescriptorSet.getFileCount(); fileIndex++) {
+ LOGGER.fine("Processing file " + fileIndex);
+ try {
+ Descriptors.FileDescriptor dep = Descriptors.FileDescriptor.buildFrom(
+ fileDescriptorSet.getFile(fileIndex),
+ new Descriptors.FileDescriptor[0]);
+ dependencies.add(dep);
+ } catch (Descriptors.DescriptorValidationException e) {
+ LOGGER.fine("Unable to parse atoms proto file: " + fileName + ". Error: "
+ + e.getDescription());
+ }
+ }
- if (atomMsgDesc.findFieldByNumber(atom) != null) return true;
- } catch (Descriptors.DescriptorValidationException | IOException e) {
+ Descriptors.FileDescriptor[] fileDescriptorDeps =
+ new Descriptors.FileDescriptor[dependencies.size()];
+ fileDescriptorDeps = dependencies.toArray(fileDescriptorDeps);
+
+ // looking for a file with an Atom definition
+ for (int fileIndex = 0; fileIndex < fileDescriptorSet.getFileCount(); fileIndex++) {
+ LOGGER.fine("Processing file " + fileIndex);
+ Descriptors.Descriptor atomMsgDesc = null;
+ try {
+ atomMsgDesc = Descriptors.FileDescriptor.buildFrom(
+ fileDescriptorSet.getFile(fileIndex), fileDescriptorDeps,
+ true)
+ .findMessageTypeByName("Atom");
+ } catch (Descriptors.DescriptorValidationException e) {
+ LOGGER.severe("Unable to parse atoms proto file: " + fileName + ". Error: "
+ + e.getDescription());
+ }
+
+ if (atomMsgDesc != null) {
+ LOGGER.fine("Atom message is located");
+ }
+
+ if (atomMsgDesc != null && atomMsgDesc.findFieldByNumber(atom) != null) {
+ return true;
+ }
+ }
+ } catch (IOException e) {
LOGGER.log(Level.WARNING, "Unable to parse atoms proto file: " + fileName, e);
} finally {
File dsFile = new File(dsFileName);
diff --git a/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java b/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java
index 1bf02cb2..650128d7 100644
--- a/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java
+++ b/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/ConfigurationTest.java
@@ -57,6 +57,8 @@ public class ConfigurationTest {
private final TestDrive.Configuration mConfiguration = new TestDrive.Configuration();
+ private final String mProtoFilePath = "test/data/atoms.proto";
+
@Test
public void testOnePushed() {
final int atom = 90;
@@ -95,7 +97,7 @@ public class ConfigurationTest {
assertFalse(TestDrive.Configuration.isPulledAtom(atom));
List<String> mProtoIncludes = new ArrayList<>();
- mProtoIncludes.add("test/external-atoms.proto");
+ mProtoIncludes.add(mProtoFilePath);
mConfiguration.addAtom(atom, mProtoIncludes);
StatsdConfig config = mConfiguration.createConfig();
@@ -124,6 +126,78 @@ public class ConfigurationTest {
assertEquals(0, atomMatchers.size());
}
+ @Ignore("b/258831376")
+ @Test
+ public void testOnePushedFromExternalAtomsProtoWithImportedAtom() {
+ final int atom = 106001;
+ assertFalse(TestDrive.Configuration.isPulledAtom(atom));
+
+ List<String> mProtoIncludes = new ArrayList<>();
+ mProtoIncludes.add(mProtoFilePath);
+
+ mConfiguration.addAtom(atom, mProtoIncludes);
+ StatsdConfig config = mConfiguration.createConfig();
+
+ //event_metric {
+ // id: 1111
+ // what: 1234567
+ //}
+ //atom_matcher {
+ // id: 1234567
+ // simple_atom_matcher {
+ // atom_id: 106001
+ // }
+ //}
+
+ assertEquals(1, config.getEventMetricCount());
+ assertEquals(0, config.getGaugeMetricCount());
+
+ assertTrue(mConfiguration.isTrackedMetric(config.getEventMetric(0).getId()));
+
+ final List<StatsdConfigProto.AtomMatcher> atomMatchers =
+ new ArrayList<>(config.getAtomMatcherList());
+ assertEquals(atom,
+ findAndRemoveAtomMatcherById(atomMatchers, config.getEventMetric(0).getWhat())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(0, atomMatchers.size());
+ }
+
+ @Ignore("b/258831376")
+ @Test
+ public void testOnePushedFromExternalAtomsProtoWithImportedEnum() {
+ final int atom = 100001;
+ assertFalse(TestDrive.Configuration.isPulledAtom(atom));
+
+ List<String> mProtoIncludes = new ArrayList<>();
+ mProtoIncludes.add(mProtoFilePath);
+
+ mConfiguration.addAtom(atom, mProtoIncludes);
+ StatsdConfig config = mConfiguration.createConfig();
+
+ //event_metric {
+ // id: 1111
+ // what: 1234567
+ //}
+ //atom_matcher {
+ // id: 1234567
+ // simple_atom_matcher {
+ // atom_id: 100001
+ // }
+ //}
+
+ assertEquals(1, config.getEventMetricCount());
+ assertEquals(0, config.getGaugeMetricCount());
+
+ assertTrue(mConfiguration.isTrackedMetric(config.getEventMetric(0).getId()));
+
+ final List<StatsdConfigProto.AtomMatcher> atomMatchers =
+ new ArrayList<>(config.getAtomMatcherList());
+ assertEquals(atom,
+ findAndRemoveAtomMatcherById(atomMatchers, config.getEventMetric(0).getWhat())
+ .getSimpleAtomMatcher().getAtomId());
+ assertEquals(0, atomMatchers.size());
+ }
+
@Test
public void testOnePulled() {
final int atom = 10022;
diff --git a/statsd/tools/localtools/test/external-atoms.proto b/statsd/tools/localtools/test/data/atoms.proto
index 5d115e0f..78d04a56 100644
--- a/statsd/tools/localtools/test/external-atoms.proto
+++ b/statsd/tools/localtools/test/data/atoms.proto
@@ -21,19 +21,26 @@ package android.tests;
option java_package = "android.tests";
option java_outer_classname = "ExternalAtoms";
+import "test/data/enum.proto";
+import "test/data/atoms/external_atoms/external_test_atom.proto";
+
/* Allocated atom IDs. */
message Atom {
oneof pushed {
- // AOSP atom ID range starts at 105000
+ AtomWithEnum atom_with_enum = 100001;
AOSPAtom aosp_atom = 105999;
+ external_atoms.TestAtom external_atoms_test_atom = 106001;
}
- // AOSP atom ID range ends at 109999
}
/* A test atom from an AOSP atom ids range */
-message AOSPAtom {
-
+message AtomWithEnum {
optional string reverse_domain_name = 1;
+ optional android.tests.enum.DemoEnumValues enum_value = 2;
+}
+/* A test atom from an AOSP atom ids range */
+message AOSPAtom {
+ optional string reverse_domain_name = 1;
optional int32 value = 2;
}
diff --git a/statsd/tools/localtools/test/data/atoms/external_atoms/external_test_atom.proto b/statsd/tools/localtools/test/data/atoms/external_atoms/external_test_atom.proto
new file mode 100644
index 00000000..ae44b86b
--- /dev/null
+++ b/statsd/tools/localtools/test/data/atoms/external_atoms/external_test_atom.proto
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package android.tests.external_atoms;
+
+option java_package = "android.tests.external_atoms";
+
+message TestAtom {
+ optional string reverse_domain_name = 1;
+ optional int32 int_value = 2;
+}
diff --git a/statsd/tools/localtools/test/data/enum.proto b/statsd/tools/localtools/test/data/enum.proto
new file mode 100644
index 00000000..35c36a20
--- /dev/null
+++ b/statsd/tools/localtools/test/data/enum.proto
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+syntax = "proto2";
+
+package android.tests.enum;
+
+enum DemoEnumValues {
+ DEMO_VALUE1 = 1;
+ DEMO_VALUE2 = 2;
+ DEMO_VALUE3 = 3;
+ DEMO_VALUE4 = 4;
+}
diff --git a/tests/src/android/cts/statsd/metric/CountMetricsTests.java b/tests/src/android/cts/statsd/metric/CountMetricsTests.java
index a641e614..22b4f9ca 100644
--- a/tests/src/android/cts/statsd/metric/CountMetricsTests.java
+++ b/tests/src/android/cts/statsd/metric/CountMetricsTests.java
@@ -385,6 +385,23 @@ public class CountMetricsTests extends DeviceAtomTestCase {
.setWhat(whatMatcherId)
.addSliceByState(stateId)
.addStateLink(stateLink)
+ .setDimensionsInWhat(
+ FieldMatcher.newBuilder()
+ .setField(whatAtomId)
+ .addChild(FieldMatcher.newBuilder()
+ .setField(1)
+ .setPosition(Position.FIRST)
+ .addChild(FieldMatcher.newBuilder()
+ .setField(AttributionNode.UID_FIELD_NUMBER)
+ )
+ )
+ .addChild(FieldMatcher.newBuilder()
+ .setField(2)
+ )
+ .addChild(FieldMatcher.newBuilder()
+ .setField(3)
+ )
+ )
)
.addAtomMatcher(whatMatcher)
.addState(state);