Loading cmds/statsd/Android.mk +3 −1 Original line number Diff line number Diff line Loading @@ -206,7 +206,9 @@ LOCAL_SRC_FILES := \ tests/e2e/GaugeMetric_e2e_push_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \ tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp \ tests/e2e/Anomaly_count_e2e_test.cpp \ tests/e2e/Anomaly_duration_sum_e2e_test.cpp LOCAL_STATIC_LIBRARIES := \ $(statsd_common_static_libraries) \ Loading cmds/statsd/src/StatsLogProcessor.h +10 −3 Original line number Diff line number Diff line Loading @@ -69,6 +69,11 @@ public: void dumpStates(FILE* out, bool verbose); private: // For testing only. inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const { return mAnomalyAlarmMonitor; } mutable mutex mMetricsMutex; std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers; Loading Loading @@ -133,13 +138,15 @@ private: FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); }; } // namespace statsd Loading cmds/statsd/src/anomaly/AnomalyTracker.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -66,6 +66,9 @@ size_t AnomalyTracker::index(int64_t bucketNum) const { void AnomalyTracker::advanceMostRecentBucketTo(const int64_t& bucketNum) { VLOG("advanceMostRecentBucketTo() called."); if (mNumOfPastBuckets <= 0) { return; } if (bucketNum <= mMostRecentBucketNum) { ALOGW("Cannot advance buckets backwards (bucketNum=%lld but mMostRecentBucketNum=%lld)", (long long)bucketNum, (long long)mMostRecentBucketNum); Loading Loading @@ -170,7 +173,8 @@ void AnomalyTracker::addBucketToSum(const shared_ptr<DimToValMap>& bucket) { int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key, const int64_t& bucketNum) const { if (bucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets if (bucketNum < 0 || mMostRecentBucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets || bucketNum > mMostRecentBucketNum) { return 0; } Loading Loading @@ -241,14 +245,10 @@ void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs, } bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key) { const MetricDimensionKey& key) const { const auto& it = mRefractoryPeriodEndsSec.find(key); if (it != mRefractoryPeriodEndsSec.end()) { if (timestampNs < it->second * NS_PER_SEC) { return true; } else { mRefractoryPeriodEndsSec.erase(key); } return timestampNs < it->second * NS_PER_SEC; } return false; } Loading cmds/statsd/src/anomaly/AnomalyTracker.h +11 −2 Original line number Diff line number Diff line Loading @@ -113,6 +113,13 @@ public: } protected: // For testing only. // Returns the alarm timestamp in seconds for the query dimension if it exists. Otherwise // returns 0. virtual uint32_t getAlarmTimestampSec(const MetricDimensionKey& dimensionKey) const { return 0; // The base AnomalyTracker class doesn't have alarms. } // statsd_config.proto Alert message that defines this tracker. const Alert mAlert; Loading Loading @@ -159,8 +166,7 @@ protected: void subtractValueFromSum(const MetricDimensionKey& key, const int64_t& bucketValue); // Returns true if in the refractory period, else false. // If there is a stored refractory period but it ended prior to timestampNs, it is removed. bool isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key); bool isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key) const; // Calculates the corresponding bucket index within the circular array. // Requires bucketNum >= 0. Loading @@ -176,6 +182,9 @@ protected: FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets); FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection); FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); }; } // namespace statsd Loading cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -40,9 +40,8 @@ void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, // Alarms are stored in secs. Must round up, since if it fires early, it is ignored completely. uint32_t timestampSec = static_cast<uint32_t>((timestampNs -1) / NS_PER_SEC) + 1; // round up if (isInRefractoryPeriod(timestampNs, dimensionKey)) { // TODO: Bug! By the refractory's end, the data might be erased and the alarm inapplicable. VLOG("Setting a delayed anomaly alarm lest it fall in the refractory period"); timestampSec = getRefractoryPeriodEndsSec(dimensionKey) + 1; VLOG("Not setting anomaly alarm since it would fall in the refractory period."); return; } auto itr = mAlarms.find(dimensionKey); Loading Loading
cmds/statsd/Android.mk +3 −1 Original line number Diff line number Diff line Loading @@ -206,7 +206,9 @@ LOCAL_SRC_FILES := \ tests/e2e/GaugeMetric_e2e_push_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \ tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp \ tests/e2e/Anomaly_count_e2e_test.cpp \ tests/e2e/Anomaly_duration_sum_e2e_test.cpp LOCAL_STATIC_LIBRARIES := \ $(statsd_common_static_libraries) \ Loading
cmds/statsd/src/StatsLogProcessor.h +10 −3 Original line number Diff line number Diff line Loading @@ -69,6 +69,11 @@ public: void dumpStates(FILE* out, bool verbose); private: // For testing only. inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const { return mAnomalyAlarmMonitor; } mutable mutex mMetricsMutex; std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers; Loading Loading @@ -133,13 +138,15 @@ private: FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); }; } // namespace statsd Loading
cmds/statsd/src/anomaly/AnomalyTracker.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -66,6 +66,9 @@ size_t AnomalyTracker::index(int64_t bucketNum) const { void AnomalyTracker::advanceMostRecentBucketTo(const int64_t& bucketNum) { VLOG("advanceMostRecentBucketTo() called."); if (mNumOfPastBuckets <= 0) { return; } if (bucketNum <= mMostRecentBucketNum) { ALOGW("Cannot advance buckets backwards (bucketNum=%lld but mMostRecentBucketNum=%lld)", (long long)bucketNum, (long long)mMostRecentBucketNum); Loading Loading @@ -170,7 +173,8 @@ void AnomalyTracker::addBucketToSum(const shared_ptr<DimToValMap>& bucket) { int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key, const int64_t& bucketNum) const { if (bucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets if (bucketNum < 0 || mMostRecentBucketNum < 0 || bucketNum <= mMostRecentBucketNum - mNumOfPastBuckets || bucketNum > mMostRecentBucketNum) { return 0; } Loading Loading @@ -241,14 +245,10 @@ void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs, } bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key) { const MetricDimensionKey& key) const { const auto& it = mRefractoryPeriodEndsSec.find(key); if (it != mRefractoryPeriodEndsSec.end()) { if (timestampNs < it->second * NS_PER_SEC) { return true; } else { mRefractoryPeriodEndsSec.erase(key); } return timestampNs < it->second * NS_PER_SEC; } return false; } Loading
cmds/statsd/src/anomaly/AnomalyTracker.h +11 −2 Original line number Diff line number Diff line Loading @@ -113,6 +113,13 @@ public: } protected: // For testing only. // Returns the alarm timestamp in seconds for the query dimension if it exists. Otherwise // returns 0. virtual uint32_t getAlarmTimestampSec(const MetricDimensionKey& dimensionKey) const { return 0; // The base AnomalyTracker class doesn't have alarms. } // statsd_config.proto Alert message that defines this tracker. const Alert mAlert; Loading Loading @@ -159,8 +166,7 @@ protected: void subtractValueFromSum(const MetricDimensionKey& key, const int64_t& bucketValue); // Returns true if in the refractory period, else false. // If there is a stored refractory period but it ended prior to timestampNs, it is removed. bool isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key); bool isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key) const; // Calculates the corresponding bucket index within the circular array. // Requires bucketNum >= 0. Loading @@ -176,6 +182,9 @@ protected: FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets); FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection); FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); }; } // namespace statsd Loading
cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -40,9 +40,8 @@ void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, // Alarms are stored in secs. Must round up, since if it fires early, it is ignored completely. uint32_t timestampSec = static_cast<uint32_t>((timestampNs -1) / NS_PER_SEC) + 1; // round up if (isInRefractoryPeriod(timestampNs, dimensionKey)) { // TODO: Bug! By the refractory's end, the data might be erased and the alarm inapplicable. VLOG("Setting a delayed anomaly alarm lest it fall in the refractory period"); timestampSec = getRefractoryPeriodEndsSec(dimensionKey) + 1; VLOG("Not setting anomaly alarm since it would fall in the refractory period."); return; } auto itr = mAlarms.find(dimensionKey); Loading