diff options
Diffstat (limited to 'cmds/statsd/src/condition/SimpleConditionTracker.cpp')
-rw-r--r-- | cmds/statsd/src/condition/SimpleConditionTracker.cpp | 386 |
1 files changed, 0 insertions, 386 deletions
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp deleted file mode 100644 index efb4d4989425..000000000000 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define DEBUG false // STOPSHIP if true -#include "Log.h" - -#include "SimpleConditionTracker.h" -#include "guardrail/StatsdStats.h" - -namespace android { -namespace os { -namespace statsd { - -using std::unordered_map; - -SimpleConditionTracker::SimpleConditionTracker( - const ConfigKey& key, const int64_t& id, const int index, - const SimplePredicate& simplePredicate, - const unordered_map<int64_t, int>& trackerNameIndexMap) - : ConditionTracker(id, index), mConfigKey(key), mContainANYPositionInInternalDimensions(false) { - VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId); - mCountNesting = simplePredicate.count_nesting(); - - if (simplePredicate.has_start()) { - auto pair = trackerNameIndexMap.find(simplePredicate.start()); - if (pair == trackerNameIndexMap.end()) { - ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start()); - return; - } - mStartLogMatcherIndex = pair->second; - mTrackerIndex.insert(mStartLogMatcherIndex); - } else { - mStartLogMatcherIndex = -1; - } - - if (simplePredicate.has_stop()) { - auto pair = trackerNameIndexMap.find(simplePredicate.stop()); - if (pair == trackerNameIndexMap.end()) { - ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop()); - return; - } - mStopLogMatcherIndex = pair->second; - mTrackerIndex.insert(mStopLogMatcherIndex); - } else { - mStopLogMatcherIndex = -1; - } - - if (simplePredicate.has_stop_all()) { - auto pair = trackerNameIndexMap.find(simplePredicate.stop_all()); - if (pair == trackerNameIndexMap.end()) { - ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all()); - return; - } - mStopAllLogMatcherIndex = pair->second; - mTrackerIndex.insert(mStopAllLogMatcherIndex); - } else { - mStopAllLogMatcherIndex = -1; - } - - if (simplePredicate.has_dimensions()) { - translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions); - if (mOutputDimensions.size() > 0) { - mSliced = true; - mDimensionTag = mOutputDimensions[0].mMatcher.getTag(); - } - mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions()); - } - - if (simplePredicate.initial_value() == SimplePredicate_InitialValue_FALSE) { - mInitialValue = ConditionState::kFalse; - } else { - mInitialValue = ConditionState::kUnknown; - } - - mInitialized = true; -} - -SimpleConditionTracker::~SimpleConditionTracker() { - VLOG("~SimpleConditionTracker()"); -} - -bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig, - const vector<sp<ConditionTracker>>& allConditionTrackers, - const unordered_map<int64_t, int>& conditionIdIndexMap, - vector<bool>& stack, - vector<ConditionState>& initialConditionCache) { - // SimpleConditionTracker does not have dependency on other conditions, thus we just return - // if the initialization was successful. - initialConditionCache[mIndex] = mInitialValue; - return mInitialized; -} - -void SimpleConditionTracker::dumpState() { - VLOG("%lld DUMP:", (long long)mConditionId); - for (const auto& pair : mSlicedConditionState) { - VLOG("\t%s : %d", pair.first.toString().c_str(), pair.second); - } - - VLOG("Changed to true keys: \n"); - for (const auto& key : mLastChangedToTrueDimensions) { - VLOG("%s", key.toString().c_str()); - } - VLOG("Changed to false keys: \n"); - for (const auto& key : mLastChangedToFalseDimensions) { - VLOG("%s", key.toString().c_str()); - } -} - -void SimpleConditionTracker::handleStopAll(std::vector<ConditionState>& conditionCache, - std::vector<bool>& conditionChangedCache) { - // Unless the default condition is false, and there was nothing started, otherwise we have - // triggered a condition change. - conditionChangedCache[mIndex] = - (mInitialValue == ConditionState::kFalse && mSlicedConditionState.empty()) ? false - : true; - - for (const auto& cond : mSlicedConditionState) { - if (cond.second > 0) { - mLastChangedToFalseDimensions.insert(cond.first); - } - } - - // After StopAll, we know everything has stopped. From now on, default condition is false. - mInitialValue = ConditionState::kFalse; - mSlicedConditionState.clear(); - conditionCache[mIndex] = ConditionState::kFalse; -} - -bool SimpleConditionTracker::hitGuardRail(const HashableDimensionKey& newKey) { - if (!mSliced || mSlicedConditionState.find(newKey) != mSlicedConditionState.end()) { - // if the condition is not sliced or the key is not new, we are good! - return false; - } - // 1. Report the tuple count if the tuple count > soft limit - if (mSlicedConditionState.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { - size_t newTupleCount = mSlicedConditionState.size() + 1; - StatsdStats::getInstance().noteConditionDimensionSize(mConfigKey, mConditionId, newTupleCount); - // 2. Don't add more tuples, we are above the allowed threshold. Drop the data. - if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) { - ALOGE("Predicate %lld dropping data for dimension key %s", - (long long)mConditionId, newKey.toString().c_str()); - return true; - } - } - return false; -} - -void SimpleConditionTracker::handleConditionEvent(const HashableDimensionKey& outputKey, - bool matchStart, ConditionState* conditionCache, - bool* conditionChangedCache) { - bool changed = false; - auto outputIt = mSlicedConditionState.find(outputKey); - ConditionState newCondition; - if (hitGuardRail(outputKey)) { - (*conditionChangedCache) = false; - // Tells the caller it's evaluated. - (*conditionCache) = ConditionState::kUnknown; - return; - } - if (outputIt == mSlicedConditionState.end()) { - // We get a new output key. - newCondition = matchStart ? ConditionState::kTrue : ConditionState::kFalse; - if (matchStart && mInitialValue != ConditionState::kTrue) { - mSlicedConditionState[outputKey] = 1; - changed = true; - mLastChangedToTrueDimensions.insert(outputKey); - } else if (mInitialValue != ConditionState::kFalse) { - // it's a stop and we don't have history about it. - // If the default condition is not false, it means this stop is valuable to us. - mSlicedConditionState[outputKey] = 0; - mLastChangedToFalseDimensions.insert(outputKey); - changed = true; - } - } else { - // we have history about this output key. - auto& startedCount = outputIt->second; - // assign the old value first. - newCondition = startedCount > 0 ? ConditionState::kTrue : ConditionState::kFalse; - if (matchStart) { - if (startedCount == 0) { - mLastChangedToTrueDimensions.insert(outputKey); - // This condition for this output key will change from false -> true - changed = true; - } - - // it's ok to do ++ here, even if we don't count nesting. The >1 counts will be treated - // as 1 if not counting nesting. - startedCount++; - newCondition = ConditionState::kTrue; - } else { - // This is a stop event. - if (startedCount > 0) { - if (mCountNesting) { - startedCount--; - if (startedCount == 0) { - newCondition = ConditionState::kFalse; - } - } else { - // not counting nesting, so ignore the number of starts, stop now. - startedCount = 0; - newCondition = ConditionState::kFalse; - } - // if everything has stopped for this output key, condition true -> false; - if (startedCount == 0) { - mLastChangedToFalseDimensions.insert(outputKey); - changed = true; - } - } - - // if default condition is false, it means we don't need to keep the false values. - if (mInitialValue == ConditionState::kFalse && startedCount == 0) { - mSlicedConditionState.erase(outputIt); - VLOG("erase key %s", outputKey.toString().c_str()); - } - } - } - - // dump all dimensions for debugging - if (DEBUG) { - dumpState(); - } - - (*conditionChangedCache) = changed; - (*conditionCache) = newCondition; - - VLOG("SimplePredicate %lld nonSlicedChange? %d", (long long)mConditionId, - conditionChangedCache[mIndex] == true); -} - -void SimpleConditionTracker::evaluateCondition( - const LogEvent& event, - const vector<MatchingState>& eventMatcherValues, - const vector<sp<ConditionTracker>>& mAllConditions, - vector<ConditionState>& conditionCache, - vector<bool>& conditionChangedCache) { - if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { - // it has been evaluated. - VLOG("Yes, already evaluated, %lld %d", - (long long)mConditionId, conditionCache[mIndex]); - return; - } - mLastChangedToTrueDimensions.clear(); - mLastChangedToFalseDimensions.clear(); - - if (mStopAllLogMatcherIndex >= 0 && mStopAllLogMatcherIndex < int(eventMatcherValues.size()) && - eventMatcherValues[mStopAllLogMatcherIndex] == MatchingState::kMatched) { - handleStopAll(conditionCache, conditionChangedCache); - return; - } - - int matchedState = -1; - // Note: The order to evaluate the following start, stop, stop_all matters. - // The priority of overwrite is stop_all > stop > start. - if (mStartLogMatcherIndex >= 0 && - eventMatcherValues[mStartLogMatcherIndex] == MatchingState::kMatched) { - matchedState = 1; - } - - if (mStopLogMatcherIndex >= 0 && - eventMatcherValues[mStopLogMatcherIndex] == MatchingState::kMatched) { - matchedState = 0; - } - - if (matchedState < 0) { - // The event doesn't match this condition. So we just report existing condition values. - conditionChangedCache[mIndex] = false; - if (mSliced) { - // if the condition result is sliced. The overall condition is true if any of the sliced - // condition is true - conditionCache[mIndex] = mInitialValue; - for (const auto& slicedCondition : mSlicedConditionState) { - if (slicedCondition.second > 0) { - conditionCache[mIndex] = ConditionState::kTrue; - break; - } - } - } else { - const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); - if (itr == mSlicedConditionState.end()) { - // condition not sliced, but we haven't seen the matched start or stop yet. so - // return initial value. - conditionCache[mIndex] = mInitialValue; - } else { - // return the cached condition. - conditionCache[mIndex] = - itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - } - } - return; - } - - ConditionState overallState = mInitialValue; - bool overallChanged = false; - - if (mOutputDimensions.size() == 0) { - handleConditionEvent(DEFAULT_DIMENSION_KEY, matchedState == 1, &overallState, - &overallChanged); - } else if (!mContainANYPositionInInternalDimensions) { - HashableDimensionKey outputValue; - filterValues(mOutputDimensions, event.getValues(), &outputValue); - - // If this event has multiple nodes in the attribution chain, this log event probably will - // generate multiple dimensions. If so, we will find if the condition changes for any - // dimension and ask the corresponding metric producer to verify whether the actual sliced - // condition has changed or not. - // A high level assumption is that a predicate is either sliced or unsliced. We will never - // have both sliced and unsliced version of a predicate. - handleConditionEvent(outputValue, matchedState == 1, &overallState, &overallChanged); - } else { - ALOGE("The condition tracker should not be sliced by ANY position matcher."); - } - conditionCache[mIndex] = overallState; - conditionChangedCache[mIndex] = overallChanged; -} - -void SimpleConditionTracker::isConditionMet( - const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions, - const bool isPartialLink, - vector<ConditionState>& conditionCache) const { - - if (conditionCache[mIndex] != ConditionState::kNotEvaluated) { - // it has been evaluated. - VLOG("Yes, already evaluated, %lld %d", - (long long)mConditionId, conditionCache[mIndex]); - return; - } - const auto pair = conditionParameters.find(mConditionId); - - if (pair == conditionParameters.end()) { - ConditionState conditionState = ConditionState::kNotEvaluated; - conditionState = conditionState | mInitialValue; - if (!mSliced) { - const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY); - if (itr != mSlicedConditionState.end()) { - ConditionState sliceState = - itr->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - conditionState = conditionState | sliceState; - } - } - conditionCache[mIndex] = conditionState; - return; - } - - ConditionState conditionState = ConditionState::kNotEvaluated; - const HashableDimensionKey& key = pair->second; - if (isPartialLink) { - // For unseen key, check whether the require dimensions are subset of sliced condition - // output. - conditionState = conditionState | mInitialValue; - for (const auto& slice : mSlicedConditionState) { - ConditionState sliceState = - slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - if (slice.first.contains(key)) { - conditionState = conditionState | sliceState; - } - } - } else { - auto startedCountIt = mSlicedConditionState.find(key); - conditionState = conditionState | mInitialValue; - if (startedCountIt != mSlicedConditionState.end()) { - ConditionState sliceState = - startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse; - conditionState = conditionState | sliceState; - } - - } - conditionCache[mIndex] = conditionState; - VLOG("Predicate %lld return %d", (long long)mConditionId, conditionCache[mIndex]); -} - -} // namespace statsd -} // namespace os -} // namespace android |