Partial Config Update: Matchers

There are two primary steps:
1. Determine which matchers to update
2. Perform the update

Added unit tests

Test: atest statsd_test
Bug: 162322018

Change-Id: I6dbaeb781eef362e2d024a560904497a3525cad2
This commit is contained in:
Tej Singh
2020-07-31 23:49:39 -07:00
parent 906a2e4fb2
commit 9605822dd9
25 changed files with 1627 additions and 857 deletions

View File

@@ -85,8 +85,9 @@ cc_defaults {
"src/metrics/EventMetricProducer.cpp",
"src/metrics/GaugeMetricProducer.cpp",
"src/metrics/MetricProducer.cpp",
"src/metrics/metrics_manager_util.cpp",
"src/metrics/MetricsManager.cpp",
"src/metrics/parsing_utils/config_update_utils.cpp",
"src/metrics/parsing_utils/metrics_manager_util.cpp",
"src/metrics/ValueMetricProducer.cpp",
"src/packages/UidMap.cpp",
"src/shell/shell_config.proto",
@@ -317,6 +318,8 @@ cc_test {
"tests/metrics/metrics_test_helper.cpp",
"tests/metrics/OringDurationTracker_test.cpp",
"tests/metrics/ValueMetricProducer_test.cpp",
"tests/metrics/parsing_utils/config_update_utils_test.cpp",
"tests/metrics/parsing_utils/metrics_manager_util_test.cpp",
"tests/MetricsManager_test.cpp",
"tests/shell/ShellSubscriber_test.cpp",
"tests/state/StateTracker_test.cpp",

View File

@@ -533,7 +533,8 @@ void StatsLogProcessor::OnConfigUpdatedLocked(const int64_t timestampNs, const C
}
} else {
// Preserve the existing MetricsManager, update necessary components and metadata in place.
configValid = it->second->updateConfig(timestampNs, config);
configValid = it->second->updateConfig(config, mTimeBaseNs, timestampNs,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
if (configValid) {
// TODO(b/162323476): refresh TTL, ensure init() is handled properly.
mUidMap->OnConfigUpdated(key);

View File

@@ -22,6 +22,7 @@ namespace android {
namespace os {
namespace statsd {
// Uses murmur2 hashing algorithm.
extern uint32_t Hash32(const char *data, size_t n, uint32_t seed);
extern uint64_t Hash64(const char* data, size_t n, uint64_t seed);

View File

@@ -27,8 +27,9 @@ using std::set;
using std::unordered_map;
using std::vector;
CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index)
: LogMatchingTracker(id, index) {
CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index,
const uint64_t protoHash)
: LogMatchingTracker(id, index, protoHash) {
}
CombinationLogMatchingTracker::~CombinationLogMatchingTracker() {

View File

@@ -28,7 +28,7 @@ namespace statsd {
// Represents a AtomMatcher_Combination in the StatsdConfig.
class CombinationLogMatchingTracker : public virtual LogMatchingTracker {
public:
CombinationLogMatchingTracker(const int64_t& id, const int index);
CombinationLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash);
bool init(const std::vector<AtomMatcher>& allLogMatchers,
const std::vector<sp<LogMatchingTracker>>& allTrackers,

View File

@@ -33,8 +33,8 @@ namespace statsd {
class LogMatchingTracker : public virtual RefBase {
public:
LogMatchingTracker(const int64_t& id, const int index)
: mId(id), mIndex(index), mInitialized(false){};
LogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash)
: mId(id), mIndex(index), mInitialized(false), mProtoHash(protoHash){};
virtual ~LogMatchingTracker(){};
@@ -69,10 +69,14 @@ public:
return mAtomIds;
}
const int64_t& getId() const {
int64_t getId() const {
return mId;
}
uint64_t getProtoHash() const {
return mProtoHash;
}
protected:
// Name of this matching. We don't really need the name, but it makes log message easy to debug.
const int64_t mId;
@@ -87,6 +91,14 @@ protected:
// return kNotMatched when we receive an event with an id not in the list. This is especially
// useful when we have a complex CombinationLogMatcherTracker.
std::set<int> mAtomIds;
// Hash of the AtomMatcher's proto bytes from StatsdConfig.
// Used to determine if the definition of this matcher has changed across a config update.
const uint64_t mProtoHash;
FRIEND_TEST(MetricsManagerTest, TestCreateLogTrackerSimple);
FRIEND_TEST(MetricsManagerTest, TestCreateLogTrackerCombination);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers);
};
} // namespace statsd

View File

@@ -26,11 +26,11 @@ namespace statsd {
using std::unordered_map;
using std::vector;
SimpleLogMatchingTracker::SimpleLogMatchingTracker(const int64_t& id, const int index,
const uint64_t protoHash,
const SimpleAtomMatcher& matcher,
const UidMap& uidMap)
: LogMatchingTracker(id, index), mMatcher(matcher), mUidMap(uidMap) {
const sp<UidMap>& uidMap)
: LogMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) {
if (!matcher.has_atom_id()) {
mInitialized = false;
} else {

View File

@@ -29,9 +29,8 @@ namespace statsd {
class SimpleLogMatchingTracker : public virtual LogMatchingTracker {
public:
SimpleLogMatchingTracker(const int64_t& id, const int index,
const SimpleAtomMatcher& matcher,
const UidMap& uidMap);
SimpleLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash,
const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap);
~SimpleLogMatchingTracker();
@@ -46,7 +45,7 @@ public:
private:
const SimpleAtomMatcher mMatcher;
const UidMap& mUidMap;
const sp<UidMap> mUidMap;
};
} // namespace statsd

View File

@@ -81,14 +81,15 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera
return matched;
}
bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const string& str_match) {
bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue,
const string& str_match) {
if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) {
int uid = fieldValue.mValue.int_value;
auto aidIt = UidMap::sAidToUidMapping.find(str_match);
if (aidIt != UidMap::sAidToUidMapping.end()) {
return ((int)aidIt->second) == uid;
}
std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/);
std::set<string> packageNames = uidMap->getAppNamesFromUid(uid, true /* normalize*/);
return packageNames.find(str_match) != packageNames.end();
} else if (fieldValue.mValue.getType() == STRING) {
return fieldValue.mValue.str_value == str_match;
@@ -96,7 +97,7 @@ bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const st
return false;
}
bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher,
const vector<FieldValue>& values, int start, int end, int depth) {
if (depth > 2) {
ALOGE("Depth > 3 not supported");
@@ -353,7 +354,7 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
}
}
bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher,
bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
const LogEvent& event) {
if (event.GetTagId() != simpleMatcher.atom_id()) {
return false;

View File

@@ -36,8 +36,8 @@ enum MatchingState {
bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation,
const std::vector<MatchingState>& matcherResults);
bool matchesSimple(const UidMap& uidMap,
const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper);
bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
const LogEvent& wrapper);
} // namespace statsd
} // namespace os

View File

@@ -26,7 +26,8 @@
#include "guardrail/StatsdStats.h"
#include "matchers/CombinationLogMatchingTracker.h"
#include "matchers/SimpleLogMatchingTracker.h"
#include "metrics_manager_util.h"
#include "parsing_utils/config_update_utils.h"
#include "parsing_utils/metrics_manager_util.h"
#include "state/StateManager.h"
#include "stats_log_util.h"
#include "stats_util.h"
@@ -76,13 +77,14 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
// Init the ttl end timestamp.
refreshTtl(timeBaseNs);
mConfigValid = initStatsdConfig(
key, config, *uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds);
mConfigValid =
initStatsdConfig(key, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseNs, currentTimeNs, mTagIds,
mAllAtomMatchers, mLogTrackerMap, mAllConditionTrackers,
mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds);
mHashStringsInReport = config.hash_strings_in_metric_report();
mVersionStringsInReport = config.version_strings_in_metric_report();
@@ -195,7 +197,19 @@ MetricsManager::~MetricsManager() {
VLOG("~MetricsManager()");
}
bool MetricsManager::updateConfig(const int64_t currentTimeNs, const StatsdConfig& config) {
bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor) {
vector<sp<LogMatchingTracker>> newAtomMatchers;
unordered_map<int64_t, int> newLogTrackerMap;
mTagIds.clear();
mConfigValid =
updateStatsdConfig(mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseNs, currentTimeNs, mAllAtomMatchers,
mLogTrackerMap, mTagIds, newAtomMatchers, newLogTrackerMap);
mAllAtomMatchers = newAtomMatchers;
mLogTrackerMap = newLogTrackerMap;
return mConfigValid;
}

View File

@@ -46,7 +46,9 @@ public:
virtual ~MetricsManager();
bool updateConfig(const int64_t currentTimeNs, const StatsdConfig& config);
bool updateConfig(const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor);
// Return whether the configuration is valid.
bool isConfigValid() const;
@@ -237,6 +239,12 @@ private:
// Hold all periodic alarm trackers.
std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers;
// To make updating configs faster, we map the id of a LogMatchingTracker, MetricProducer, and
// ConditionTracker to its index in the corresponding vector.
// Maps the id of an atom matcher to its index in mAllAtomMatchers.
std::unordered_map<int64_t, int> mLogTrackerMap;
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2020 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.
*/
#define DEBUG false // STOPSHIP if true
#include "config_update_utils.h"
#include "external/StatsPullerManager.h"
#include "hash.h"
#include "metrics_manager_util.h"
namespace android {
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>& oldLogTrackerMap,
const vector<sp<LogMatchingTracker>>& oldAtomMatchers,
const unordered_map<int64_t, int>& newLogTrackerMap,
vector<UpdateStatus>& matchersToUpdate,
vector<bool>& cycleTracker) {
// Have already examined this matcher.
if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) {
return true;
}
const AtomMatcher& matcher = config.atom_matcher(matcherIdx);
int64_t id = matcher.id();
// Check if new matcher.
const auto& oldLogTrackerIt = oldLogTrackerMap.find(id);
if (oldLogTrackerIt == oldLogTrackerMap.end()) {
matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
return true;
}
// 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;
}
uint64_t newProtoHash = Hash64(serializedMatcher);
if (newProtoHash != oldAtomMatchers[oldLogTrackerIt->second]->getProtoHash()) {
matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
return true;
}
switch (matcher.contents_case()) {
case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
matchersToUpdate[matcherIdx] = UPDATE_PRESERVE;
return true;
}
case AtomMatcher::ContentsCase::kCombination: {
// Recurse to check if children have changed.
cycleTracker[matcherIdx] = true;
UpdateStatus status = UPDATE_PRESERVE;
for (const int64_t childMatcherId : matcher.combination().matcher()) {
const auto& childIt = newLogTrackerMap.find(childMatcherId);
if (childIt == newLogTrackerMap.end()) {
ALOGW("Matcher %lld not found in the config", (long long)childMatcherId);
return false;
}
const int childIdx = childIt->second;
if (cycleTracker[childIdx]) {
ALOGE("Cycle detected in matcher config");
return false;
}
if (!determineMatcherUpdateStatus(config, childIdx, oldLogTrackerMap,
oldAtomMatchers, newLogTrackerMap,
matchersToUpdate, cycleTracker)) {
return false;
}
if (matchersToUpdate[childIdx] == UPDATE_REPLACE) {
status = UPDATE_REPLACE;
break;
}
}
matchersToUpdate[matcherIdx] = status;
cycleTracker[matcherIdx] = false;
return true;
}
default: {
ALOGE("Matcher \"%lld\" malformed", (long long)id);
return false;
}
}
return true;
}
bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
const unordered_map<int64_t, int>& oldLogTrackerMap,
const vector<sp<LogMatchingTracker>>& oldAtomMatchers, set<int>& allTagIds,
unordered_map<int64_t, int>& newLogTrackerMap,
vector<sp<LogMatchingTracker>>& newAtomMatchers) {
const int atomMatcherCount = config.atom_matcher_size();
vector<AtomMatcher> matcherProtos;
matcherProtos.reserve(atomMatcherCount);
newAtomMatchers.reserve(atomMatcherCount);
// 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 (newLogTrackerMap.find(matcher.id()) != newLogTrackerMap.end()) {
ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id());
return false;
}
newLogTrackerMap[matcher.id()] = i;
matcherProtos.push_back(matcher);
}
// For combination matchers, we need to determine if any children need to be updated.
vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN);
vector<bool> cycleTracker(atomMatcherCount, false);
for (int i = 0; i < atomMatcherCount; i++) {
if (!determineMatcherUpdateStatus(config, i, oldLogTrackerMap, oldAtomMatchers,
newLogTrackerMap, matchersToUpdate, cycleTracker)) {
return false;
}
}
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& matcher = config.atom_matcher(i);
const int64_t id = matcher.id();
switch (matchersToUpdate[i]) {
case UPDATE_PRESERVE: {
const auto& oldLogTrackerIt = oldLogTrackerMap.find(id);
if (oldLogTrackerIt == oldLogTrackerMap.end()) {
ALOGE("Could not find AtomMatcher %lld in the previous config, but expected it "
"to be there",
(long long)id);
return false;
}
const int oldIndex = oldLogTrackerIt->second;
newAtomMatchers.push_back(oldAtomMatchers[oldIndex]);
break;
}
case UPDATE_REPLACE: {
sp<LogMatchingTracker> tracker = createLogTracker(matcher, i, uidMap);
if (tracker == nullptr) {
return false;
}
newAtomMatchers.push_back(tracker);
break;
}
default: {
ALOGE("Matcher \"%lld\" update state is unknown. This should never happen",
(long long)id);
return false;
}
}
}
std::fill(cycleTracker.begin(), cycleTracker.end(), false);
for (auto& matcher : newAtomMatchers) {
if (!matcher->init(matcherProtos, newAtomMatchers, newLogTrackerMap, cycleTracker)) {
return false;
}
// Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
const set<int>& tagIds = matcher->getAtomIds();
allTagIds.insert(tagIds.begin(), tagIds.end());
}
return true;
}
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<LogMatchingTracker>>& oldAtomMatchers,
const unordered_map<int64_t, int>& oldLogTrackerMap, set<int>& allTagIds,
vector<sp<LogMatchingTracker>>& newAtomMatchers,
unordered_map<int64_t, int>& newLogTrackerMap) {
if (!updateLogTrackers(config, uidMap, oldLogTrackerMap, oldAtomMatchers, allTagIds,
newLogTrackerMap, newAtomMatchers)) {
ALOGE("updateLogMatchingTrackers failed");
return false;
}
return true;
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <vector>
#include "anomaly/AlarmMonitor.h"
#include "external/StatsPullerManager.h"
#include "matchers/LogMatchingTracker.h"
namespace android {
namespace os {
namespace statsd {
// Helper functions for MetricsManager to update itself from a new StatsdConfig.
// *Note*: only updateStatsdConfig() should be called from outside this file.
// All other functions are intermediate steps, created to make unit testing easier.
// Possible update states for a component. PRESERVE means we should keep the existing one.
// REPLACE means we should create a new one, either because it didn't exist or it changed.
enum UpdateStatus {
UPDATE_UNKNOWN = 0,
UPDATE_PRESERVE = 1,
UPDATE_REPLACE = 2,
};
// Recursive function to determine if a matcher needs to be updated.
// input:
// [config]: the input StatsdConfig
// [matcherIdx]: the index of the current matcher to be updated
// [newLogTrackerMap]: matcher id to index mapping in the input StatsdConfig
// [oldLogTrackerMap]: matcher id to index mapping in the existing MetricsManager
// [oldAtomMatchers]: stores the existing LogMatchingTrackers
// output:
// [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.
bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
const unordered_map<int64_t, int>& oldLogTrackerMap,
const vector<sp<LogMatchingTracker>>& oldAtomMatchers,
const unordered_map<int64_t, int>& newLogTrackerMap,
vector<UpdateStatus>& matchersToUpdate,
vector<bool>& cycleTracker);
// Updates the LogMatchingTrackers.
// input:
// [config]: the input StatsdConfig
// [oldLogTrackerMap]: existing matcher id to index mapping
// [oldAtomMatchers]: stores the existing LogMatchingTrackers
// output:
// [allTagIds]: contains the set of all interesting tag ids to this config.
// [newLogTrackerMap]: new matcher id to index mapping
// [newAtomMatchers]: stores the new LogMatchingTrackers
bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
const unordered_map<int64_t, int>& oldLogTrackerMap,
const vector<sp<LogMatchingTracker>>& oldAtomMatchers, set<int>& allTagIds,
unordered_map<int64_t, int>& newLogTrackerMap,
vector<sp<LogMatchingTracker>>& newAtomMatchers);
// 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<LogMatchingTracker>>& oldAtomMatchers,
const unordered_map<int64_t, int>& oldLogTrackerMap,
std::set<int>& allTagIds,
std::vector<sp<LogMatchingTracker>>& newAtomMatchers,
unordered_map<int64_t, int>& newLogTrackerMap);
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -22,10 +22,10 @@
#include <inttypes.h>
#include "FieldValue.h"
#include "MetricProducer.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "external/StatsPullerManager.h"
#include "hash.h"
#include "matchers/CombinationLogMatchingTracker.h"
#include "matchers/EventMatcherWizard.h"
#include "matchers/SimpleLogMatchingTracker.h"
@@ -33,6 +33,7 @@
#include "metrics/DurationMetricProducer.h"
#include "metrics/EventMetricProducer.h"
#include "metrics/GaugeMetricProducer.h"
#include "metrics/MetricProducer.h"
#include "metrics/ValueMetricProducer.h"
#include "state/StateManager.h"
#include "stats_util.h"
@@ -61,6 +62,28 @@ bool hasLeafNode(const FieldMatcher& matcher) {
} // namespace
sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index,
const sp<UidMap>& uidMap) {
string serializedMatcher;
if (!logMatcher.SerializeToString(&serializedMatcher)) {
ALOGE("Unable to serialize matcher %lld", (long long)logMatcher.id());
return nullptr;
}
uint64_t protoHash = Hash64(serializedMatcher);
switch (logMatcher.contents_case()) {
case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
return new SimpleLogMatchingTracker(logMatcher.id(), index, protoHash,
logMatcher.simple_atom_matcher(), uidMap);
break;
case AtomMatcher::ContentsCase::kCombination:
return new CombinationLogMatchingTracker(logMatcher.id(), index, protoHash);
break;
default:
ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
return nullptr;
}
}
bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
const bool usedForDimension,
const vector<sp<LogMatchingTracker>>& allAtomMatchers,
@@ -184,9 +207,7 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
// to provide the producer with state about its activators and deactivators.
// Returns false if there are errors.
bool handleMetricActivation(
const StatsdConfig& config,
const int64_t metricId,
const int metricIndex,
const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
const unordered_map<int64_t, int>& logTrackerMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
@@ -210,10 +231,11 @@ bool handleMetricActivation(
return false;
}
ActivationType activationType = (activation.has_activation_type()) ?
activation.activation_type() : metricActivation.activation_type();
std::shared_ptr<Activation> activationWrapper = std::make_shared<Activation>(
activationType, activation.ttl_seconds() * NS_PER_SEC);
ActivationType activationType = (activation.has_activation_type())
? activation.activation_type()
: metricActivation.activation_type();
std::shared_ptr<Activation> activationWrapper =
std::make_shared<Activation>(activationType, activation.ttl_seconds() * NS_PER_SEC);
int atomMatcherIndex = itr->second;
activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex);
@@ -235,7 +257,7 @@ bool handleMetricActivation(
return true;
}
bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
unordered_map<int64_t, int>& logTrackerMap,
vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
vector<AtomMatcher> matcherConfigs;
@@ -245,22 +267,12 @@ bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& logMatcher = config.atom_matcher(i);
int index = allAtomMatchers.size();
switch (logMatcher.contents_case()) {
case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
allAtomMatchers.push_back(new SimpleLogMatchingTracker(
logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
break;
case AtomMatcher::ContentsCase::kCombination:
allAtomMatchers.push_back(
new CombinationLogMatchingTracker(logMatcher.id(), index));
break;
default:
ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
return false;
// continue;
sp<LogMatchingTracker> tracker = createLogTracker(logMatcher, index, uidMap);
if (tracker == nullptr) {
return false;
}
allAtomMatchers.push_back(tracker);
if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
ALOGE("Duplicate AtomMatcher found!");
return false;
@@ -383,7 +395,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
const MetricActivation& metricActivation = config.metric_activation(i);
int64_t metricId = metricActivation.metric_id();
if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
ALOGE("Metric %lld has multiple MetricActivations", (long long) metricId);
ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
return false;
}
metricToActivationMap.insert({metricId, i});
@@ -402,9 +414,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
metric.has_dimensions_in_what(),
allAtomMatchers, logTrackerMap, trackerToMetricMap,
trackerIndex)) {
metric.has_dimensions_in_what(), allAtomMatchers,
logTrackerMap, trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -438,10 +449,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
bool success = handleMetricActivation(config, metric.id(), metricIndex,
metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
eventDeactivationMap);
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> countProducer =
@@ -544,10 +555,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
bool success = handleMetricActivation(config, metric.id(), metricIndex,
metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
eventDeactivationMap);
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> durationMetric = new DurationMetricProducer(
@@ -591,10 +602,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
bool success = handleMetricActivation(config, metric.id(), metricIndex,
metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
eventDeactivationMap);
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> eventMetric =
@@ -626,9 +637,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
metric.has_dimensions_in_what(),
allAtomMatchers, logTrackerMap, trackerToMetricMap,
trackerIndex)) {
metric.has_dimensions_in_what(), allAtomMatchers,
logTrackerMap, trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -718,9 +728,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
metric.has_dimensions_in_what(),
allAtomMatchers, logTrackerMap, trackerToMetricMap,
trackerIndex)) {
metric.has_dimensions_in_what(), allAtomMatchers,
logTrackerMap, trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -775,10 +784,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
bool success = handleMetricActivation(config, metric.id(), metricIndex,
metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
eventDeactivationMap);
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
@@ -813,8 +822,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
return true;
}
bool initAlerts(const StatsdConfig& config,
const unordered_map<int64_t, int>& metricProducerMap,
bool initAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& metricProducerMap,
unordered_map<int64_t, int>& alertTrackerMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
vector<sp<MetricProducer>>& allMetricProducers,
@@ -832,8 +840,8 @@ bool initAlerts(const StatsdConfig& config,
return false;
}
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());
ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
alert.num_buckets());
return false;
}
const int metricIndex = itr->second;
@@ -853,14 +861,13 @@ bool initAlerts(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());
ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
return false;
}
const auto& itr = alertTrackerMap.find(subscription.rule_id());
if (itr == alertTrackerMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
(long long)subscription.id(), (long long)subscription.rule_id());
(long long)subscription.id(), (long long)subscription.rule_id());
return false;
}
const int anomalyTrackerIndex = itr->second;
@@ -870,12 +877,11 @@ bool initAlerts(const StatsdConfig& config,
}
bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
const sp<AlarmMonitor>& periodicAlarmMonitor,
const int64_t timeBaseNs, const int64_t currentTimeNs,
vector<sp<AlarmTracker>>& allAlarmTrackers) {
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;
int64_t currentTimeMillis = currentTimeNs / 1000 / 1000;
for (int i = 0; i < config.alarm_size(); i++) {
const Alarm& alarm = config.alarm(i);
if (alarm.offset_millis() <= 0) {
@@ -888,8 +894,7 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
}
alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
allAlarmTrackers.push_back(
new AlarmTracker(startMillis, currentTimeMillis,
alarm, key, periodicAlarmMonitor));
new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
}
for (int i = 0; i < config.subscription_size(); ++i) {
const Subscription& subscription = config.subscription(i);
@@ -898,14 +903,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
}
if (subscription.subscriber_information_case() ==
Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
ALOGW("subscription \"%lld\" has no subscriber info.\"",
(long long)subscription.id());
ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
return false;
}
const auto& itr = alarmTrackerMap.find(subscription.rule_id());
if (itr == alarmTrackerMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
(long long)subscription.id(), (long long)subscription.rule_id());
(long long)subscription.id(), (long long)subscription.rule_id());
return false;
}
const int trackerIndex = itr->second;
@@ -914,12 +918,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
return true;
}
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
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, set<int>& allTagIds,
vector<sp<LogMatchingTracker>>& allAtomMatchers,
unordered_map<int64_t, int>& logTrackerMap,
vector<sp<ConditionTracker>>& allConditionTrackers,
vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
@@ -930,9 +935,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
unordered_map<int64_t, int>& alertTrackerMap,
vector<int>& metricsWithActivation,
std::set<int64_t>& noReportMetricIds) {
unordered_map<int64_t, int> logTrackerMap;
vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds) {
unordered_map<int64_t, int> conditionTrackerMap;
vector<ConditionState> initialConditionCache;
unordered_map<int64_t, int> metricProducerMap;
@@ -969,8 +972,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
ALOGE("initAlerts failed");
return false;
}
if (!initAlarms(config, key, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
allPeriodicAlarmTrackers)) {
ALOGE("initAlarms failed");
return false;
}

View File

@@ -20,16 +20,28 @@
#include <unordered_map>
#include <vector>
#include "../anomaly/AlarmTracker.h"
#include "../condition/ConditionTracker.h"
#include "../external/StatsPullerManager.h"
#include "../matchers/LogMatchingTracker.h"
#include "../metrics/MetricProducer.h"
#include "anomaly/AlarmTracker.h"
#include "condition/ConditionTracker.h"
#include "external/StatsPullerManager.h"
#include "matchers/LogMatchingTracker.h"
#include "metrics/MetricProducer.h"
namespace android {
namespace os {
namespace statsd {
// Helper functions for creating individual config components from StatsdConfig.
// Should only be called from metrics_manager_util and config_update_utils.
// Create a LogMatchingTracker.
// input:
// [logMatcher]: the input AtomMatcher from the StatsdConfig
// [index]: the index of the matcher
// output:
// new LogMatchingTracker, or null if the tracker is unable to be created
sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index,
const sp<UidMap>& uidMap);
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
@@ -44,8 +56,7 @@ namespace statsd {
// [logTrackerMap]: this map should contain matcher name to index mapping
// [allAtomMatchers]: should store the sp to all the LogMatchingTracker
// [allTagIds]: contains the set of all interesting tag ids to this config.
bool initLogTrackers(const StatsdConfig& config,
const UidMap& uidMap,
bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
std::unordered_map<int64_t, int>& logTrackerMap,
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
std::set<int>& allTagIds);
@@ -97,7 +108,7 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
bool initMetrics(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
const int64_t currentTimeNs, UidMap& uidMap, const sp<StatsPullerManager>& pullerManager,
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int64_t, int>& logTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
@@ -116,12 +127,13 @@ bool initMetrics(
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
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::set<int>& allTagIds,
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
std::unordered_map<int64_t, int>& logTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
@@ -132,8 +144,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::unordered_map<int64_t, int>& alertTrackerMap,
vector<int>& metricsWithActivation,
std::set<int64_t>& noReportMetricIds);
vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds);
} // namespace statsd
} // namespace os

View File

@@ -191,7 +191,7 @@ void ShellSubscriber::writePulledAtomsLocked(const vector<std::shared_ptr<LogEve
mProto.clear();
int count = 0;
for (const auto& event : data) {
if (matchesSimple(*mUidMap, matcher, *event)) {
if (matchesSimple(mUidMap, matcher, *event)) {
count++;
uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE |
util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
@@ -209,7 +209,7 @@ void ShellSubscriber::onLogEvent(const LogEvent& event) {
mProto.clear();
for (const auto& matcher : mSubscriptionInfo->mPushedMatchers) {
if (matchesSimple(*mUidMap, matcher, event)) {
if (matchesSimple(mUidMap, matcher, event)) {
uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE |
util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
event.ToProto(mProto);

View File

@@ -113,7 +113,7 @@ void makeBoolLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t ti
} // anonymous namespace
TEST(AtomMatcherTest, TestSimpleMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
@@ -132,7 +132,7 @@ TEST(AtomMatcherTest, TestSimpleMatcher) {
}
TEST(AtomMatcherTest, TestAttributionMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
std::vector<int> attributionUids = {1111, 2222, 3333};
std::vector<string> attributionTags = {"location1", "location2", "location3"};
@@ -207,7 +207,7 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
"pkg0");
EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
uidMap.updateMap(
uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -359,8 +359,8 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
}
TEST(AtomMatcherTest, TestUidFieldMatcher) {
UidMap uidMap;
uidMap.updateMap(
sp<UidMap> uidMap = new UidMap();
uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -395,8 +395,8 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) {
}
TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
sp<UidMap> uidMap = new UidMap();
uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -456,8 +456,8 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
}
TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
sp<UidMap> uidMap = new UidMap();
uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -520,7 +520,7 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
}
TEST(AtomMatcherTest, TestBoolMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -553,7 +553,7 @@ TEST(AtomMatcherTest, TestBoolMatcher) {
}
TEST(AtomMatcherTest, TestStringMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -571,7 +571,7 @@ TEST(AtomMatcherTest, TestStringMatcher) {
}
TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -600,7 +600,7 @@ TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
}
TEST(AtomMatcherTest, TestIntComparisonMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -657,7 +657,7 @@ TEST(AtomMatcherTest, TestIntComparisonMatcher) {
}
TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
UidMap uidMap;
sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();

View File

@@ -28,7 +28,7 @@
#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/MetricProducer.h"
#include "src/metrics/ValueMetricProducer.h"
#include "src/metrics/metrics_manager_util.h"
#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "src/state/StateManager.h"
#include "statsd_test_util.h"
@@ -48,7 +48,6 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
const long kAlertId = 3;
const long timeBaseSec = 1000;
@@ -90,287 +89,6 @@ StatsdConfig buildGoodConfig() {
metric->set_bucket(ONE_MINUTE);
metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
config.add_no_report_metric(3);
auto alert = config.add_alert();
alert->set_id(kAlertId);
alert->set_metric_id(3);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
}
StatsdConfig buildCircleMatchers() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("SCREEN_IS_ON"));
// Circle dependency
combination->add_matcher(StringToId("SCREEN_ON_OR_OFF"));
return config;
}
StatsdConfig buildAlertWithUnknownMetric() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
CountMetric* metric = config.add_count_metric();
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()->add_child()->set_field(1);
auto alert = config.add_alert();
alert->set_id(3);
alert->set_metric_id(2);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
}
StatsdConfig buildMissingMatchers() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("SCREEN_IS_ON"));
// undefined matcher
combination->add_matcher(StringToId("ABC"));
return config;
}
StatsdConfig buildMissingPredicate() {
StatsdConfig config;
config.set_id(12345);
CountMetric* metric = config.add_count_metric();
metric->set_id(3);
metric->set_what(StringToId("SCREEN_EVENT"));
metric->set_bucket(ONE_MINUTE);
metric->set_condition(StringToId("SOME_CONDITION"));
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_EVENT"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2);
return config;
}
StatsdConfig buildDimensionMetricsWithMultiTags() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("BATTERY_VERY_LOW"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(3);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("BATTERY_LOW"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("BATTERY_VERY_LOW"));
combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW"));
// Count process state changes, slice by uid, while SCREEN_IS_OFF
CountMetric* metric = config.add_count_metric();
metric->set_id(3);
metric->set_what(StringToId("BATTERY_LOW"));
metric->set_bucket(ONE_MINUTE);
// This case is interesting. We want to dimension across two atoms.
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
auto alert = config.add_alert();
alert->set_id(kAlertId);
alert->set_metric_id(3);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
}
StatsdConfig buildCirclePredicates() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
auto condition = config.add_predicate();
condition->set_id(StringToId("SCREEN_IS_ON"));
SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
simplePredicate->set_start(StringToId("SCREEN_IS_ON"));
simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
condition = config.add_predicate();
condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF"));
Predicate_Combination* combination = condition->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_predicate(StringToId("SCREEN_IS_ON"));
combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF"));
return config;
}
StatsdConfig buildConfigWithDifferentPredicates() {
StatsdConfig config;
config.set_id(12345);
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher();
*config.add_atom_matcher() = screenOnAtomMatcher;
auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher();
*config.add_atom_matcher() = screenOffAtomMatcher;
auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher();
*config.add_atom_matcher() = batteryNoneAtomMatcher;
auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher();
*config.add_atom_matcher() = batteryUsbAtomMatcher;
// Simple condition with InitialValue set to default (unknown).
auto screenOnUnknownPredicate = CreateScreenIsOnPredicate();
*config.add_predicate() = screenOnUnknownPredicate;
// Simple condition with InitialValue set to false.
auto screenOnFalsePredicate = config.add_predicate();
screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse"));
SimplePredicate* simpleScreenOnFalsePredicate =
screenOnFalsePredicate->mutable_simple_predicate();
simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id());
simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id());
simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
// Simple condition with InitialValue set to false.
auto onBatteryFalsePredicate = config.add_predicate();
onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse"));
SimplePredicate* simpleOnBatteryFalsePredicate =
onBatteryFalsePredicate->mutable_simple_predicate();
simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id());
simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id());
simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
// Combination condition with both simple condition InitialValues set to false.
auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate();
screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse"));
screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation(
LogicalOperation::AND);
addPredicateToPredicateCombination(*screenOnFalsePredicate,
screenOnFalseOnBatteryFalsePredicate);
addPredicateToPredicateCombination(*onBatteryFalsePredicate,
screenOnFalseOnBatteryFalsePredicate);
// Combination condition with one simple condition InitialValue set to unknown and one set to
// false.
auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate();
screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse"));
screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation(
LogicalOperation::AND);
addPredicateToPredicateCombination(screenOnUnknownPredicate,
screenOnUnknownOnBatteryFalsePredicate);
addPredicateToPredicateCombination(*onBatteryFalsePredicate,
screenOnUnknownOnBatteryFalsePredicate);
// Simple condition metric with initial value false.
ValueMetric* metric1 = config.add_value_metric();
metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse"));
metric1->set_what(pulledAtomMatcher.id());
*metric1->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric1->set_bucket(FIVE_MINUTES);
metric1->set_condition(screenOnFalsePredicate->id());
// Simple condition metric with initial value unknown.
ValueMetric* metric2 = config.add_value_metric();
metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown"));
metric2->set_what(pulledAtomMatcher.id());
*metric2->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric2->set_bucket(FIVE_MINUTES);
metric2->set_condition(screenOnUnknownPredicate.id());
// Combination condition metric with initial values false and false.
ValueMetric* metric3 = config.add_value_metric();
metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse"));
metric3->set_what(pulledAtomMatcher.id());
*metric3->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric3->set_bucket(FIVE_MINUTES);
metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id());
// Combination condition metric with initial values unknown and false.
ValueMetric* metric4 = config.add_value_metric();
metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse"));
metric4->set_what(pulledAtomMatcher.id());
*metric4->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric4->set_bucket(FIVE_MINUTES);
metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id());
return config;
}
@@ -379,274 +97,6 @@ bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) {
}
} // anonymous namespace
TEST(MetricsManagerTest, TestInitialConditions) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildConfigWithDifferentPredicates();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, allConditionTrackers,
allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
noReportMetricIds));
ASSERT_EQ(4u, allMetricProducers.size());
ASSERT_EQ(5u, allConditionTrackers.size());
ConditionKey queryKey;
vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
EXPECT_EQ(ConditionState::kFalse, conditionCache[1]);
EXPECT_EQ(ConditionState::kFalse, conditionCache[2]);
EXPECT_EQ(ConditionState::kFalse, conditionCache[3]);
EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]);
EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition);
EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition);
EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition);
EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
}
TEST(MetricsManagerTest, TestGoodConfig) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildGoodConfig();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation,
noReportMetricIds));
ASSERT_EQ(1u, allMetricProducers.size());
ASSERT_EQ(1u, allAnomalyTrackers.size());
ASSERT_EQ(1u, noReportMetricIds.size());
ASSERT_EQ(1u, alertTrackerMap.size());
EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
}
TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildDimensionMetricsWithMultiTags();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation,
noReportMetricIds));
}
TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildCircleMatchers();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation,
noReportMetricIds));
}
TEST(MetricsManagerTest, TestMissingMatchers) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildMissingMatchers();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation,
noReportMetricIds));
}
TEST(MetricsManagerTest, TestMissingPredicate) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildMissingPredicate();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCirclePredicateDependency) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildCirclePredicates();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation,
noReportMetricIds));
}
TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildAlertWithUnknownMetric();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
allAtomMatchers, allConditionTrackers, allMetricProducers,
allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation,
noReportMetricIds));
}
TEST(MetricsManagerTest, TestLogSources) {
string app1 = "app1";
set<int32_t> app1Uids = {1111, 11111};
@@ -680,7 +130,7 @@ TEST(MetricsManagerTest, TestLogSources) {
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildGoodConfig();
StatsdConfig config;
config.add_allowed_log_source("AID_SYSTEM");
config.add_allowed_log_source(app1);
config.add_default_pull_packages("AID_SYSTEM");
@@ -744,7 +194,7 @@ TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildGoodConfig();
StatsdConfig config;
config.add_whitelisted_atom_ids(3);
config.add_whitelisted_atom_ids(4);

View File

@@ -47,7 +47,6 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
const int64_t atomMatcherId = 678;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -94,11 +93,8 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<EventMatcherWizard> eventMatcherWizard =
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -127,12 +123,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -217,12 +209,8 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
wizard, logEventMatcherIndex, eventMatcherWizard,
@@ -301,12 +289,9 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
@@ -378,12 +363,8 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -428,12 +409,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
int64_t conditionChangeNs = bucketStartTimeNs + 8;
@@ -502,12 +479,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
dim->set_field(tagId);
dim->add_child()->set_field(1);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, _, _))
@@ -577,12 +550,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
gaugeFieldMatcher->set_field(tagId);
gaugeFieldMatcher->add_child()->set_field(2);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
@@ -657,12 +626,8 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
@@ -729,12 +694,8 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
@@ -807,12 +768,8 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _))

View File

@@ -46,7 +46,6 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
const int64_t atomMatcherId = 678;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10000000000;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -99,12 +98,8 @@ class ValueMetricProducerTestHelper {
public:
static sp<ValueMetricProducer> createValueProducerNoConditions(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -122,12 +117,8 @@ public:
static sp<ValueMetricProducer> createValueProducerWithCondition(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
ConditionState conditionAfterFirstBucketPrepared) {
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -147,12 +138,8 @@ public:
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
vector<int32_t> slicedStateAtoms,
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -172,12 +159,8 @@ public:
vector<int32_t> slicedStateAtoms,
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap,
ConditionState conditionAfterFirstBucketPrepared) {
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -237,12 +220,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
int64_t startTimeBase = 11;
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -267,12 +246,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
TEST(ValueMetricProducerTest, TestFirstBucket) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -421,15 +396,11 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
auto keyValue = atomMatcher.add_field_value_matcher();
keyValue->set_field(1);
keyValue->set_eq_int(3);
FieldValueMatcher fvm;
fvm.set_field(1);
fvm.set_eq_int(3);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex, {fvm});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -698,12 +669,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -759,12 +726,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
@@ -820,12 +783,8 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_split_bucket_for_app_upgrade(false);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -900,12 +859,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse
TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -944,12 +899,8 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1015,12 +966,8 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1317,12 +1264,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1361,12 +1304,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MAX);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1404,12 +1343,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::AVG);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1452,12 +1387,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::SUM);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1496,12 +1427,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1568,12 +1495,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2097,12 +2020,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -2920,12 +2839,8 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -2958,12 +2873,8 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -3002,12 +2913,8 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());

View File

@@ -0,0 +1,382 @@
// Copyright (C) 2020 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 "src/metrics/parsing_utils/config_update_utils.h"
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
#include <set>
#include <unordered_map>
#include <vector>
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "tests/statsd_test_util.h"
using namespace testing;
using android::sp;
using android::os::statsd::Predicate;
using std::map;
using std::set;
using std::unordered_map;
using std::vector;
#ifdef __ANDROID__
namespace android {
namespace os {
namespace statsd {
namespace {
ConfigKey key(123, 456);
const int64_t timeBaseNs = 1000;
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
set<int> allTagIds;
vector<sp<LogMatchingTracker>> oldAtomMatchers;
unordered_map<int64_t, int> oldLogTrackerMap;
vector<sp<ConditionTracker>> oldConditionTrackers;
vector<sp<MetricProducer>> oldMetricProducers;
std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
std::vector<sp<AlarmTracker>> oldAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
class ConfigUpdateTest : public ::testing::Test {
public:
ConfigUpdateTest() {
}
void SetUp() override {
allTagIds.clear();
oldAtomMatchers.clear();
oldLogTrackerMap.clear();
oldConditionTrackers.clear();
oldMetricProducers.clear();
oldAnomalyTrackers.clear();
oldAlarmTrackers.clear();
conditionToMetricMap.clear();
trackerToMetricMap.clear();
trackerToConditionMap.clear();
activationAtomTrackerToMetricMap.clear();
deactivationAtomTrackerToMetricMap.clear();
alertTrackerMap.clear();
metricsWithActivation.clear();
noReportMetricIds.clear();
}
};
bool initConfig(const StatsdConfig& config) {
return initStatsdConfig(key, config, uidMap, pullerManager, anomalyAlarmMonitor,
periodicAlarmMonitor, timeBaseNs, timeBaseNs, allTagIds,
oldAtomMatchers, oldLogTrackerMap, oldConditionTrackers,
oldMetricProducers, oldAnomalyTrackers, oldAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
alertTrackerMap, metricsWithActivation, noReportMetricIds);
}
} // anonymous namespace
TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
StatsdConfig config;
AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
int64_t matcherId = matcher.id();
*config.add_atom_matcher() = matcher;
// Create an initial config.
EXPECT_TRUE(initConfig(config));
vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newLogTrackerMap;
newLogTrackerMap[matcherId] = 0;
EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldLogTrackerMap, oldAtomMatchers,
newLogTrackerMap, matchersToUpdate, cycleTracker));
EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
}
TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) {
StatsdConfig config;
AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
*config.add_atom_matcher() = matcher;
EXPECT_TRUE(initConfig(config));
StatsdConfig newConfig;
// Same id, different atom, so should be replaced.
AtomMatcher newMatcher = CreateSimpleAtomMatcher("TEST", /*atom=*/11);
int64_t matcherId = newMatcher.id();
EXPECT_EQ(matcherId, matcher.id());
*newConfig.add_atom_matcher() = newMatcher;
vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
vector<bool> cycleTracker(1, false);
unordered_map<int64_t, int> newLogTrackerMap;
newLogTrackerMap[matcherId] = 0;
EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldLogTrackerMap, oldAtomMatchers,
newLogTrackerMap, matchersToUpdate, cycleTracker));
EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
}
TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) {
StatsdConfig config;
AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
int64_t matcher1Id = matcher1.id();
*config.add_atom_matcher() = matcher1;
AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
*config.add_atom_matcher() = matcher2;
int64_t matcher2Id = matcher2.id();
AtomMatcher matcher3;
matcher3.set_id(StringToId("TEST3"));
AtomMatcher_Combination* combination = matcher3.mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(matcher1Id);
combination->add_matcher(matcher2Id);
int64_t matcher3Id = matcher3.id();
*config.add_atom_matcher() = matcher3;
EXPECT_TRUE(initConfig(config));
StatsdConfig newConfig;
unordered_map<int64_t, int> newLogTrackerMap;
// Same matchers, different order, all should be preserved.
*newConfig.add_atom_matcher() = matcher2;
newLogTrackerMap[matcher2Id] = 0;
*newConfig.add_atom_matcher() = matcher3;
newLogTrackerMap[matcher3Id] = 1;
*newConfig.add_atom_matcher() = matcher1;
newLogTrackerMap[matcher1Id] = 2;
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, oldLogTrackerMap, oldAtomMatchers,
newLogTrackerMap, matchersToUpdate, cycleTracker));
EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE);
EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE);
}
TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) {
StatsdConfig config;
AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
int64_t matcher1Id = matcher1.id();
*config.add_atom_matcher() = matcher1;
AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
*config.add_atom_matcher() = matcher2;
int64_t matcher2Id = matcher2.id();
AtomMatcher matcher3;
matcher3.set_id(StringToId("TEST3"));
AtomMatcher_Combination* combination = matcher3.mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(matcher1Id);
combination->add_matcher(matcher2Id);
int64_t matcher3Id = matcher3.id();
*config.add_atom_matcher() = matcher3;
EXPECT_TRUE(initConfig(config));
// Change the logical operation of the combination matcher, causing a replacement.
matcher3.mutable_combination()->set_operation(LogicalOperation::AND);
StatsdConfig newConfig;
unordered_map<int64_t, int> newLogTrackerMap;
*newConfig.add_atom_matcher() = matcher2;
newLogTrackerMap[matcher2Id] = 0;
*newConfig.add_atom_matcher() = matcher3;
newLogTrackerMap[matcher3Id] = 1;
*newConfig.add_atom_matcher() = matcher1;
newLogTrackerMap[matcher1Id] = 2;
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, oldLogTrackerMap, oldAtomMatchers,
newLogTrackerMap, matchersToUpdate, cycleTracker));
EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN);
EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN);
}
TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) {
StatsdConfig config;
AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
int64_t matcher1Id = matcher1.id();
*config.add_atom_matcher() = matcher1;
AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
*config.add_atom_matcher() = matcher2;
int64_t matcher2Id = matcher2.id();
AtomMatcher matcher3;
matcher3.set_id(StringToId("TEST3"));
AtomMatcher_Combination* combination = matcher3.mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(matcher1Id);
combination->add_matcher(matcher2Id);
int64_t matcher3Id = matcher3.id();
*config.add_atom_matcher() = matcher3;
EXPECT_TRUE(initConfig(config));
// Change a dependency of matcher 3.
matcher2.mutable_simple_atom_matcher()->set_atom_id(12);
StatsdConfig newConfig;
unordered_map<int64_t, int> newLogTrackerMap;
*newConfig.add_atom_matcher() = matcher2;
newLogTrackerMap[matcher2Id] = 0;
*newConfig.add_atom_matcher() = matcher3;
newLogTrackerMap[matcher3Id] = 1;
*newConfig.add_atom_matcher() = matcher1;
newLogTrackerMap[matcher1Id] = 2;
vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
vector<bool> cycleTracker(3, false);
// Only update the combination.
EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers,
newLogTrackerMap, matchersToUpdate, cycleTracker));
// 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);
}
TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
StatsdConfig config;
// Will be preserved.
AtomMatcher simple1 = CreateSimpleAtomMatcher("SIMPLE1", /*atom=*/10);
int64_t simple1Id = simple1.id();
*config.add_atom_matcher() = simple1;
// Will be replaced.
AtomMatcher simple2 = CreateSimpleAtomMatcher("SIMPLE2", /*atom=*/11);
*config.add_atom_matcher() = simple2;
int64_t simple2Id = simple2.id();
// Will be removed.
AtomMatcher simple3 = CreateSimpleAtomMatcher("SIMPLE3", /*atom=*/12);
*config.add_atom_matcher() = simple3;
int64_t simple3Id = simple3.id();
// Will be preserved.
AtomMatcher combination1;
combination1.set_id(StringToId("combination1"));
AtomMatcher_Combination* combination = combination1.mutable_combination();
combination->set_operation(LogicalOperation::NOT);
combination->add_matcher(simple1Id);
int64_t combination1Id = combination1.id();
*config.add_atom_matcher() = combination1;
// Will be replaced since it depends on simple2.
AtomMatcher combination2;
combination2.set_id(StringToId("combination2"));
combination = combination2.mutable_combination();
combination->set_operation(LogicalOperation::AND);
combination->add_matcher(simple1Id);
combination->add_matcher(simple2Id);
int64_t combination2Id = combination2.id();
*config.add_atom_matcher() = combination2;
EXPECT_TRUE(initConfig(config));
// Change simple2, causing simple2 and combination2 to be replaced.
simple2.mutable_simple_atom_matcher()->set_atom_id(111);
// 2 new matchers: simple4 and combination3:
AtomMatcher simple4 = CreateSimpleAtomMatcher("SIMPLE4", /*atom=*/13);
int64_t simple4Id = simple4.id();
AtomMatcher combination3;
combination3.set_id(StringToId("combination3"));
combination = combination3.mutable_combination();
combination->set_operation(LogicalOperation::AND);
combination->add_matcher(simple4Id);
combination->add_matcher(simple2Id);
int64_t combination3Id = combination3.id();
StatsdConfig newConfig;
*newConfig.add_atom_matcher() = combination3;
*newConfig.add_atom_matcher() = simple2;
*newConfig.add_atom_matcher() = combination2;
*newConfig.add_atom_matcher() = simple1;
*newConfig.add_atom_matcher() = simple4;
*newConfig.add_atom_matcher() = combination1;
set<int> newTagIds;
unordered_map<int64_t, int> newLogTrackerMap;
vector<sp<LogMatchingTracker>> newAtomMatchers;
EXPECT_TRUE(updateLogTrackers(newConfig, uidMap, oldLogTrackerMap, oldAtomMatchers, newTagIds,
newLogTrackerMap, newAtomMatchers));
ASSERT_EQ(newTagIds.size(), 3);
EXPECT_EQ(newTagIds.count(10), 1);
EXPECT_EQ(newTagIds.count(111), 1);
EXPECT_EQ(newTagIds.count(13), 1);
ASSERT_EQ(newLogTrackerMap.size(), 6);
EXPECT_EQ(newLogTrackerMap.at(combination3Id), 0);
EXPECT_EQ(newLogTrackerMap.at(simple2Id), 1);
EXPECT_EQ(newLogTrackerMap.at(combination2Id), 2);
EXPECT_EQ(newLogTrackerMap.at(simple1Id), 3);
EXPECT_EQ(newLogTrackerMap.at(simple4Id), 4);
EXPECT_EQ(newLogTrackerMap.at(combination1Id), 5);
ASSERT_EQ(newAtomMatchers.size(), 6);
// Make sure all atom matchers are initialized:
for (const sp<LogMatchingTracker>& tracker : newAtomMatchers) {
EXPECT_TRUE(tracker->mInitialized);
}
// Make sure preserved atom matchers are the same.
EXPECT_EQ(oldAtomMatchers[oldLogTrackerMap.at(simple1Id)],
newAtomMatchers[newLogTrackerMap.at(simple1Id)]);
EXPECT_EQ(oldAtomMatchers[oldLogTrackerMap.at(combination1Id)],
newAtomMatchers[newLogTrackerMap.at(combination1Id)]);
// Make sure replaced matchers are different.
EXPECT_NE(oldAtomMatchers[oldLogTrackerMap.at(simple2Id)],
newAtomMatchers[newLogTrackerMap.at(simple2Id)]);
EXPECT_NE(oldAtomMatchers[oldLogTrackerMap.at(combination2Id)],
newAtomMatchers[newLogTrackerMap.at(combination2Id)]);
// Validation, make sure the matchers have the proper ids. Could do more checks here.
EXPECT_EQ(newAtomMatchers[0]->getId(), combination3Id);
EXPECT_EQ(newAtomMatchers[1]->getId(), simple2Id);
EXPECT_EQ(newAtomMatchers[2]->getId(), combination2Id);
EXPECT_EQ(newAtomMatchers[3]->getId(), simple1Id);
EXPECT_EQ(newAtomMatchers[4]->getId(), simple4Id);
EXPECT_EQ(newAtomMatchers[5]->getId(), combination1Id);
}
} // namespace statsd
} // namespace os
} // namespace android
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif

View File

@@ -0,0 +1,708 @@
// Copyright (C) 2020 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 "src/metrics/parsing_utils/metrics_manager_util.h"
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
#include <set>
#include <unordered_map>
#include <vector>
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "src/condition/ConditionTracker.h"
#include "src/matchers/LogMatchingTracker.h"
#include "src/metrics/CountMetricProducer.h"
#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/MetricProducer.h"
#include "src/metrics/ValueMetricProducer.h"
#include "src/state/StateManager.h"
#include "tests/metrics/metrics_test_helper.h"
#include "tests/statsd_test_util.h"
using namespace testing;
using android::sp;
using android::os::statsd::Predicate;
using std::map;
using std::set;
using std::unordered_map;
using std::vector;
#ifdef __ANDROID__
namespace android {
namespace os {
namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
const long kAlertId = 3;
const long timeBaseSec = 1000;
StatsdConfig buildGoodConfig() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("SCREEN_IS_ON"));
combination->add_matcher(StringToId("SCREEN_IS_OFF"));
CountMetric* metric = config.add_count_metric();
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()->add_child()->set_field(1);
config.add_no_report_metric(3);
auto alert = config.add_alert();
alert->set_id(kAlertId);
alert->set_metric_id(3);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
}
StatsdConfig buildCircleMatchers() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("SCREEN_IS_ON"));
// Circle dependency
combination->add_matcher(StringToId("SCREEN_ON_OR_OFF"));
return config;
}
StatsdConfig buildAlertWithUnknownMetric() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
CountMetric* metric = config.add_count_metric();
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()->add_child()->set_field(1);
auto alert = config.add_alert();
alert->set_id(3);
alert->set_metric_id(2);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
}
StatsdConfig buildMissingMatchers() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("SCREEN_IS_ON"));
// undefined matcher
combination->add_matcher(StringToId("ABC"));
return config;
}
StatsdConfig buildMissingPredicate() {
StatsdConfig config;
config.set_id(12345);
CountMetric* metric = config.add_count_metric();
metric->set_id(3);
metric->set_what(StringToId("SCREEN_EVENT"));
metric->set_bucket(ONE_MINUTE);
metric->set_condition(StringToId("SOME_CONDITION"));
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_EVENT"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2);
return config;
}
StatsdConfig buildDimensionMetricsWithMultiTags() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("BATTERY_VERY_LOW"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(3);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("BATTERY_LOW"));
AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(StringToId("BATTERY_VERY_LOW"));
combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW"));
// Count process state changes, slice by uid, while SCREEN_IS_OFF
CountMetric* metric = config.add_count_metric();
metric->set_id(3);
metric->set_what(StringToId("BATTERY_LOW"));
metric->set_bucket(ONE_MINUTE);
// This case is interesting. We want to dimension across two atoms.
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
auto alert = config.add_alert();
alert->set_id(kAlertId);
alert->set_metric_id(3);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
}
StatsdConfig buildCirclePredicates() {
StatsdConfig config;
config.set_id(12345);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
simpleAtomMatcher->add_field_value_matcher()->set_field(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
auto condition = config.add_predicate();
condition->set_id(StringToId("SCREEN_IS_ON"));
SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
simplePredicate->set_start(StringToId("SCREEN_IS_ON"));
simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
condition = config.add_predicate();
condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF"));
Predicate_Combination* combination = condition->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_predicate(StringToId("SCREEN_IS_ON"));
combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF"));
return config;
}
StatsdConfig buildConfigWithDifferentPredicates() {
StatsdConfig config;
config.set_id(12345);
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher();
*config.add_atom_matcher() = screenOnAtomMatcher;
auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher();
*config.add_atom_matcher() = screenOffAtomMatcher;
auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher();
*config.add_atom_matcher() = batteryNoneAtomMatcher;
auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher();
*config.add_atom_matcher() = batteryUsbAtomMatcher;
// Simple condition with InitialValue set to default (unknown).
auto screenOnUnknownPredicate = CreateScreenIsOnPredicate();
*config.add_predicate() = screenOnUnknownPredicate;
// Simple condition with InitialValue set to false.
auto screenOnFalsePredicate = config.add_predicate();
screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse"));
SimplePredicate* simpleScreenOnFalsePredicate =
screenOnFalsePredicate->mutable_simple_predicate();
simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id());
simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id());
simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
// Simple condition with InitialValue set to false.
auto onBatteryFalsePredicate = config.add_predicate();
onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse"));
SimplePredicate* simpleOnBatteryFalsePredicate =
onBatteryFalsePredicate->mutable_simple_predicate();
simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id());
simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id());
simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
// Combination condition with both simple condition InitialValues set to false.
auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate();
screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse"));
screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation(
LogicalOperation::AND);
addPredicateToPredicateCombination(*screenOnFalsePredicate,
screenOnFalseOnBatteryFalsePredicate);
addPredicateToPredicateCombination(*onBatteryFalsePredicate,
screenOnFalseOnBatteryFalsePredicate);
// Combination condition with one simple condition InitialValue set to unknown and one set to
// false.
auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate();
screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse"));
screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation(
LogicalOperation::AND);
addPredicateToPredicateCombination(screenOnUnknownPredicate,
screenOnUnknownOnBatteryFalsePredicate);
addPredicateToPredicateCombination(*onBatteryFalsePredicate,
screenOnUnknownOnBatteryFalsePredicate);
// Simple condition metric with initial value false.
ValueMetric* metric1 = config.add_value_metric();
metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse"));
metric1->set_what(pulledAtomMatcher.id());
*metric1->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric1->set_bucket(FIVE_MINUTES);
metric1->set_condition(screenOnFalsePredicate->id());
// Simple condition metric with initial value unknown.
ValueMetric* metric2 = config.add_value_metric();
metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown"));
metric2->set_what(pulledAtomMatcher.id());
*metric2->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric2->set_bucket(FIVE_MINUTES);
metric2->set_condition(screenOnUnknownPredicate.id());
// Combination condition metric with initial values false and false.
ValueMetric* metric3 = config.add_value_metric();
metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse"));
metric3->set_what(pulledAtomMatcher.id());
*metric3->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric3->set_bucket(FIVE_MINUTES);
metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id());
// Combination condition metric with initial values unknown and false.
ValueMetric* metric4 = config.add_value_metric();
metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse"));
metric4->set_what(pulledAtomMatcher.id());
*metric4->mutable_value_field() =
CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
metric4->set_bucket(FIVE_MINUTES);
metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id());
return config;
}
} // anonymous namespace
TEST(MetricsManagerTest, TestInitialConditions) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildConfigWithDifferentPredicates();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
ASSERT_EQ(4u, allMetricProducers.size());
ASSERT_EQ(5u, allConditionTrackers.size());
ConditionKey queryKey;
vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
EXPECT_EQ(ConditionState::kFalse, conditionCache[1]);
EXPECT_EQ(ConditionState::kFalse, conditionCache[2]);
EXPECT_EQ(ConditionState::kFalse, conditionCache[3]);
EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]);
EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition);
EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition);
EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition);
EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
}
TEST(MetricsManagerTest, TestGoodConfig) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildGoodConfig();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
ASSERT_EQ(1u, allMetricProducers.size());
ASSERT_EQ(1u, allAnomalyTrackers.size());
ASSERT_EQ(1u, noReportMetricIds.size());
ASSERT_EQ(1u, alertTrackerMap.size());
EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
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();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildCircleMatchers();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, TestMissingMatchers) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildMissingMatchers();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, TestMissingPredicate) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildMissingPredicate();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCirclePredicateDependency) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildCirclePredicates();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
StatsdConfig config = buildAlertWithUnknownMetric();
set<int> allTagIds;
vector<sp<LogMatchingTracker>> allAtomMatchers;
unordered_map<int64_t, int> logTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
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;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCreateLogTrackerInvalidMatcher) {
sp<UidMap> uidMap = new UidMap();
AtomMatcher matcher;
matcher.set_id(21);
EXPECT_EQ(createLogTracker(matcher, 0, uidMap), nullptr);
}
TEST(MetricsManagerTest, TestCreateLogTrackerSimple) {
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->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<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap);
EXPECT_NE(tracker, nullptr);
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);
}
TEST(MetricsManagerTest, TestCreateLogTrackerCombination) {
int index = 1;
int64_t id = 123;
sp<UidMap> uidMap = new UidMap();
AtomMatcher matcher;
matcher.set_id(id);
AtomMatcher_Combination* combination = matcher.mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_matcher(123);
combination->add_matcher(223);
sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap);
EXPECT_NE(tracker, nullptr);
// Combination matchers need to be initialized first.
EXPECT_FALSE(tracker->mInitialized);
EXPECT_EQ(tracker->getId(), id);
EXPECT_EQ(tracker->mIndex, index);
const set<int>& atomIds = tracker->getAtomIds();
ASSERT_EQ(atomIds.size(), 0);
}
} // namespace statsd
} // namespace os
} // namespace android
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif

View File

@@ -15,6 +15,8 @@
#include "statsd_test_util.h"
#include <aidl/android/util/StatsEventParcel.h>
#include "matchers/SimpleLogMatchingTracker.h"
#include "stats_event.h"
using aidl::android::util::StatsEventParcel;
@@ -996,6 +998,20 @@ int64_t StringToId(const string& str) {
return static_cast<int64_t>(std::hash<std::string>()(str));
}
sp<EventMatcherWizard> createEventMatcherWizard(
int tagId, int matcherIndex, const vector<FieldValueMatcher>& fieldValueMatchers) {
sp<UidMap> uidMap = new UidMap();
SimpleAtomMatcher atomMatcher;
atomMatcher.set_atom_id(tagId);
for (const FieldValueMatcher& fvm : fieldValueMatchers) {
*atomMatcher.add_field_value_matcher() = fvm;
}
uint64_t matcherHash = 0x12345678;
int64_t matcherId = 678;
return new EventMatcherWizard({new SimpleLogMatchingTracker(matcherId, matcherIndex,
matcherHash, atomMatcher, uidMap)});
}
void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
const int uid, const string& tag) {
EXPECT_EQ(value.field(), atomId);

View File

@@ -25,6 +25,7 @@
#include "src/StatsLogProcessor.h"
#include "src/hash.h"
#include "src/logd/LogEvent.h"
#include "src/matchers/EventMatcherWizard.h"
#include "src/packages/UidMap.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
@@ -335,6 +336,9 @@ void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
int64_t StringToId(const string& str);
sp<EventMatcherWizard> createEventMatcherWizard(
int tagId, int matcherIndex, const std::vector<FieldValueMatcher>& fieldValueMatchers = {});
void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
const int uid, const string& tag);
void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);