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 175154a379303ab90a2b2914676a4441917a329b5dYao Chen#ifndef DURATION_TRACKER_H 185154a379303ab90a2b2914676a4441917a329b5dYao Chen#define DURATION_TRACKER_H 195154a379303ab90a2b2914676a4441917a329b5dYao Chen 20857aaa520804d846a050e1eeb85d82977c983666Bookatz#include "anomaly/DurationAnomalyTracker.h" 215154a379303ab90a2b2914676a4441917a329b5dYao Chen#include "condition/ConditionWizard.h" 22b356151e63140085cb96fa16804ee18b3862a4fcYao Chen#include "config/ConfigKey.h" 235154a379303ab90a2b2914676a4441917a329b5dYao Chen#include "stats_util.h" 245154a379303ab90a2b2914676a4441917a329b5dYao Chen 255154a379303ab90a2b2914676a4441917a329b5dYao Chennamespace android { 265154a379303ab90a2b2914676a4441917a329b5dYao Chennamespace os { 275154a379303ab90a2b2914676a4441917a329b5dYao Chennamespace statsd { 285154a379303ab90a2b2914676a4441917a329b5dYao Chen 295154a379303ab90a2b2914676a4441917a329b5dYao Chenenum DurationState { 305154a379303ab90a2b2914676a4441917a329b5dYao Chen kStopped = 0, // The event is stopped. 315154a379303ab90a2b2914676a4441917a329b5dYao Chen kStarted = 1, // The event is on going. 325154a379303ab90a2b2914676a4441917a329b5dYao Chen kPaused = 2, // The event is started, but condition is false, clock is paused. When condition 335154a379303ab90a2b2914676a4441917a329b5dYao Chen // turns to true, kPaused will become kStarted. 345154a379303ab90a2b2914676a4441917a329b5dYao Chen}; 355154a379303ab90a2b2914676a4441917a329b5dYao Chen 365154a379303ab90a2b2914676a4441917a329b5dYao Chen// Hold duration information for one atom level duration in current on-going bucket. 375154a379303ab90a2b2914676a4441917a329b5dYao Chenstruct DurationInfo { 385154a379303ab90a2b2914676a4441917a329b5dYao Chen DurationState state; 390ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen 400ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen // the number of starts seen. 410ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen int32_t startCount; 420ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen 435154a379303ab90a2b2914676a4441917a329b5dYao Chen // most recent start time. 445154a379303ab90a2b2914676a4441917a329b5dYao Chen int64_t lastStartTime; 455154a379303ab90a2b2914676a4441917a329b5dYao Chen // existing duration in current bucket. 465154a379303ab90a2b2914676a4441917a329b5dYao Chen int64_t lastDuration; 475154a379303ab90a2b2914676a4441917a329b5dYao Chen // TODO: Optimize the way we track sliced condition in duration metrics. 485154a379303ab90a2b2914676a4441917a329b5dYao Chen // cache the HashableDimensionKeys we need to query the condition for this duration event. 495154a379303ab90a2b2914676a4441917a329b5dYao Chen ConditionKey conditionKeys; 505154a379303ab90a2b2914676a4441917a329b5dYao Chen 510ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen DurationInfo() : state(kStopped), startCount(0), lastStartTime(0), lastDuration(0){}; 525154a379303ab90a2b2914676a4441917a329b5dYao Chen}; 535154a379303ab90a2b2914676a4441917a329b5dYao Chen 542b0f88678b2877a8e9f83cea60f097322b078367yrostruct DurationBucket { 55b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t mBucketStartNs; 56b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t mBucketEndNs; 57b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t mDuration; 582b0f88678b2877a8e9f83cea60f097322b078367yro}; 592b0f88678b2877a8e9f83cea60f097322b078367yro 605154a379303ab90a2b2914676a4441917a329b5dYao Chenclass DurationTracker { 615154a379303ab90a2b2914676a4441917a329b5dYao Chenpublic: 629369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey, 639369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac sp<ConditionWizard> wizard, int conditionIndex, 648a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen const std::vector<Matcher>& dimensionInCondition, bool nesting, 65b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs, 66b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t bucketSizeNs, bool conditionSliced, bool fullLink, 67857aaa520804d846a050e1eeb85d82977c983666Bookatz const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers) 68b356151e63140085cb96fa16804ee18b3862a4fcYao Chen : mConfigKey(key), 6994e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac mTrackerId(id), 70b356151e63140085cb96fa16804ee18b3862a4fcYao Chen mEventKey(eventKey), 71e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac mWizard(wizard), 725154a379303ab90a2b2914676a4441917a329b5dYao Chen mConditionTrackerIndex(conditionIndex), 735154a379303ab90a2b2914676a4441917a329b5dYao Chen mBucketSizeNs(bucketSizeNs), 749369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac mDimensionInCondition(dimensionInCondition), 750ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen mNested(nesting), 760ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen mCurrentBucketStartTimeNs(currentBucketStartNs), 77e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac mDuration(0), 7827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mDurationFullBucket(0), 7927785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mCurrentBucketNum(currentBucketNum), 8027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen mStartTimeNs(startTimeNs), 81d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen mConditionSliced(conditionSliced), 8213fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster mHasLinksToAllConditionDimensionsInTracker(fullLink), 83e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac mAnomalyTrackers(anomalyTrackers){}; 847c334a129e93e405a72e8299a1cd928af079d14fYangster 855154a379303ab90a2b2914676a4441917a329b5dYao Chen virtual ~DurationTracker(){}; 867c334a129e93e405a72e8299a1cd928af079d14fYangster 87b142cc8add29c8c97f6134d35873d23db666027cYangster-mac virtual unique_ptr<DurationTracker> clone(const int64_t eventTime) = 0; 889369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac 895154a379303ab90a2b2914676a4441917a329b5dYao Chen virtual void noteStart(const HashableDimensionKey& key, bool condition, 90b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t eventTime, const ConditionKey& conditionKey) = 0; 91b142cc8add29c8c97f6134d35873d23db666027cYangster-mac virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime, 920ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen const bool stopAll) = 0; 93b142cc8add29c8c97f6134d35873d23db666027cYangster-mac virtual void noteStopAll(const int64_t eventTime) = 0; 947c334a129e93e405a72e8299a1cd928af079d14fYangster 95b142cc8add29c8c97f6134d35873d23db666027cYangster-mac virtual void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) = 0; 96b142cc8add29c8c97f6134d35873d23db666027cYangster-mac virtual void onConditionChanged(bool condition, const int64_t timestamp) = 0; 977c334a129e93e405a72e8299a1cd928af079d14fYangster 985154a379303ab90a2b2914676a4441917a329b5dYao Chen // Flush stale buckets if needed, and return true if the tracker has no on-going duration 995154a379303ab90a2b2914676a4441917a329b5dYao Chen // events, so that the owner can safely remove the tracker. 100f60e0bad5908c51c954ca8dc763c8efd394c56dcYao Chen virtual bool flushIfNeeded( 101b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t timestampNs, 1029369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0; 1035154a379303ab90a2b2914676a4441917a329b5dYao Chen 10427785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // Should only be called during an app upgrade or from this tracker's flushIfNeeded. If from 10527785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // an app upgrade, we assume that we're trying to form a partial bucket. 10627785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen virtual bool flushCurrentBucket( 107b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t& eventTimeNs, 10827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0; 10927785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen 110e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Predict the anomaly timestamp given the current status. 111857aaa520804d846a050e1eeb85d82977c983666Bookatz virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker, 112be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac const int64_t currentTimestamp) const = 0; 113884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen // Dump internal states for debugging 114884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen virtual void dumpStates(FILE* out, bool verbose) const = 0; 115e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1169369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac void setEventKey(const MetricDimensionKey& eventKey) { 1179369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac mEventKey = eventKey; 1189369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac } 1199369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac 1205154a379303ab90a2b2914676a4441917a329b5dYao Chenprotected: 121b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t getCurrentBucketEndTimeNs() const { 122be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs; 123be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac } 124be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac 125e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac // Starts the anomaly alarm. 126b142cc8add29c8c97f6134d35873d23db666027cYangster-mac void startAnomalyAlarm(const int64_t eventTime) { 127e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac for (auto& anomalyTracker : mAnomalyTrackers) { 128e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac if (anomalyTracker != nullptr) { 129b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t alarmTimestampNs = 130be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac predictAnomalyTimestampNs(*anomalyTracker, eventTime); 131be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac if (alarmTimestampNs > 0) { 132be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac anomalyTracker->startAlarm(mEventKey, alarmTimestampNs); 133be10ddfe46ba6371bcd02cb57a06782e6b18d371Yangster-mac } 134e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 135e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 136e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 137e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1383e8cd35b551827234aa115700e50abb6c4721597Bookatz // Stops the anomaly alarm. If it should have already fired, declare the anomaly now. 139b142cc8add29c8c97f6134d35873d23db666027cYangster-mac void stopAnomalyAlarm(const int64_t timestamp) { 140e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac for (auto& anomalyTracker : mAnomalyTrackers) { 141e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac if (anomalyTracker != nullptr) { 1423e8cd35b551827234aa115700e50abb6c4721597Bookatz anomalyTracker->stopAlarm(mEventKey, timestamp); 143e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 144e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 145e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 146e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 147e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac void addPastBucketToAnomalyTrackers(const int64_t& bucketValue, const int64_t& bucketNum) { 148e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac for (auto& anomalyTracker : mAnomalyTrackers) { 149e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac if (anomalyTracker != nullptr) { 150e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker->addPastBucket(mEventKey, bucketValue, bucketNum); 151e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 152e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 153e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 154e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 155b142cc8add29c8c97f6134d35873d23db666027cYangster-mac void detectAndDeclareAnomaly(const int64_t& timestamp, const int64_t& currBucketNum, 156e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac const int64_t& currentBucketValue) { 157e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac for (auto& anomalyTracker : mAnomalyTrackers) { 158e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac if (anomalyTracker != nullptr) { 159e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mEventKey, 160e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac currentBucketValue); 161e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 162e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 163e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac } 164e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 16527785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // Convenience to compute the current bucket's end time, which is always aligned with the 16627785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen // start time of the metric. 167b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t getCurrentBucketEndTimeNs() { 16827785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs; 16927785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen } 17027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen 171b356151e63140085cb96fa16804ee18b3862a4fcYao Chen // A reference to the DurationMetricProducer's config key. 172b356151e63140085cb96fa16804ee18b3862a4fcYao Chen const ConfigKey& mConfigKey; 173b356151e63140085cb96fa16804ee18b3862a4fcYao Chen 17494e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac const int64_t mTrackerId; 175e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1769369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac MetricDimensionKey mEventKey; 177e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 1785154a379303ab90a2b2914676a4441917a329b5dYao Chen sp<ConditionWizard> mWizard; 1795154a379303ab90a2b2914676a4441917a329b5dYao Chen 1800ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen const int mConditionTrackerIndex; 1815154a379303ab90a2b2914676a4441917a329b5dYao Chen 1820ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen const int64_t mBucketSizeNs; 1830ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen 1848a8d16ceea1e5b7a2f8c41e17b5d993035f50f5dYao Chen const std::vector<Matcher>& mDimensionInCondition; 1859369446f0b04945d6674550728ae81196d6fb5c2Yangster-mac 1860ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen const bool mNested; 1875154a379303ab90a2b2914676a4441917a329b5dYao Chen 188b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t mCurrentBucketStartTimeNs; 1895154a379303ab90a2b2914676a4441917a329b5dYao Chen 19027785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen int64_t mDuration; // current recorded duration result (for partial bucket) 19127785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen 19227785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen int64_t mDurationFullBucket; // Sum of past partial buckets in current full bucket. 193e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 194b142cc8add29c8c97f6134d35873d23db666027cYangster-mac int64_t mCurrentBucketNum; 195e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 196b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const int64_t mStartTimeNs; 19727785a8a4a684c831c18f7189a6fa1b98c3573e6David Chen 198d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen const bool mConditionSliced; 199d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen 20013fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster bool mSameConditionDimensionsInTracker; 20113fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster bool mHasLinksToAllConditionDimensionsInTracker; 20213fb7e4eeaf7aee408821afe7ee55a5167e49e59Yangster 203857aaa520804d846a050e1eeb85d82977c983666Bookatz std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers; 204e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac 205e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp); 2061bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm); 2071bf94382d036fa8d61258205c5f4e18cd53cb61dBookatz FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm); 2085154a379303ab90a2b2914676a4441917a329b5dYao Chen}; 2095154a379303ab90a2b2914676a4441917a329b5dYao Chen 2105154a379303ab90a2b2914676a4441917a329b5dYao Chen} // namespace statsd 2115154a379303ab90a2b2914676a4441917a329b5dYao Chen} // namespace os 2125154a379303ab90a2b2914676a4441917a329b5dYao Chen} // namespace android 2135154a379303ab90a2b2914676a4441917a329b5dYao Chen 2142b0f88678b2877a8e9f83cea60f097322b078367yro#endif // DURATION_TRACKER_H 215