15154a379303ab90a2b2914676a4441917a329b5dYao Chen/* 25154a379303ab90a2b2914676a4441917a329b5dYao Chen * Copyright (C) 2017 The Android Open Source Project 35154a379303ab90a2b2914676a4441917a329b5dYao Chen * 45154a379303ab90a2b2914676a4441917a329b5dYao Chen * Licensed under the Apache License, Version 2.0 (the "License"); 55154a379303ab90a2b2914676a4441917a329b5dYao Chen * you may not use this file except in compliance with the License. 65154a379303ab90a2b2914676a4441917a329b5dYao Chen * You may obtain a copy of the License at 75154a379303ab90a2b2914676a4441917a329b5dYao Chen * 85154a379303ab90a2b2914676a4441917a329b5dYao Chen * http://www.apache.org/licenses/LICENSE-2.0 95154a379303ab90a2b2914676a4441917a329b5dYao Chen * 105154a379303ab90a2b2914676a4441917a329b5dYao Chen * Unless required by applicable law or agreed to in writing, software 115154a379303ab90a2b2914676a4441917a329b5dYao Chen * distributed under the License is distributed on an "AS IS" BASIS, 125154a379303ab90a2b2914676a4441917a329b5dYao Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135154a379303ab90a2b2914676a4441917a329b5dYao Chen * See the License for the specific language governing permissions and 145154a379303ab90a2b2914676a4441917a329b5dYao Chen * limitations under the License. 155154a379303ab90a2b2914676a4441917a329b5dYao Chen */ 165154a379303ab90a2b2914676a4441917a329b5dYao Chen 173c0b95ceb520c6b23871da90c23f89c55b76b560Yao Chen#define DEBUG false 185154a379303ab90a2b2914676a4441917a329b5dYao Chen 195154a379303ab90a2b2914676a4441917a329b5dYao Chen#include "Log.h" 205154a379303ab90a2b2914676a4441917a329b5dYao Chen#include "MaxDurationTracker.h" 21b356151e63140085cb96fa16804ee18b3862a4fcYao Chen#include "guardrail/StatsdStats.h" 225154a379303ab90a2b2914676a4441917a329b5dYao Chen 235154a379303ab90a2b2914676a4441917a329b5dYao Chennamespace android { 245154a379303ab90a2b2914676a4441917a329b5dYao Chennamespace os { 255154a379303ab90a2b2914676a4441917a329b5dYao Chennamespace statsd { 265154a379303ab90a2b2914676a4441917a329b5dYao Chen 2794e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-macMaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id, 289369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac const MetricDimensionKey& eventKey, 299369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac sp<ConditionWizard> wizard, int conditionIndex, 308a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen const vector<Matcher>& dimensionInCondition, bool nesting, 31b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t currentBucketStartNs, int64_t currentBucketNum, 32b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t startTimeNs, int64_t bucketSizeNs, 3313fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster bool conditionSliced, bool fullLink, 34857aaa520804d846a050e1eeb85d82977c983666Bookatz const vector<sp<DurationAnomalyTracker>>& anomalyTrackers) 359369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac : DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting, 3627785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs, 3713fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster conditionSliced, fullLink, anomalyTrackers) { 3813fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster if (mWizard != nullptr) { 3913fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster mSameConditionDimensionsInTracker = 4013fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster mWizard->equalOutputDimensions(conditionIndex, mDimensionInCondition); 4113fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster } 429369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac} 439369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac 44b142cc8add29c8c97f6134d35873d23db666027cYangster-macunique_ptr<DurationTracker> MaxDurationTracker::clone(const int64_t eventTime) { 459369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac auto clonedTracker = make_unique<MaxDurationTracker>(*this); 4613fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster for (auto it = clonedTracker->mInfos.begin(); it != clonedTracker->mInfos.end();) { 4713fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster if (it->second.state != kStopped) { 4813fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster it->second.lastStartTime = eventTime; 4913fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster it->second.lastDuration = 0; 5013fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster it++; 5113fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster } else { 5213fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster it = clonedTracker->mInfos.erase(it); 5313fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster } 5413fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster } 5513fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster if (clonedTracker->mInfos.empty()) { 5613fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster return nullptr; 5713fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster } else { 5813fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster return clonedTracker; 599369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac } 60b356151e63140085cb96fa16804ee18b3862a4fcYao Chen} 61b356151e63140085cb96fa16804ee18b3862a4fcYao Chen 62b356151e63140085cb96fa16804ee18b3862a4fcYao Chenbool MaxDurationTracker::hitGuardRail(const HashableDimensionKey& newKey) { 63b356151e63140085cb96fa16804ee18b3862a4fcYao Chen // ===========GuardRail============== 64b356151e63140085cb96fa16804ee18b3862a4fcYao Chen if (mInfos.find(newKey) != mInfos.end()) { 65b356151e63140085cb96fa16804ee18b3862a4fcYao Chen // if the key existed, we are good! 66b356151e63140085cb96fa16804ee18b3862a4fcYao Chen return false; 67b356151e63140085cb96fa16804ee18b3862a4fcYao Chen } 68b356151e63140085cb96fa16804ee18b3862a4fcYao Chen // 1. Report the tuple count if the tuple count > soft limit 69b356151e63140085cb96fa16804ee18b3862a4fcYao Chen if (mInfos.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { 70b356151e63140085cb96fa16804ee18b3862a4fcYao Chen size_t newTupleCount = mInfos.size() + 1; 718a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mTrackerId, newTupleCount); 72b356151e63140085cb96fa16804ee18b3862a4fcYao Chen // 2. Don't add more tuples, we are above the allowed threshold. Drop the data. 73b356151e63140085cb96fa16804ee18b3862a4fcYao Chen if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) { 7494e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac ALOGE("MaxDurTracker %lld dropping data for dimension key %s", 7513fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster (long long)mTrackerId, newKey.toString().c_str()); 76b356151e63140085cb96fa16804ee18b3862a4fcYao Chen return true; 77b356151e63140085cb96fa16804ee18b3862a4fcYao Chen } 78b356151e63140085cb96fa16804ee18b3862a4fcYao Chen } 79b356151e63140085cb96fa16804ee18b3862a4fcYao Chen return false; 805154a379303ab90a2b2914676a4441917a329b5dYao Chen} 815154a379303ab90a2b2914676a4441917a329b5dYao Chen 825154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid MaxDurationTracker::noteStart(const HashableDimensionKey& key, bool condition, 83b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t eventTime, const ConditionKey& conditionKey) { 845154a379303ab90a2b2914676a4441917a329b5dYao Chen // this will construct a new DurationInfo if this key didn't exist. 85b356151e63140085cb96fa16804ee18b3862a4fcYao Chen if (hitGuardRail(key)) { 86b356151e63140085cb96fa16804ee18b3862a4fcYao Chen return; 87b356151e63140085cb96fa16804ee18b3862a4fcYao Chen } 88b356151e63140085cb96fa16804ee18b3862a4fcYao Chen 895154a379303ab90a2b2914676a4441917a329b5dYao Chen DurationInfo& duration = mInfos[key]; 90d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen if (mConditionSliced) { 91d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen duration.conditionKeys = conditionKey; 92d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen } 9313fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster VLOG("MaxDuration: key %s start condition %d", key.toString().c_str(), condition); 945154a379303ab90a2b2914676a4441917a329b5dYao Chen 955154a379303ab90a2b2914676a4441917a329b5dYao Chen switch (duration.state) { 965154a379303ab90a2b2914676a4441917a329b5dYao Chen case kStarted: 970ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.startCount++; 985154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 995154a379303ab90a2b2914676a4441917a329b5dYao Chen case kPaused: 1000ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.startCount++; 1015154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 1025154a379303ab90a2b2914676a4441917a329b5dYao Chen case kStopped: 1035154a379303ab90a2b2914676a4441917a329b5dYao Chen if (!condition) { 1045154a379303ab90a2b2914676a4441917a329b5dYao Chen // event started, but we need to wait for the condition to become true. 1055154a379303ab90a2b2914676a4441917a329b5dYao Chen duration.state = DurationState::kPaused; 1065154a379303ab90a2b2914676a4441917a329b5dYao Chen } else { 1075154a379303ab90a2b2914676a4441917a329b5dYao Chen duration.state = DurationState::kStarted; 1085154a379303ab90a2b2914676a4441917a329b5dYao Chen duration.lastStartTime = eventTime; 1092e414b99f44f00000d84765b3a095490415695afDavid Chen startAnomalyAlarm(eventTime); 1105154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1110ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.startCount = 1; 1125154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 1135154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1145154a379303ab90a2b2914676a4441917a329b5dYao Chen} 1155154a379303ab90a2b2914676a4441917a329b5dYao Chen 116e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 117b142cc8add29c8c97f6134d35873d23db666027cYangster-macvoid MaxDurationTracker::noteStop(const HashableDimensionKey& key, const int64_t eventTime, 1180ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen bool forceStop) { 11913fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster VLOG("MaxDuration: key %s stop", key.toString().c_str()); 1205154a379303ab90a2b2914676a4441917a329b5dYao Chen if (mInfos.find(key) == mInfos.end()) { 1215154a379303ab90a2b2914676a4441917a329b5dYao Chen // we didn't see a start event before. do nothing. 1225154a379303ab90a2b2914676a4441917a329b5dYao Chen return; 1235154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1245154a379303ab90a2b2914676a4441917a329b5dYao Chen DurationInfo& duration = mInfos[key]; 1255154a379303ab90a2b2914676a4441917a329b5dYao Chen 1265154a379303ab90a2b2914676a4441917a329b5dYao Chen switch (duration.state) { 1275154a379303ab90a2b2914676a4441917a329b5dYao Chen case DurationState::kStopped: 1285154a379303ab90a2b2914676a4441917a329b5dYao Chen // already stopped, do nothing. 1295154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 1305154a379303ab90a2b2914676a4441917a329b5dYao Chen case DurationState::kStarted: { 1310ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.startCount--; 1320ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen if (forceStop || !mNested || duration.startCount <= 0) { 1333e8cd35b551827234aa115700e50abb6c4721597Bookatz stopAnomalyAlarm(eventTime); 1340ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.state = DurationState::kStopped; 1350ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen int64_t durationTime = eventTime - duration.lastStartTime; 13613fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster VLOG("Max, key %s, Stop %lld %lld %lld", key.toString().c_str(), 1370ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen (long long)duration.lastStartTime, (long long)eventTime, 1380ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen (long long)durationTime); 13927785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen duration.lastDuration += durationTime; 1402e414b99f44f00000d84765b3a095490415695afDavid Chen if (anyStarted()) { 1412e414b99f44f00000d84765b3a095490415695afDavid Chen // In case any other dimensions are still started, we need to keep the alarm 1422e414b99f44f00000d84765b3a095490415695afDavid Chen // set. 1432e414b99f44f00000d84765b3a095490415695afDavid Chen startAnomalyAlarm(eventTime); 1442e414b99f44f00000d84765b3a095490415695afDavid Chen } 1450ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen VLOG(" record duration: %lld ", (long long)duration.lastDuration); 1460ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen } 1475154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 1485154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1495154a379303ab90a2b2914676a4441917a329b5dYao Chen case DurationState::kPaused: { 1500ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.startCount--; 1510ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen if (forceStop || !mNested || duration.startCount <= 0) { 1520ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen duration.state = DurationState::kStopped; 1530ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen } 1545154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 1555154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1565154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1575154a379303ab90a2b2914676a4441917a329b5dYao Chen 1585154a379303ab90a2b2914676a4441917a329b5dYao Chen if (duration.lastDuration > mDuration) { 1595154a379303ab90a2b2914676a4441917a329b5dYao Chen mDuration = duration.lastDuration; 1605154a379303ab90a2b2914676a4441917a329b5dYao Chen VLOG("Max: new max duration: %lld", (long long)mDuration); 1615154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1625154a379303ab90a2b2914676a4441917a329b5dYao Chen // Once an atom duration ends, we erase it. Next time, if we see another atom event with the 1635154a379303ab90a2b2914676a4441917a329b5dYao Chen // same name, they are still considered as different atom durations. 1640ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen if (duration.state == DurationState::kStopped) { 1650ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen mInfos.erase(key); 1660ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen } 1675154a379303ab90a2b2914676a4441917a329b5dYao Chen} 168e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1692e414b99f44f00000d84765b3a095490415695afDavid Chenbool MaxDurationTracker::anyStarted() { 1702e414b99f44f00000d84765b3a095490415695afDavid Chen for (auto& pair : mInfos) { 1712e414b99f44f00000d84765b3a095490415695afDavid Chen if (pair.second.state == kStarted) { 1722e414b99f44f00000d84765b3a095490415695afDavid Chen return true; 1732e414b99f44f00000d84765b3a095490415695afDavid Chen } 1742e414b99f44f00000d84765b3a095490415695afDavid Chen } 1752e414b99f44f00000d84765b3a095490415695afDavid Chen return false; 1762e414b99f44f00000d84765b3a095490415695afDavid Chen} 1772e414b99f44f00000d84765b3a095490415695afDavid Chen 178b142cc8add29c8c97f6134d35873d23db666027cYangster-macvoid MaxDurationTracker::noteStopAll(const int64_t eventTime) { 179e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac std::set<HashableDimensionKey> keys; 180e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac for (const auto& pair : mInfos) { 181e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac keys.insert(pair.first); 182e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 183e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac for (auto& key : keys) { 184e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac noteStop(key, eventTime, true); 1855154a379303ab90a2b2914676a4441917a329b5dYao Chen } 1865154a379303ab90a2b2914676a4441917a329b5dYao Chen} 1875154a379303ab90a2b2914676a4441917a329b5dYao Chen 18827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chenbool MaxDurationTracker::flushCurrentBucket( 189b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t& eventTimeNs, 19027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) { 1915154a379303ab90a2b2914676a4441917a329b5dYao Chen VLOG("MaxDurationTracker flushing....."); 1925154a379303ab90a2b2914676a4441917a329b5dYao Chen 1935154a379303ab90a2b2914676a4441917a329b5dYao Chen // adjust the bucket start time 19427785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen int numBucketsForward = 0; 195b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t fullBucketEnd = getCurrentBucketEndTimeNs(); 196b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t currentBucketEndTimeNs; 19727785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen if (eventTimeNs >= fullBucketEnd) { 19827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen numBucketsForward = 1 + (eventTimeNs - fullBucketEnd) / mBucketSizeNs; 19927785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen currentBucketEndTimeNs = fullBucketEnd; 20027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen } else { 20127785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // This must be a partial bucket. 20227785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen currentBucketEndTimeNs = eventTimeNs; 20327785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen } 2045154a379303ab90a2b2914676a4441917a329b5dYao Chen 2055154a379303ab90a2b2914676a4441917a329b5dYao Chen bool hasPendingEvent = 2065154a379303ab90a2b2914676a4441917a329b5dYao Chen false; // has either a kStarted or kPaused event across bucket boundaries 20727785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // meaning we need to carry them over to the new bucket. 20859cc0a2237fe0527c9871f0236e9bc76146990b7Yao Chen for (auto it = mInfos.begin(); it != mInfos.end();) { 2095154a379303ab90a2b2914676a4441917a329b5dYao Chen if (it->second.state == DurationState::kStopped) { 2105154a379303ab90a2b2914676a4441917a329b5dYao Chen // No need to keep buckets for events that were stopped before. 21159cc0a2237fe0527c9871f0236e9bc76146990b7Yao Chen it = mInfos.erase(it); 2125154a379303ab90a2b2914676a4441917a329b5dYao Chen } else { 21359cc0a2237fe0527c9871f0236e9bc76146990b7Yao Chen ++it; 2145154a379303ab90a2b2914676a4441917a329b5dYao Chen hasPendingEvent = true; 2155154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2165154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2175154a379303ab90a2b2914676a4441917a329b5dYao Chen 21827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // mDuration is updated in noteStop to the maximum duration that ended in the current bucket. 2195154a379303ab90a2b2914676a4441917a329b5dYao Chen if (mDuration != 0) { 22027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen DurationBucket info; 22127785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen info.mBucketStartNs = mCurrentBucketStartTimeNs; 22227785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen info.mBucketEndNs = currentBucketEndTimeNs; 2232b0f88678b2877a8e9f83cea60f097322b078367yro info.mDuration = mDuration; 224f60e0bad5908c51c954ca8dc763c8efd394c56dcYao Chen (*output)[mEventKey].push_back(info); 2255154a379303ab90a2b2914676a4441917a329b5dYao Chen VLOG(" final duration for last bucket: %lld", (long long)mDuration); 2265154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2275154a379303ab90a2b2914676a4441917a329b5dYao Chen 22827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen if (numBucketsForward > 0) { 22927785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mCurrentBucketStartTimeNs = fullBucketEnd + (numBucketsForward - 1) * mBucketSizeNs; 23027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mCurrentBucketNum += numBucketsForward; 23127785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen } else { // We must be forming a partial bucket. 23227785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mCurrentBucketStartTimeNs = eventTimeNs; 2335154a379303ab90a2b2914676a4441917a329b5dYao Chen } 234e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 23527785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mDuration = 0; 2365154a379303ab90a2b2914676a4441917a329b5dYao Chen // If this tracker has no pending events, tell owner to remove. 2375154a379303ab90a2b2914676a4441917a329b5dYao Chen return !hasPendingEvent; 2385154a379303ab90a2b2914676a4441917a329b5dYao Chen} 2395154a379303ab90a2b2914676a4441917a329b5dYao Chen 24027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chenbool MaxDurationTracker::flushIfNeeded( 241b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) { 24227785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen if (eventTimeNs < getCurrentBucketEndTimeNs()) { 24327785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen return false; 24427785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen } 24527785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen return flushCurrentBucket(eventTimeNs, output); 24627785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen} 24727785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen 248427d372552490a2c5ac4041fe345b15f69451f57Yao Chenvoid MaxDurationTracker::onSlicedConditionMayChange(bool overallCondition, 249b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t timestamp) { 2505154a379303ab90a2b2914676a4441917a329b5dYao Chen // Now for each of the on-going event, check if the condition has changed for them. 2515154a379303ab90a2b2914676a4441917a329b5dYao Chen for (auto& pair : mInfos) { 2525154a379303ab90a2b2914676a4441917a329b5dYao Chen if (pair.second.state == kStopped) { 2535154a379303ab90a2b2914676a4441917a329b5dYao Chen continue; 2545154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2559369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac std::unordered_set<HashableDimensionKey> conditionDimensionKeySet; 2569369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac ConditionState conditionState = mWizard->query( 2579369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac mConditionTrackerIndex, pair.second.conditionKeys, mDimensionInCondition, 25813fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster !mSameConditionDimensionsInTracker, 25913fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster !mHasLinksToAllConditionDimensionsInTracker, 2609369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac &conditionDimensionKeySet); 2618a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen bool conditionMet = 2628a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen (conditionState == ConditionState::kTrue) && 2638a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen (mDimensionInCondition.size() == 0 || 2648a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen conditionDimensionKeySet.find(mEventKey.getDimensionKeyInCondition()) != 2658a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen conditionDimensionKeySet.end()); 26613fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster VLOG("key: %s, condition: %d", pair.first.toString().c_str(), conditionMet); 2675154a379303ab90a2b2914676a4441917a329b5dYao Chen noteConditionChanged(pair.first, conditionMet, timestamp); 2685154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2695154a379303ab90a2b2914676a4441917a329b5dYao Chen} 2705154a379303ab90a2b2914676a4441917a329b5dYao Chen 271b142cc8add29c8c97f6134d35873d23db666027cYangster-macvoid MaxDurationTracker::onConditionChanged(bool condition, const int64_t timestamp) { 2725154a379303ab90a2b2914676a4441917a329b5dYao Chen for (auto& pair : mInfos) { 2735154a379303ab90a2b2914676a4441917a329b5dYao Chen noteConditionChanged(pair.first, condition, timestamp); 2745154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2755154a379303ab90a2b2914676a4441917a329b5dYao Chen} 2765154a379303ab90a2b2914676a4441917a329b5dYao Chen 2775154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid MaxDurationTracker::noteConditionChanged(const HashableDimensionKey& key, bool conditionMet, 278b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t timestamp) { 2795154a379303ab90a2b2914676a4441917a329b5dYao Chen auto it = mInfos.find(key); 2805154a379303ab90a2b2914676a4441917a329b5dYao Chen if (it == mInfos.end()) { 2815154a379303ab90a2b2914676a4441917a329b5dYao Chen return; 2825154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2835154a379303ab90a2b2914676a4441917a329b5dYao Chen 2845154a379303ab90a2b2914676a4441917a329b5dYao Chen switch (it->second.state) { 2855154a379303ab90a2b2914676a4441917a329b5dYao Chen case kStarted: 2862e414b99f44f00000d84765b3a095490415695afDavid Chen // If condition becomes false, kStarted -> kPaused. Record the current duration and 2872e414b99f44f00000d84765b3a095490415695afDavid Chen // stop anomaly alarm. 2885154a379303ab90a2b2914676a4441917a329b5dYao Chen if (!conditionMet) { 2893e8cd35b551827234aa115700e50abb6c4721597Bookatz stopAnomalyAlarm(timestamp); 2905154a379303ab90a2b2914676a4441917a329b5dYao Chen it->second.state = DurationState::kPaused; 2915154a379303ab90a2b2914676a4441917a329b5dYao Chen it->second.lastDuration += (timestamp - it->second.lastStartTime); 2922e414b99f44f00000d84765b3a095490415695afDavid Chen if (anyStarted()) { 2932e414b99f44f00000d84765b3a095490415695afDavid Chen // In case any other dimensions are still started, we need to set the alarm. 2942e414b99f44f00000d84765b3a095490415695afDavid Chen startAnomalyAlarm(timestamp); 2952e414b99f44f00000d84765b3a095490415695afDavid Chen } 29613fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster VLOG("MaxDurationTracker Key: %s Started->Paused ", key.toString().c_str()); 2975154a379303ab90a2b2914676a4441917a329b5dYao Chen } 2985154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 2995154a379303ab90a2b2914676a4441917a329b5dYao Chen case kStopped: 3002e414b99f44f00000d84765b3a095490415695afDavid Chen // Nothing to do if it's stopped. 3015154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 3025154a379303ab90a2b2914676a4441917a329b5dYao Chen case kPaused: 3032e414b99f44f00000d84765b3a095490415695afDavid Chen // If condition becomes true, kPaused -> kStarted. and the start time is the condition 3045154a379303ab90a2b2914676a4441917a329b5dYao Chen // change time. 3055154a379303ab90a2b2914676a4441917a329b5dYao Chen if (conditionMet) { 3065154a379303ab90a2b2914676a4441917a329b5dYao Chen it->second.state = DurationState::kStarted; 3075154a379303ab90a2b2914676a4441917a329b5dYao Chen it->second.lastStartTime = timestamp; 3082e414b99f44f00000d84765b3a095490415695afDavid Chen startAnomalyAlarm(timestamp); 30913fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster VLOG("MaxDurationTracker Key: %s Paused->Started", key.toString().c_str()); 3105154a379303ab90a2b2914676a4441917a329b5dYao Chen } 3115154a379303ab90a2b2914676a4441917a329b5dYao Chen break; 3125154a379303ab90a2b2914676a4441917a329b5dYao Chen } 3132e414b99f44f00000d84765b3a095490415695afDavid Chen // Note that we don't update mDuration here since it's only updated during noteStop. 314e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac} 315e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 316857aaa520804d846a050e1eeb85d82977c983666Bookatzint64_t MaxDurationTracker::predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, 317be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac const int64_t currentTimestamp) const { 3182e414b99f44f00000d84765b3a095490415695afDavid Chen // The allowed time we can continue in the current state is the 3192e414b99f44f00000d84765b3a095490415695afDavid Chen // (anomaly threshold) - max(elapsed time of the started mInfos). 3202e414b99f44f00000d84765b3a095490415695afDavid Chen int64_t maxElapsed = 0; 3212e414b99f44f00000d84765b3a095490415695afDavid Chen for (auto it = mInfos.begin(); it != mInfos.end(); ++it) { 3222e414b99f44f00000d84765b3a095490415695afDavid Chen if (it->second.state == DurationState::kStarted) { 3232e414b99f44f00000d84765b3a095490415695afDavid Chen int64_t duration = 3242e414b99f44f00000d84765b3a095490415695afDavid Chen it->second.lastDuration + (currentTimestamp - it->second.lastStartTime); 3252e414b99f44f00000d84765b3a095490415695afDavid Chen if (duration > maxElapsed) { 3262e414b99f44f00000d84765b3a095490415695afDavid Chen maxElapsed = duration; 3272e414b99f44f00000d84765b3a095490415695afDavid Chen } 3282e414b99f44f00000d84765b3a095490415695afDavid Chen } 3292e414b99f44f00000d84765b3a095490415695afDavid Chen } 3300dbc7a434345fa318ee129eaa5cf83681de4936bBookatz int64_t anomalyTimeNs = currentTimestamp + anomalyTracker.getAnomalyThreshold() - maxElapsed; 3310dbc7a434345fa318ee129eaa5cf83681de4936bBookatz int64_t refractoryEndNs = anomalyTracker.getRefractoryPeriodEndsSec(mEventKey) * NS_PER_SEC; 3320dbc7a434345fa318ee129eaa5cf83681de4936bBookatz return std::max(anomalyTimeNs, refractoryEndNs); 3335154a379303ab90a2b2914676a4441917a329b5dYao Chen} 3345154a379303ab90a2b2914676a4441917a329b5dYao Chen 335884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chenvoid MaxDurationTracker::dumpStates(FILE* out, bool verbose) const { 336884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen fprintf(out, "\t\t sub-durations %lu\n", (unsigned long)mInfos.size()); 337884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen fprintf(out, "\t\t current duration %lld\n", (long long)mDuration); 338884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen} 339884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen 3405154a379303ab90a2b2914676a4441917a329b5dYao Chen} // namespace statsd 3415154a379303ab90a2b2914676a4441917a329b5dYao Chen} // namespace os 3422b0f88678b2877a8e9f83cea60f097322b078367yro} // namespace android 343