Anomaly detection statsdstats
Adds statsdstats for tracking the number of anomaly alarms registered.
Test: adb shell data/nativetest64/statsd_test/statsd_test
Bug: 67978682
Change-Id: I4aa0539a13c60ccb3b7fd2a4f41c4ad867f3a4ea
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index fa7fe0c..dc12efb 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -72,7 +72,7 @@
// ======================================================================
StatsService::StatsService(const sp<Looper>& handlerLooper)
- : mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Put this comment somewhere better
+ : mAnomalyMonitor(new AnomalyMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS))
{
mUidMap = new UidMap();
mConfigManager = new ConfigManager();
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index bdae1ef..e434f65 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -46,6 +46,10 @@
StatsService(const sp<Looper>& handlerLooper);
virtual ~StatsService();
+ /** The anomaly alarm registered with AlarmManager won't be updated by less than this. */
+ // TODO: Consider making this configurable. And choose a good number.
+ const uint32_t MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS = 5;
+
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
index 2b2bcfc..4912648 100644
--- a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp
@@ -18,6 +18,7 @@
#include "Log.h"
#include "anomaly/AnomalyMonitor.h"
+#include "guardrail/StatsdStats.h"
namespace android {
namespace os {
@@ -76,10 +77,7 @@
if (!wasPresent) return;
if (mPq.empty()) {
if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
- mRegisteredAlarmTimeSec = 0;
- if (mStatsCompanionService != nullptr) {
- mStatsCompanionService->cancelAnomalyAlarm();
- }
+ cancelRegisteredAlarmTime_l();
return;
}
uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec;
@@ -106,10 +104,7 @@
if (!oldAlarms.empty()) {
if (mPq.empty()) {
if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
- mRegisteredAlarmTimeSec = 0;
- if (mStatsCompanionService != nullptr) {
- mStatsCompanionService->cancelAnomalyAlarm();
- }
+ cancelRegisteredAlarmTime_l();
} else {
// Always update the registered alarm in this case (unlike remove()).
updateRegisteredAlarmTime_l(mPq.top()->timestampSec);
@@ -123,6 +118,16 @@
mRegisteredAlarmTimeSec = timestampSec;
if (mStatsCompanionService != nullptr) {
mStatsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec));
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
+ }
+}
+
+void AnomalyMonitor::cancelRegisteredAlarmTime_l() {
+ if (DEBUG) ALOGD("Cancelling reg alarm.");
+ mRegisteredAlarmTimeSec = 0;
+ if (mStatsCompanionService != nullptr) {
+ mStatsCompanionService->cancelAnomalyAlarm();
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
}
}
diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.h b/cmds/statsd/src/anomaly/AnomalyMonitor.h
index e19c469..7acc7904 100644
--- a/cmds/statsd/src/anomaly/AnomalyMonitor.h
+++ b/cmds/statsd/src/anomaly/AnomalyMonitor.h
@@ -138,6 +138,12 @@
*/
void updateRegisteredAlarmTime_l(uint32_t timestampSec);
+ /**
+ * Cancels the alarm registered with StatsCompanionService.
+ * Also correspondingly sets mRegisteredAlarmTimeSec to 0.
+ */
+ void cancelRegisteredAlarmTime_l();
+
/** Converts uint32 timestamp in seconds to a Java long in msec. */
int64_t secToMs(uint32_t timeSec);
};
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 2957457..a48ebc3 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -46,6 +46,7 @@
const int FIELD_ID_METRIC_STATS = 6;
const int FIELD_ID_ATOM_STATS = 7;
const int FIELD_ID_UIDMAP_STATS = 8;
+const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
const int FIELD_ID_MATCHER_STATS_NAME = 1;
const int FIELD_ID_MATCHER_STATS_COUNT = 2;
@@ -59,6 +60,8 @@
const int FIELD_ID_ATOM_STATS_TAG = 1;
const int FIELD_ID_ATOM_STATS_COUNT = 2;
+const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
+
// TODO: add stats for pulled atoms.
StatsdStats::StatsdStats() {
mPushedAtomStats.resize(android::util::kMaxPushedAtomId + 1);
@@ -219,6 +222,11 @@
matcherStats[name]++;
}
+void StatsdStats::noteRegisteredAnomalyAlarmChanged() {
+ lock_guard<std::mutex> lock(mLock);
+ mAnomalyAlarmRegisteredStats++;
+}
+
void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
@@ -246,6 +254,7 @@
mConditionStats.clear();
mMetricsStats.clear();
std::fill(mPushedAtomStats.begin(), mPushedAtomStats.end(), 0);
+ mAnomalyAlarmRegisteredStats = 0;
mMatcherStats.clear();
for (auto& config : mConfigStats) {
config.second.clear_broadcast_sent_time_sec();
@@ -386,6 +395,15 @@
}
}
+ if (mAnomalyAlarmRegisteredStats > 0) {
+ VLOG("********AnomalyAlarmStats stats***********");
+ long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
+ mAnomalyAlarmRegisteredStats);
+ proto.end(token);
+ VLOG("Anomaly alarm registrations: %d", mAnomalyAlarmRegisteredStats);
+ }
+
const int numBytes = mUidMapStats.ByteSize();
vector<char> buffer(numBytes);
mUidMapStats.SerializeToArray(&buffer[0], numBytes);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index d6f6566..95a4e26 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -117,6 +117,11 @@
void noteAtomLogged(int atomId, int32_t timeSec);
/**
+ * Report that statsd modified the anomaly alarm registered with StatsCompanionService.
+ */
+ void noteRegisteredAnomalyAlarmChanged();
+
+ /**
* Records the number of snapshot and delta entries that are being dropped from the uid map.
*/
void noteUidMapDropped(int snapshots, int deltas);
@@ -174,6 +179,10 @@
// This is a vector, not a map because it will be accessed A LOT -- for each stats log.
std::vector<int> mPushedAtomStats;
+ // Stores the number of times statsd modified the anomaly alarm registered with
+ // StatsCompanionService.
+ int mAnomalyAlarmRegisteredStats = 0;
+
// Stores how many times a matcher have been matched.
std::map<const ConfigKey, std::map<const std::string, int>> mMatcherStats;
@@ -195,6 +204,7 @@
FRIEND_TEST(StatsdStatsTest, TestSubStats);
FRIEND_TEST(StatsdStatsTest, TestAtomLog);
FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold);
+ FRIEND_TEST(StatsdStatsTest, TestAnomalyMonitor);
};
} // namespace statsd
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 60d9a3d..79c4727 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -229,4 +229,9 @@
optional int32 dropped_changes = 5;
}
optional UidMapStats uidmap_stats = 8;
+
+ message AnomalyAlarmStats {
+ optional int32 alarms_registered = 1;
+ }
+ optional AnomalyAlarmStats anomaly_alarm_stats = 9;
}
\ No newline at end of file