Splits AnomalyTracker into two files
Splits out DurationAnomalyTracker-specific functions into their own
subclass.
Test: the unit tests and CTS tests
Change-Id: Id6eb74d232b4a9c3a932d805d1ba3f0ba43a88b1
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index f98ee3d..c392540 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -22,6 +22,7 @@
src/atoms.proto \
src/anomaly/AnomalyMonitor.cpp \
src/anomaly/AnomalyTracker.cpp \
+ src/anomaly/DurationAnomalyTracker.cpp \
src/condition/CombinationConditionTracker.cpp \
src/condition/condition_util.cpp \
src/condition/SimpleConditionTracker.cpp \
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 0c078d5..5f9b53a 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -81,6 +81,9 @@
void StatsLogProcessor::onAnomalyAlarmFired(
const uint64_t timestampNs,
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet) {
+ // TODO: This is a thread-safety issue. mMetricsManagers could change under our feet.
+ // TODO: Solution? Lock everything! :(
+ // TODO: Question: Can we replace the other lock (broadcast), or do we need to supplement it?
for (const auto& itr : mMetricsManagers) {
itr.second->onAnomalyAlarmFired(timestampNs, anomalySet);
}
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 162a34b..f8a9413 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -30,8 +30,6 @@
namespace os {
namespace statsd {
-// TODO: Separate DurationAnomalyTracker as a separate subclass and let each MetricProducer
-// decide and let which one it wants.
// TODO: Get rid of bucketNumbers, and return to the original circular array method.
AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey)
: mAlert(alert),
@@ -52,7 +50,6 @@
AnomalyTracker::~AnomalyTracker() {
VLOG("~AnomalyTracker() called");
- stopAllAlarms();
}
void AnomalyTracker::resetStorage() {
@@ -61,8 +58,6 @@
// Excludes the current bucket.
mPastBuckets.resize(mNumOfPastBuckets);
mSumOverPastBuckets.clear();
-
- if (!mAlarms.empty()) VLOG("AnomalyTracker.resetStorage() called but mAlarms is NOT empty!");
}
size_t AnomalyTracker::index(int64_t bucketNum) const {
@@ -205,23 +200,22 @@
return;
}
// TODO(guardrail): Consider guarding against too short refractory periods.
- mLastAlarmTimestampNs = timestampNs;
-
+ mLastAnomalyTimestampNs = timestampNs;
// TODO: If we had access to the bucket_size_millis, consider calling resetStorage()
// if (mAlert.refractory_period_secs() > mNumOfPastBuckets * bucketSizeNs) { resetStorage(); }
if (mAlert.has_incidentd_details()) {
if (mAlert.has_name()) {
- ALOGW("An anomaly (%s) has occurred! Informing incidentd.",
+ ALOGI("An anomaly (%s) has occurred! Informing incidentd.",
mAlert.name().c_str());
} else {
// TODO: Can construct a name based on the criteria (and/or relay the criteria).
- ALOGW("An anomaly (nameless) has occurred! Informing incidentd.");
+ ALOGI("An anomaly (nameless) has occurred! Informing incidentd.");
}
informIncidentd();
} else {
- ALOGW("An anomaly has occurred! (But informing incidentd not requested.)");
+ ALOGI("An anomaly has occurred! (But informing incidentd not requested.)");
}
StatsdStats::getInstance().noteAnomalyDeclared(mConfigKey, mAlert.name());
@@ -230,20 +224,6 @@
mConfigKey.GetName().c_str(), mAlert.name().c_str());
}
-void AnomalyTracker::declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey,
- const uint64_t& timestampNs) {
- auto itr = mAlarms.find(dimensionKey);
- if (itr == mAlarms.end()) {
- return;
- }
-
- if (itr->second != nullptr &&
- static_cast<uint32_t>(timestampNs / NS_PER_SEC) >= itr->second->timestampSec) {
- declareAnomaly(timestampNs);
- stopAlarm(dimensionKey);
- }
-}
-
void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs,
const int64_t& currBucketNum,
const HashableDimensionKey& key,
@@ -261,68 +241,9 @@
}
}
-void AnomalyTracker::startAlarm(const HashableDimensionKey& dimensionKey,
- const uint64_t& timestampNs) {
- uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC);
- if (isInRefractoryPeriod(timestampNs)) {
- VLOG("Skipping setting anomaly alarm since it'd fall in the refractory period");
- return;
- }
-
- sp<const AnomalyAlarm> alarm = new AnomalyAlarm{timestampSec};
- mAlarms.insert({dimensionKey, alarm});
- if (mAnomalyMonitor != nullptr) {
- mAnomalyMonitor->add(alarm);
- }
-}
-
-void AnomalyTracker::stopAlarm(const HashableDimensionKey& dimensionKey) {
- auto itr = mAlarms.find(dimensionKey);
- if (itr != mAlarms.end()) {
- mAlarms.erase(dimensionKey);
- if (mAnomalyMonitor != nullptr) {
- mAnomalyMonitor->remove(itr->second);
- }
- }
-}
-
-void AnomalyTracker::stopAllAlarms() {
- std::set<HashableDimensionKey> keys;
- for (auto itr = mAlarms.begin(); itr != mAlarms.end(); ++itr) {
- keys.insert(itr->first);
- }
- for (auto key : keys) {
- stopAlarm(key);
- }
-}
-
-bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs) {
- return mLastAlarmTimestampNs >= 0 &&
- timestampNs - mLastAlarmTimestampNs <= mAlert.refractory_period_secs() * NS_PER_SEC;
-}
-
-void AnomalyTracker::informAlarmsFired(const uint64_t& timestampNs,
- unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) {
-
- if (firedAlarms.empty() || mAlarms.empty()) return;
- // Find the intersection of firedAlarms and mAlarms.
- // The for loop is inefficient, since it loops over all keys, but that's okay since it is very
- // seldomly called. The alternative would be having AnomalyAlarms store information about the
- // AnomalyTracker and key, but that's a lot of data overhead to speed up something that is
- // rarely ever called.
- unordered_map<HashableDimensionKey, sp<const AnomalyAlarm>> matchedAlarms;
- for (const auto& kv : mAlarms) {
- if (firedAlarms.count(kv.second) > 0) {
- matchedAlarms.insert({kv.first, kv.second});
- }
- }
-
- // Now declare each of these alarms to have fired.
- for (const auto& kv : matchedAlarms) {
- declareAnomaly(timestampNs /* TODO: , kv.first */);
- mAlarms.erase(kv.first);
- firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
- }
+bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs) const {
+ return mLastAnomalyTimestampNs >= 0 &&
+ timestampNs - mLastAnomalyTimestampNs <= mAlert.refractory_period_secs() * NS_PER_SEC;
}
void AnomalyTracker::informIncidentd() {
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index 874add2..48f0203 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -61,23 +61,11 @@
const HashableDimensionKey& key,
const int64_t& currentBucketValue);
- // Starts the alarm at the given timestamp.
- void startAlarm(const HashableDimensionKey& dimensionKey, const uint64_t& eventTime);
- // Stops the alarm.
- void stopAlarm(const HashableDimensionKey& dimensionKey);
-
- // Stop all the alarms owned by this tracker.
- void stopAllAlarms();
-
- // Init the anmaly monitor which is shared across anomaly trackers.
- inline void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor) {
- mAnomalyMonitor = anomalyMonitor;
+ // Init the AnomalyMonitor which is shared across anomaly trackers.
+ virtual void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor) {
+ return; // Base AnomalyTracker class has no need for the AnomalyMonitor.
}
- // Declares the anomaly when the alarm expired given the current timestamp.
- void declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey,
- const uint64_t& timestampNs);
-
// Helper function to return the sum value of past buckets at given dimension.
int64_t getSumOverPastBuckets(const HashableDimensionKey& key) const;
@@ -89,9 +77,9 @@
return mAlert.trigger_if_sum_gt();
}
- // Helper function to return the last alarm timestamp.
- inline int64_t getLastAlarmTimestampNs() const {
- return mLastAlarmTimestampNs;
+ // Helper function to return the timestamp of the last detected anomaly.
+ inline int64_t getLastAnomalyTimestampNs() const {
+ return mLastAnomalyTimestampNs;
}
inline int getNumOfPastBuckets() const {
@@ -100,15 +88,12 @@
// Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker,
// and removes it from firedAlarms. Does NOT remove the alarm from the AnomalyMonitor.
- // TODO: This will actually be called from a different thread, so make it thread-safe!
- // TODO: Consider having AnomalyMonitor have a reference to each relevant MetricProducer
- // instead of calling it from a chain starting at StatsLogProcessor.
- void informAlarmsFired(const uint64_t& timestampNs,
- unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms);
+ virtual void informAlarmsFired(const uint64_t& timestampNs,
+ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) {
+ return; // The base AnomalyTracker class doesn't have alarms.
+ }
protected:
- void flushPastBuckets(const int64_t& currBucketNum);
-
// statsd_config.proto Alert message that defines this tracker.
const Alert mAlert;
@@ -119,13 +104,6 @@
// for the anomaly detection (since the current bucket is not in the past).
int mNumOfPastBuckets;
- // The alarms owned by this tracker. The alarm monitor also shares the alarm pointers when they
- // are still active.
- std::unordered_map<HashableDimensionKey, sp<const AnomalyAlarm>> mAlarms;
-
- // Anomaly alarm monitor.
- sp<AnomalyMonitor> mAnomalyMonitor;
-
// The exisiting bucket list.
std::vector<shared_ptr<DimToValMap>> mPastBuckets;
@@ -136,7 +114,9 @@
int64_t mMostRecentBucketNum = -1;
// The timestamp when the last anomaly was declared.
- int64_t mLastAlarmTimestampNs = -1;
+ int64_t mLastAnomalyTimestampNs = -1;
+
+ void flushPastBuckets(const int64_t& currBucketNum);
// Add the information in the given bucket to mSumOverPastBuckets.
void addBucketToSum(const shared_ptr<DimToValMap>& bucket);
@@ -145,13 +125,13 @@
// and remove any items with value 0.
void subtractBucketFromSum(const shared_ptr<DimToValMap>& bucket);
- bool isInRefractoryPeriod(const uint64_t& timestampNs);
+ bool isInRefractoryPeriod(const uint64_t& timestampNs) const;
// Calculates the corresponding bucket index within the circular array.
size_t index(int64_t bucketNum) const;
// Resets all bucket data. For use when all the data gets stale.
- void resetStorage();
+ virtual void resetStorage();
// Informs the incident service that an anomaly has occurred.
void informIncidentd();
@@ -160,11 +140,6 @@
FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets);
FRIEND_TEST(GaugeMetricProducerTest, TestAnomalyDetection);
FRIEND_TEST(CountMetricProducerTest, TestAnomalyDetection);
- FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
- FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
- FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
- FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
- FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
};
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
new file mode 100644
index 0000000..d30810f
--- /dev/null
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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 true // STOPSHIP if true
+#include "Log.h"
+
+#include "DurationAnomalyTracker.h"
+#include "guardrail/StatsdStats.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+DurationAnomalyTracker::DurationAnomalyTracker(const Alert& alert, const ConfigKey& configKey)
+ : AnomalyTracker(alert, configKey) {
+}
+
+DurationAnomalyTracker::~DurationAnomalyTracker() {
+ stopAllAlarms();
+}
+
+void DurationAnomalyTracker::resetStorage() {
+ AnomalyTracker::resetStorage();
+ if (!mAlarms.empty()) VLOG("AnomalyTracker.resetStorage() called but mAlarms is NOT empty!");
+}
+
+void DurationAnomalyTracker::declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey,
+ const uint64_t& timestampNs) {
+ auto itr = mAlarms.find(dimensionKey);
+ if (itr == mAlarms.end()) {
+ return;
+ }
+
+ if (itr->second != nullptr &&
+ static_cast<uint32_t>(timestampNs / NS_PER_SEC) >= itr->second->timestampSec) {
+ declareAnomaly(timestampNs);
+ stopAlarm(dimensionKey);
+ }
+}
+
+void DurationAnomalyTracker::startAlarm(const HashableDimensionKey& dimensionKey,
+ const uint64_t& timestampNs) {
+
+ uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC);
+ if (isInRefractoryPeriod(timestampNs)) {
+ VLOG("Skipping setting anomaly alarm since it'd fall in the refractory period");
+ return;
+ }
+ sp<const AnomalyAlarm> alarm = new AnomalyAlarm{timestampSec};
+ mAlarms.insert({dimensionKey, alarm});
+ if (mAnomalyMonitor != nullptr) {
+ mAnomalyMonitor->add(alarm);
+ }
+}
+
+void DurationAnomalyTracker::stopAlarm(const HashableDimensionKey& dimensionKey) {
+ auto itr = mAlarms.find(dimensionKey);
+ if (itr != mAlarms.end()) {
+ mAlarms.erase(dimensionKey);
+ if (mAnomalyMonitor != nullptr) {
+ mAnomalyMonitor->remove(itr->second);
+ }
+ }
+}
+
+void DurationAnomalyTracker::stopAllAlarms() {
+ std::set<HashableDimensionKey> keys;
+ for (auto itr = mAlarms.begin(); itr != mAlarms.end(); ++itr) {
+ keys.insert(itr->first);
+ }
+ for (auto key : keys) {
+ stopAlarm(key);
+ }
+}
+
+void DurationAnomalyTracker::informAlarmsFired(const uint64_t& timestampNs,
+ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) {
+
+ if (firedAlarms.empty() || mAlarms.empty()) return;
+ // Find the intersection of firedAlarms and mAlarms.
+ // The for loop is inefficient, since it loops over all keys, but that's okay since it is very
+ // seldomly called. The alternative would be having AnomalyAlarms store information about the
+ // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that is
+ // rarely ever called.
+ unordered_map<HashableDimensionKey, sp<const AnomalyAlarm>> matchedAlarms;
+ for (const auto& kv : mAlarms) {
+ if (firedAlarms.count(kv.second) > 0) {
+ matchedAlarms.insert({kv.first, kv.second});
+ }
+ }
+
+ // Now declare each of these alarms to have fired.
+ for (const auto& kv : matchedAlarms) {
+ declareAnomaly(timestampNs /* TODO: , kv.first */);
+ mAlarms.erase(kv.first);
+ firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
+ }
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
new file mode 100644
index 0000000..182ce3b
--- /dev/null
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "AnomalyMonitor.h"
+#include "AnomalyTracker.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::unordered_map;
+
+class DurationAnomalyTracker : public virtual AnomalyTracker {
+public:
+ DurationAnomalyTracker(const Alert& alert, const ConfigKey& configKey);
+
+ virtual ~DurationAnomalyTracker();
+
+ // Starts the alarm at the given timestamp.
+ void startAlarm(const HashableDimensionKey& dimensionKey, const uint64_t& eventTime);
+
+ // Stops the alarm.
+ void stopAlarm(const HashableDimensionKey& dimensionKey);
+
+ // Stop all the alarms owned by this tracker.
+ void stopAllAlarms();
+
+ // Init the AnomalyMonitor which is shared across anomaly trackers.
+ void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor) override {
+ mAnomalyMonitor = anomalyMonitor;
+ }
+
+ // Declares the anomaly when the alarm expired given the current timestamp.
+ void declareAnomalyIfAlarmExpired(const HashableDimensionKey& dimensionKey,
+ const uint64_t& timestampNs);
+
+ // Declares an anomaly for each alarm in firedAlarms that belongs to this DurationAnomalyTracker
+ // and removes it from firedAlarms. Does NOT remove the alarm from the AnomalyMonitor.
+ // TODO: This will actually be called from a different thread, so make it thread-safe!
+ // This means that almost every function in DurationAnomalyTracker needs to be locked.
+ // But this should be done at the level of StatsLogProcessor, which needs to lock
+ // mMetricsMangers anyway.
+ void informAlarmsFired(const uint64_t& timestampNs,
+ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) override;
+
+protected:
+ // The alarms owned by this tracker. The alarm monitor also shares the alarm pointers when they
+ // are still active.
+ std::unordered_map<HashableDimensionKey, sp<const AnomalyAlarm>> mAlarms;
+
+ // Anomaly alarm monitor.
+ sp<AnomalyMonitor> mAnomalyMonitor;
+
+ // Resets all bucket data. For use when all the data gets stale.
+ void resetStorage() override;
+
+ FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
+ FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
+ FRIEND_TEST(MaxDurationTrackerTest, TestAnomalyDetection);
+ FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 1c8f422..51ea4b5 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -101,15 +101,19 @@
VLOG("~DurationMetric() called");
}
-sp<AnomalyTracker> DurationMetricProducer::createAnomalyTracker(const Alert &alert) {
+sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(const Alert &alert) {
+ std::lock_guard<std::mutex> lock(mMutex);
if (alert.trigger_if_sum_gt() > alert.number_of_buckets() * mBucketSizeNs) {
ALOGW("invalid alert: threshold (%lld) > possible recordable value (%d x %lld)",
alert.trigger_if_sum_gt(), alert.number_of_buckets(),
(long long)mBucketSizeNs);
return nullptr;
}
- // TODO: return a DurationAnomalyTracker (which should sublclass AnomalyTracker)
- return new AnomalyTracker(alert, mConfigKey);
+ sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, mConfigKey);
+ if (anomalyTracker != nullptr) {
+ mAnomalyTrackers.push_back(anomalyTracker);
+ }
+ return anomalyTracker;
}
unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 7044b4b..abc89bd 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -20,6 +20,7 @@
#include <unordered_map>
#include <android/util/ProtoOutputStream.h>
+#include "../anomaly/DurationAnomalyTracker.h"
#include "../condition/ConditionTracker.h"
#include "../matchers/matcher_util.h"
#include "MetricProducer.h"
@@ -45,7 +46,7 @@
virtual ~DurationMetricProducer();
- virtual sp<AnomalyTracker> createAnomalyTracker(const Alert &alert) override;
+ sp<AnomalyTracker> addAnomalyTracker(const Alert &alert) override;
protected:
void onMatchedLogEventInternalLocked(
@@ -98,6 +99,9 @@
std::unique_ptr<DurationTracker> createDurationTracker(
const HashableDimensionKey& eventKey) const;
+ // This hides the base class's std::vector<sp<AnomalyTracker>> mAnomalyTrackers
+ std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
+
// Util function to check whether the specified dimension hits the guardrail.
bool hitGuardRailLocked(const HashableDimensionKey& newKey);
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 85ef4ad..647d8c1 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -98,13 +98,13 @@
return byteSizeLocked();
}
- virtual sp<AnomalyTracker> createAnomalyTracker(const Alert &alert) {
- return new AnomalyTracker(alert, mConfigKey);
- }
-
- void addAnomalyTracker(sp<AnomalyTracker> tracker) {
+ virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert) {
std::lock_guard<std::mutex> lock(mMutex);
- mAnomalyTrackers.push_back(tracker);
+ sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, mConfigKey);
+ if (anomalyTracker != nullptr) {
+ mAnomalyTrackers.push_back(anomalyTracker);
+ }
+ return anomalyTracker;
}
int64_t getBuckeSizeInNs() const {
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 3c714b3..9192d12f 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -17,7 +17,7 @@
#ifndef DURATION_TRACKER_H
#define DURATION_TRACKER_H
-#include "anomaly/AnomalyTracker.h"
+#include "anomaly/DurationAnomalyTracker.h"
#include "condition/ConditionWizard.h"
#include "config/ConfigKey.h"
#include "stats_util.h"
@@ -63,7 +63,7 @@
DurationTracker(const ConfigKey& key, const string& name, const HashableDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
uint64_t currentBucketStartNs, uint64_t bucketSizeNs,
- const std::vector<sp<AnomalyTracker>>& anomalyTrackers)
+ const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: mConfigKey(key),
mName(name),
mEventKey(eventKey),
@@ -94,7 +94,7 @@
std::unordered_map<HashableDimensionKey, std::vector<DurationBucket>>* output) = 0;
// Predict the anomaly timestamp given the current status.
- virtual int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
+ virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const = 0;
protected:
@@ -163,7 +163,7 @@
uint64_t mCurrentBucketNum;
- std::vector<sp<AnomalyTracker>> mAnomalyTrackers;
+ std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetection);
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 6050f43..d8a8e23 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -28,7 +28,7 @@
const HashableDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
uint64_t currentBucketStartNs, uint64_t bucketSizeNs,
- const std::vector<sp<AnomalyTracker>>& anomalyTrackers)
+ const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, name, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
bucketSizeNs, anomalyTrackers) {
}
@@ -281,7 +281,7 @@
}
}
-int64_t MaxDurationTracker::predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
+int64_t MaxDurationTracker::predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const {
ALOGE("Max duration producer does not support anomaly timestamp prediction!!!");
return currentTimestamp;
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 10eddb8..76f486e 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -32,7 +32,7 @@
const HashableDimensionKey& eventKey, sp<ConditionWizard> wizard,
int conditionIndex, bool nesting, uint64_t currentBucketStartNs,
uint64_t bucketSizeNs,
- const std::vector<sp<AnomalyTracker>>& anomalyTrackers);
+ const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime,
const ConditionKey& conditionKey) override;
void noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
@@ -46,7 +46,7 @@
void onSlicedConditionMayChange(const uint64_t timestamp) override;
void onConditionChanged(bool condition, const uint64_t timestamp) override;
- int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
+ int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const override;
private:
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 5c43096..c347d5c 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -24,12 +24,11 @@
using std::pair;
-OringDurationTracker::OringDurationTracker(const ConfigKey& key, const string& name,
- const HashableDimensionKey& eventKey,
- sp<ConditionWizard> wizard, int conditionIndex,
- bool nesting, uint64_t currentBucketStartNs,
- uint64_t bucketSizeNs,
- const std::vector<sp<AnomalyTracker>>& anomalyTrackers)
+OringDurationTracker::OringDurationTracker(
+ const ConfigKey& key, const string& name, const HashableDimensionKey& eventKey,
+ sp<ConditionWizard> wizard, int conditionIndex, bool nesting, uint64_t currentBucketStartNs,
+ uint64_t bucketSizeNs, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+
: DurationTracker(key, name, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
bucketSizeNs, anomalyTrackers),
mStarted(),
@@ -264,8 +263,8 @@
}
}
-int64_t OringDurationTracker::predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
- const uint64_t eventTimestampNs) const {
+int64_t OringDurationTracker::predictAnomalyTimestampNs(
+ const DurationAnomalyTracker& anomalyTracker, const uint64_t eventTimestampNs) const {
// TODO: Unit-test this and see if it can be done more efficiently (e.g. use int32).
// All variables below represent durations (not timestamps).
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index b7d3cba..dcf04db 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -31,7 +31,7 @@
const HashableDimensionKey& eventKey, sp<ConditionWizard> wizard,
int conditionIndex, bool nesting, uint64_t currentBucketStartNs,
uint64_t bucketSizeNs,
- const std::vector<sp<AnomalyTracker>>& anomalyTrackers);
+ const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime,
const ConditionKey& conditionKey) override;
@@ -46,7 +46,7 @@
uint64_t timestampNs,
std::unordered_map<HashableDimensionKey, std::vector<DurationBucket>>* output) override;
- int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
+ int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const override;
private:
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 5d0e97e..658b732 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -480,9 +480,8 @@
}
const int metricIndex = itr->second;
sp<MetricProducer> metric = allMetricProducers[metricIndex];
- sp<AnomalyTracker> anomalyTracker = metric->createAnomalyTracker(alert);
+ sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert);
if (anomalyTracker != nullptr) {
- metric->addAnomalyTracker(anomalyTracker);
allAnomalyTrackers.push_back(anomalyTracker);
}
}
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index f62171d..a016054 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -89,7 +89,7 @@
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
EXPECT_FALSE(anomalyTracker.detectAnomaly(0, *bucket0));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp0, 0, *bucket0);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, -1L);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
// Adds past bucket #0
anomalyTracker.addPastBucket(bucket0, 0);
@@ -100,7 +100,7 @@
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 1, *bucket1);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, -1L);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
// Adds past bucket #0 again. The sum does not change.
anomalyTracker.addPastBucket(bucket0, 0);
@@ -111,7 +111,7 @@
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 0LL);
EXPECT_FALSE(anomalyTracker.detectAnomaly(1, *bucket1));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1 + 1, 1, *bucket1);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, -1L);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1L);
// Adds past bucket #1.
anomalyTracker.addPastBucket(bucket1, 1);
@@ -122,7 +122,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 2, *bucket2);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp2);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
// Adds past bucket #1 again. Nothing changes.
anomalyTracker.addPastBucket(bucket1, 1);
@@ -133,7 +133,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
EXPECT_TRUE(anomalyTracker.detectAnomaly(2, *bucket2));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2 + 1, 2, *bucket2);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp2);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
// Adds past bucket #2.
anomalyTracker.addPastBucket(bucket2, 2);
@@ -144,7 +144,7 @@
EXPECT_TRUE(anomalyTracker.detectAnomaly(3, *bucket3));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 3, *bucket3);
// Within refractory period.
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp2);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
// Adds bucket #3.
anomalyTracker.addPastBucket(bucket3, 3L);
@@ -154,7 +154,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_FALSE(anomalyTracker.detectAnomaly(4, *bucket4));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 4, *bucket4);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp2);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
// Adds bucket #4.
anomalyTracker.addPastBucket(bucket4, 4);
@@ -164,7 +164,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_TRUE(anomalyTracker.detectAnomaly(5, *bucket5));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 5, *bucket5);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp5);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
// Adds bucket #5.
anomalyTracker.addPastBucket(bucket5, 5);
@@ -175,7 +175,7 @@
EXPECT_TRUE(anomalyTracker.detectAnomaly(6, *bucket6));
// Within refractory period.
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 6, *bucket6);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp5);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp5);
}
TEST(AnomalyTrackerTest, TestSparseBuckets) {
@@ -210,7 +210,7 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
EXPECT_FALSE(anomalyTracker.detectAnomaly(9, *bucket9));
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp1, 9, *bucket9);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, -1);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, -1);
// Add past bucket #9
anomalyTracker.addPastBucket(bucket9, 9);
@@ -224,7 +224,7 @@
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp2, 16, *bucket16);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp2);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
// Add past bucket #16
@@ -237,7 +237,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
// Within refractory period.
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp3, 18, *bucket18);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp2);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp2);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
@@ -253,7 +253,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4, 20, *bucket20);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp4);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
// Add bucket #18 again. Nothing changes.
anomalyTracker.addPastBucket(bucket18, 18);
@@ -267,7 +267,7 @@
EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp4 + 1, 20, *bucket20);
// Within refractory period.
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp4);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
// Add past bucket #20
anomalyTracker.addPastBucket(bucket20, 20);
@@ -279,7 +279,7 @@
EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 24L);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp5, 25, *bucket25);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp4);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
// Add past bucket #25
anomalyTracker.addPastBucket(bucket25, 25);
@@ -291,7 +291,7 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6, 28, *bucket28);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp4);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp4);
// Updates current bucket #28.
(*bucket28)[keyE] = 5;
@@ -300,7 +300,7 @@
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
anomalyTracker.detectAndDeclareAnomaly(eventTimestamp6 + 7, 28, *bucket28);
EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
- EXPECT_EQ(anomalyTracker.mLastAlarmTimestampNs, eventTimestamp6 + 7);
+ EXPECT_EQ(anomalyTracker.mLastAnomalyTimestampNs, eventTimestamp6 + 7);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index eec94539..d3269ed 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -196,8 +196,6 @@
int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
- sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
-
CountMetric metric;
metric.set_name("1");
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
@@ -205,7 +203,7 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
bucketStartTimeNs);
- countProducer.addAnomalyTracker(anomalyTracker);
+ sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert);
int tagId = 1;
LogEvent event1(tagId, bucketStartTimeNs + 1);
@@ -222,13 +220,13 @@
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), -1LL);
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL);
// One event in bucket #2. No alarm as bucket #0 is trashed out.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), -1LL);
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL);
// Two events in bucket #3.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
@@ -237,12 +235,12 @@
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
// Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event5.GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event5.GetTimestampNs());
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event7.GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event7.GetTimestampNs());
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 5204834..584a6d3 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -173,8 +173,7 @@
alert.set_metric_name(metricName);
alert.set_trigger_if_sum_gt(25);
alert.set_number_of_buckets(2);
- sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
- gaugeProducer.addAnomalyTracker(anomalyTracker);
+ sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert);
std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(1, bucketStartTimeNs + 1);
event1->write(1);
@@ -184,7 +183,7 @@
gaugeProducer.onDataPulled({event1});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()->second->kv[0].value_int());
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), -1LL);
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL);
std::shared_ptr<LogEvent> event2 =
std::make_shared<LogEvent>(1, bucketStartTimeNs + bucketSizeNs + 10);
@@ -195,7 +194,7 @@
gaugeProducer.onDataPulled({event2});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()->second->kv[0].value_int());
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event2->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event2->GetTimestampNs());
std::shared_ptr<LogEvent> event3 =
std::make_shared<LogEvent>(1, bucketStartTimeNs + 2 * bucketSizeNs + 10);
@@ -206,7 +205,7 @@
gaugeProducer.onDataPulled({event3});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(24L, gaugeProducer.mCurrentSlicedBucket->begin()->second->kv[0].value_int());
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event3->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event3->GetTimestampNs());
// The event4 does not have the gauge field. Thus the current bucket value is 0.
std::shared_ptr<LogEvent> event4 =
@@ -216,7 +215,7 @@
gaugeProducer.onDataPulled({event4});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(0, gaugeProducer.mCurrentSlicedBucket->begin()->second->kv[0].value_int());
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event3->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event3->GetTimestampNs());
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index 7dac0fb..4ad1db1 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -219,20 +219,20 @@
uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
uint64_t bucketSizeNs = 30 * NS_PER_SEC;
- sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
+ sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
MaxDurationTracker tracker(kConfigKey, "metric", eventKey, wizard, -1, true, bucketStartTimeNs,
bucketSizeNs, {anomalyTracker});
tracker.noteStart(key1, true, eventStartTimeNs, conditionKey1);
tracker.noteStop(key1, eventStartTimeNs + 10, false);
- EXPECT_EQ(anomalyTracker->mLastAlarmTimestampNs, -1);
+ EXPECT_EQ(anomalyTracker->mLastAnomalyTimestampNs, -1);
EXPECT_EQ(10LL, tracker.mDuration);
tracker.noteStart(key2, true, eventStartTimeNs + 20, conditionKey1);
tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC, &buckets);
tracker.noteStop(key2, eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC, false);
EXPECT_EQ((long long)(4 * NS_PER_SEC + 1LL), tracker.mDuration);
- EXPECT_EQ(anomalyTracker->mLastAlarmTimestampNs,
+ EXPECT_EQ(anomalyTracker->mLastAnomalyTimestampNs,
(long long)(eventStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC));
}
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 9ec302f..e0f554d 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -273,7 +273,7 @@
uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
uint64_t bucketSizeNs = 30 * NS_PER_SEC;
- sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
+ sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
OringDurationTracker tracker(kConfigKey, "metric", eventKey, wizard, 1, true, bucketStartTimeNs,
bucketSizeNs, {anomalyTracker});
@@ -335,13 +335,13 @@
uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
uint64_t bucketSizeNs = 30 * NS_PER_SEC;
- sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
+ sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, kConfigKey);
OringDurationTracker tracker(kConfigKey, "metric", eventKey, wizard, 1, true /*nesting*/,
bucketStartTimeNs, bucketSizeNs, {anomalyTracker});
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, key1);
tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 10, false);
- EXPECT_EQ(anomalyTracker->mLastAlarmTimestampNs, -1);
+ EXPECT_EQ(anomalyTracker->mLastAnomalyTimestampNs, -1);
EXPECT_TRUE(tracker.mStarted.empty());
EXPECT_EQ(10LL, tracker.mDuration);
@@ -355,7 +355,7 @@
tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 2 * bucketSizeNs + 25, false);
EXPECT_EQ(anomalyTracker->getSumOverPastBuckets(eventKey), (long long)(bucketSizeNs));
EXPECT_EQ((long long)(eventStartTimeNs + 2 * bucketSizeNs + 25),
- anomalyTracker->mLastAlarmTimestampNs);
+ anomalyTracker->mLastAnomalyTimestampNs);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 6f117d3..12bc834 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -245,7 +245,6 @@
alert.set_trigger_if_sum_gt(130);
alert.set_number_of_buckets(2);
alert.set_refractory_period_secs(3);
- sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, kConfigKey);
ValueMetric metric;
metric.set_name(metricName);
@@ -255,7 +254,7 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-1 /*not pulled*/, bucketStartTimeNs);
- valueProducer.addAnomalyTracker(anomalyTracker);
+ sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert);
shared_ptr<LogEvent> event1
@@ -292,23 +291,23 @@
// Two events in bucket #0.
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), -1LL); // Value sum == 30 <= 130.
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL); // Value sum == 30 <= 130.
// One event in bucket #2. No alarm as bucket #0 is trashed out.
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), -1LL); // Value sum == 130 <= 130.
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), -1LL); // Value sum == 130 <= 130.
// Three events in bucket #3.
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
// Anomaly at event 4 since Value sum == 131 > 130!
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event4->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event4->GetTimestampNs());
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
// Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event4->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event4->GetTimestampNs());
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
// Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
- EXPECT_EQ(anomalyTracker->getLastAlarmTimestampNs(), (long long)event6->GetTimestampNs());
+ EXPECT_EQ(anomalyTracker->getLastAnomalyTimestampNs(), (long long)event6->GetTimestampNs());
}
} // namespace statsd