Merge changes Ife0b17c2,If37e5c6c
* changes: Remove dead code for AnomalyAlarm Remove alarm manager dependency from anomalyalarms
This commit is contained in:
@@ -26,17 +26,6 @@ interface IStatsCompanionService {
|
|||||||
*/
|
*/
|
||||||
oneway void statsdReady();
|
oneway void statsdReady();
|
||||||
|
|
||||||
/**
|
|
||||||
* Register an alarm for anomaly detection to fire at the given timestamp (ms since epoch).
|
|
||||||
* If anomaly alarm had already been registered, it will be replaced with the new timestamp.
|
|
||||||
* Uses AlarmManager.set API, so if the timestamp is in the past, alarm fires immediately, and
|
|
||||||
* alarm is inexact.
|
|
||||||
*/
|
|
||||||
oneway void setAnomalyAlarm(long timestampMs);
|
|
||||||
|
|
||||||
/** Cancel any anomaly detection alarm. */
|
|
||||||
oneway void cancelAnomalyAlarm();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a repeating alarm for pulling to fire at the given timestamp and every
|
* Register a repeating alarm for pulling to fire at the given timestamp and every
|
||||||
* intervalMs thereafter (in ms since epoch).
|
* intervalMs thereafter (in ms since epoch).
|
||||||
|
|||||||
@@ -41,13 +41,6 @@ interface IStatsd {
|
|||||||
*/
|
*/
|
||||||
void statsCompanionReady();
|
void statsCompanionReady();
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells statsd that an anomaly may have occurred, so statsd can check whether this is so and
|
|
||||||
* act accordingly.
|
|
||||||
* Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
|
|
||||||
*/
|
|
||||||
void informAnomalyAlarmFired();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells statsd that it is time to poll some stats. Statsd will be responsible for determing
|
* Tells statsd that it is time to poll some stats. Statsd will be responsible for determing
|
||||||
* what stats to poll and initiating the polling.
|
* what stats to poll and initiating the polling.
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
|||||||
private static IStatsd sStatsd;
|
private static IStatsd sStatsd;
|
||||||
private static final Object sStatsdLock = new Object();
|
private static final Object sStatsdLock = new Object();
|
||||||
|
|
||||||
private final OnAlarmListener mAnomalyAlarmListener;
|
|
||||||
private final OnAlarmListener mPullingAlarmListener;
|
private final OnAlarmListener mPullingAlarmListener;
|
||||||
private final OnAlarmListener mPeriodicAlarmListener;
|
private final OnAlarmListener mPeriodicAlarmListener;
|
||||||
|
|
||||||
@@ -124,7 +123,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
|||||||
handlerThread.start();
|
handlerThread.start();
|
||||||
mHandler = new CompanionHandler(handlerThread.getLooper());
|
mHandler = new CompanionHandler(handlerThread.getLooper());
|
||||||
|
|
||||||
mAnomalyAlarmListener = new AnomalyAlarmListener(context);
|
|
||||||
mPullingAlarmListener = new PullingAlarmListener(context);
|
mPullingAlarmListener = new PullingAlarmListener(context);
|
||||||
mPeriodicAlarmListener = new PeriodicAlarmListener(context);
|
mPeriodicAlarmListener = new PeriodicAlarmListener(context);
|
||||||
}
|
}
|
||||||
@@ -336,41 +334,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class AnomalyAlarmListener implements OnAlarmListener {
|
|
||||||
private final Context mContext;
|
|
||||||
|
|
||||||
AnomalyAlarmListener(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAlarm() {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time "
|
|
||||||
+ System.currentTimeMillis() + "ms.");
|
|
||||||
}
|
|
||||||
IStatsd statsd = getStatsdNonblocking();
|
|
||||||
if (statsd == null) {
|
|
||||||
Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wakelock needs to be retained while calling statsd.
|
|
||||||
Thread thread = new WakelockThread(mContext,
|
|
||||||
AnomalyAlarmListener.class.getCanonicalName(), new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
statsd.informAnomalyAlarmFired();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final static class PullingAlarmListener implements OnAlarmListener {
|
public final static class PullingAlarmListener implements OnAlarmListener {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
@@ -468,34 +431,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // Binder call
|
|
||||||
public void setAnomalyAlarm(long timestampMs) {
|
|
||||||
StatsCompanion.enforceStatsdCallingUid();
|
|
||||||
if (DEBUG) Log.d(TAG, "Setting anomaly alarm for " + timestampMs);
|
|
||||||
final long callingToken = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
// using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
|
|
||||||
// only fire when it awakens.
|
|
||||||
// AlarmManager will automatically cancel any previous mAnomalyAlarmListener alarm.
|
|
||||||
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".anomaly",
|
|
||||||
mAnomalyAlarmListener, mHandler);
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(callingToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // Binder call
|
|
||||||
public void cancelAnomalyAlarm() {
|
|
||||||
StatsCompanion.enforceStatsdCallingUid();
|
|
||||||
if (DEBUG) Log.d(TAG, "Cancelling anomaly alarm");
|
|
||||||
final long callingToken = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
mAlarmManager.cancel(mAnomalyAlarmListener);
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(callingToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // Binder call
|
@Override // Binder call
|
||||||
public void setAlarmForSubscriberTriggering(long timestampMs) {
|
public void setAlarmForSubscriberTriggering(long timestampMs) {
|
||||||
StatsCompanion.enforceStatsdCallingUid();
|
StatsCompanion.enforceStatsdCallingUid();
|
||||||
@@ -666,7 +601,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
|
|||||||
// instead of in binder death because statsd can come back and set different alarms, or not
|
// instead of in binder death because statsd can come back and set different alarms, or not
|
||||||
// want to set an alarm when it had been set. This guarantees that when we get a new statsd,
|
// want to set an alarm when it had been set. This guarantees that when we get a new statsd,
|
||||||
// we cancel any alarms before it is able to set them.
|
// we cancel any alarms before it is able to set them.
|
||||||
cancelAnomalyAlarm();
|
|
||||||
cancelPullingAlarm();
|
cancelPullingAlarm();
|
||||||
cancelAlarmForSubscriberTriggering();
|
cancelAlarmForSubscriberTriggering();
|
||||||
|
|
||||||
|
|||||||
@@ -120,10 +120,9 @@ static void flushProtoToBuffer(ProtoOutputStream& proto, vector<uint8_t>* outDat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsLogProcessor::onAnomalyAlarmFired(
|
void StatsLogProcessor::processFiredAnomalyAlarmsLocked(
|
||||||
const int64_t& timestampNs,
|
const int64_t& timestampNs,
|
||||||
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
|
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
|
||||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
|
||||||
for (const auto& itr : mMetricsManagers) {
|
for (const auto& itr : mMetricsManagers) {
|
||||||
itr.second->onAnomalyAlarmFired(timestampNs, alarmSet);
|
itr.second->onAnomalyAlarmFired(timestampNs, alarmSet);
|
||||||
}
|
}
|
||||||
@@ -431,6 +430,20 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fireAlarm = false;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> anomalyLock(mAnomalyAlarmMutex);
|
||||||
|
if (mNextAnomalyAlarmTime != 0 &&
|
||||||
|
MillisToNano(mNextAnomalyAlarmTime) <= elapsedRealtimeNs) {
|
||||||
|
mNextAnomalyAlarmTime = 0;
|
||||||
|
VLOG("informing anomaly alarm at time %lld", (long long)elapsedRealtimeNs);
|
||||||
|
fireAlarm = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fireAlarm) {
|
||||||
|
informAnomalyAlarmFiredLocked(NanoToMillis(elapsedRealtimeNs));
|
||||||
|
}
|
||||||
|
|
||||||
int64_t curTimeSec = getElapsedRealtimeSec();
|
int64_t curTimeSec = getElapsedRealtimeSec();
|
||||||
if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
|
if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
|
||||||
mPullerManager->ClearPullerCacheIfNecessary(curTimeSec * NS_PER_SEC);
|
mPullerManager->ClearPullerCacheIfNecessary(curTimeSec * NS_PER_SEC);
|
||||||
@@ -1092,6 +1105,28 @@ void StatsLogProcessor::noteOnDiskData(const ConfigKey& key) {
|
|||||||
mOnDiskDataConfigs.insert(key);
|
mOnDiskDataConfigs.insert(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatsLogProcessor::setAnomalyAlarm(const int64_t elapsedTimeMillis) {
|
||||||
|
std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
|
||||||
|
mNextAnomalyAlarmTime = elapsedTimeMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsLogProcessor::cancelAnomalyAlarm() {
|
||||||
|
std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
|
||||||
|
mNextAnomalyAlarmTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsLogProcessor::informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis) {
|
||||||
|
VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
|
||||||
|
std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
|
||||||
|
mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(elapsedTimeMillis / 1000));
|
||||||
|
if (alarmSet.size() > 0) {
|
||||||
|
VLOG("Found periodic alarm fired.");
|
||||||
|
processFiredAnomalyAlarmsLocked(MillisToNano(elapsedTimeMillis), alarmSet);
|
||||||
|
} else {
|
||||||
|
ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace statsd
|
} // namespace statsd
|
||||||
} // namespace os
|
} // namespace os
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|||||||
@@ -66,11 +66,6 @@ public:
|
|||||||
const DumpLatency dumpLatency,
|
const DumpLatency dumpLatency,
|
||||||
ProtoOutputStream* proto);
|
ProtoOutputStream* proto);
|
||||||
|
|
||||||
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
|
|
||||||
void onAnomalyAlarmFired(
|
|
||||||
const int64_t& timestampNs,
|
|
||||||
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
|
|
||||||
|
|
||||||
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */
|
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */
|
||||||
void onPeriodicAlarmFired(
|
void onPeriodicAlarmFired(
|
||||||
const int64_t& timestampNs,
|
const int64_t& timestampNs,
|
||||||
@@ -148,6 +143,10 @@ public:
|
|||||||
// Add a specific config key to the possible configs to dump ASAP.
|
// Add a specific config key to the possible configs to dump ASAP.
|
||||||
void noteOnDiskData(const ConfigKey& key);
|
void noteOnDiskData(const ConfigKey& key);
|
||||||
|
|
||||||
|
void setAnomalyAlarm(const int64_t timeMillis);
|
||||||
|
|
||||||
|
void cancelAnomalyAlarm();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For testing only.
|
// For testing only.
|
||||||
inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const {
|
inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const {
|
||||||
@@ -160,6 +159,11 @@ private:
|
|||||||
|
|
||||||
mutable mutex mMetricsMutex;
|
mutable mutex mMetricsMutex;
|
||||||
|
|
||||||
|
// Guards mNextAnomalyAlarmTime. A separate mutex is needed because alarms are set/cancelled
|
||||||
|
// in the onLogEvent code path, which is locked by mMetricsMutex.
|
||||||
|
// DO NOT acquire mMetricsMutex while holding mAnomalyAlarmMutex. This can lead to a deadlock.
|
||||||
|
mutable mutex mAnomalyAlarmMutex;
|
||||||
|
|
||||||
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
|
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
|
||||||
|
|
||||||
std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes;
|
std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes;
|
||||||
@@ -250,6 +254,15 @@ private:
|
|||||||
// Reset the specified configs.
|
// Reset the specified configs.
|
||||||
void resetConfigsLocked(const int64_t timestampNs, const std::vector<ConfigKey>& configs);
|
void resetConfigsLocked(const int64_t timestampNs, const std::vector<ConfigKey>& configs);
|
||||||
|
|
||||||
|
// An anomaly alarm should have fired.
|
||||||
|
// Check with anomaly alarm manager to find the alarms and process the result.
|
||||||
|
void informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis);
|
||||||
|
|
||||||
|
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
|
||||||
|
void processFiredAnomalyAlarmsLocked(
|
||||||
|
const int64_t& timestampNs,
|
||||||
|
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
|
||||||
|
|
||||||
// Function used to send a broadcast so that receiver for the config key can call getData
|
// Function used to send a broadcast so that receiver for the config key can call getData
|
||||||
// to retrieve the stored data.
|
// to retrieve the stored data.
|
||||||
std::function<bool(const ConfigKey& key)> mSendBroadcast;
|
std::function<bool(const ConfigKey& key)> mSendBroadcast;
|
||||||
@@ -276,6 +289,9 @@ private:
|
|||||||
//Last time we wrote metadata to disk.
|
//Last time we wrote metadata to disk.
|
||||||
int64_t mLastMetadataWriteNs = 0;
|
int64_t mLastMetadataWriteNs = 0;
|
||||||
|
|
||||||
|
// The time for the next anomaly alarm for alerts.
|
||||||
|
int64_t mNextAnomalyAlarmTime = 0;
|
||||||
|
|
||||||
#ifdef VERY_VERBOSE_PRINTING
|
#ifdef VERY_VERBOSE_PRINTING
|
||||||
bool mPrintAllLogs = false;
|
bool mPrintAllLogs = false;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -91,17 +91,13 @@ Status checkUid(uid_t expectedUid) {
|
|||||||
StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue)
|
StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue)
|
||||||
: mAnomalyAlarmMonitor(new AlarmMonitor(
|
: mAnomalyAlarmMonitor(new AlarmMonitor(
|
||||||
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
|
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
|
||||||
[](const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) {
|
[this](const shared_ptr<IStatsCompanionService>& /*sc*/, int64_t timeMillis) {
|
||||||
if (sc != nullptr) {
|
mProcessor->setAnomalyAlarm(timeMillis);
|
||||||
sc->setAnomalyAlarm(timeMillis);
|
StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
|
||||||
StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[](const shared_ptr<IStatsCompanionService>& sc) {
|
[this](const shared_ptr<IStatsCompanionService>& /*sc*/) {
|
||||||
if (sc != nullptr) {
|
mProcessor->cancelAnomalyAlarm();
|
||||||
sc->cancelAnomalyAlarm();
|
StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
|
||||||
StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
|
|
||||||
}
|
|
||||||
})),
|
})),
|
||||||
mPeriodicAlarmMonitor(new AlarmMonitor(
|
mPeriodicAlarmMonitor(new AlarmMonitor(
|
||||||
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
|
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
|
||||||
@@ -975,22 +971,6 @@ Status StatsService::informOnePackageRemoved(const string& app, int32_t uid) {
|
|||||||
return Status::ok();
|
return Status::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status StatsService::informAnomalyAlarmFired() {
|
|
||||||
ENFORCE_UID(AID_SYSTEM);
|
|
||||||
|
|
||||||
VLOG("StatsService::informAnomalyAlarmFired was called");
|
|
||||||
int64_t currentTimeSec = getElapsedRealtimeSec();
|
|
||||||
std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
|
|
||||||
mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
|
|
||||||
if (alarmSet.size() > 0) {
|
|
||||||
VLOG("Found an anomaly alarm that fired.");
|
|
||||||
mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
|
|
||||||
} else {
|
|
||||||
VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
|
|
||||||
}
|
|
||||||
return Status::ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
Status StatsService::informAlarmForSubscriberTriggeringFired() {
|
Status StatsService::informAlarmForSubscriberTriggeringFired() {
|
||||||
ENFORCE_UID(AID_SYSTEM);
|
ENFORCE_UID(AID_SYSTEM);
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ public:
|
|||||||
virtual Status systemRunning();
|
virtual Status systemRunning();
|
||||||
virtual Status statsCompanionReady();
|
virtual Status statsCompanionReady();
|
||||||
virtual Status bootCompleted();
|
virtual Status bootCompleted();
|
||||||
virtual Status informAnomalyAlarmFired();
|
|
||||||
virtual Status informPollAlarmFired();
|
virtual Status informPollAlarmFired();
|
||||||
virtual Status informAlarmForSubscriberTriggeringFired();
|
virtual Status informAlarmForSubscriberTriggeringFired();
|
||||||
|
|
||||||
@@ -404,6 +403,10 @@ private:
|
|||||||
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket);
|
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket);
|
||||||
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket);
|
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket);
|
||||||
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket);
|
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket);
|
||||||
|
|
||||||
|
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
|
||||||
|
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
|
||||||
|
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace statsd
|
} // namespace statsd
|
||||||
|
|||||||
@@ -12,14 +12,19 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <android/binder_ibinder.h>
|
||||||
|
#include <android/binder_interface_utils.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "src/anomaly/DurationAnomalyTracker.h"
|
#include <vector>
|
||||||
|
|
||||||
#include "src/StatsLogProcessor.h"
|
#include "src/StatsLogProcessor.h"
|
||||||
|
#include "src/StatsService.h"
|
||||||
|
#include "src/anomaly/DurationAnomalyTracker.h"
|
||||||
#include "src/stats_log_util.h"
|
#include "src/stats_log_util.h"
|
||||||
#include "tests/statsd_test_util.h"
|
#include "tests/statsd_test_util.h"
|
||||||
|
|
||||||
#include <vector>
|
using ::ndk::SharedRefBase;
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace os {
|
namespace os {
|
||||||
@@ -29,6 +34,9 @@ namespace statsd {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const int kConfigKey = 789130124;
|
||||||
|
const int kCallingUid = 0;
|
||||||
|
|
||||||
StatsdConfig CreateStatsdConfig(int num_buckets,
|
StatsdConfig CreateStatsdConfig(int num_buckets,
|
||||||
uint64_t threshold_ns,
|
uint64_t threshold_ns,
|
||||||
DurationMetric::AggregationType aggregationType,
|
DurationMetric::AggregationType aggregationType,
|
||||||
@@ -89,6 +97,13 @@ MetricDimensionKey dimensionKey2(
|
|||||||
(int32_t)0x02010101), Value((int32_t)222))}),
|
(int32_t)0x02010101), Value((int32_t)222))}),
|
||||||
DEFAULT_DIMENSION_KEY);
|
DEFAULT_DIMENSION_KEY);
|
||||||
|
|
||||||
|
void sendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
|
||||||
|
string str;
|
||||||
|
config.SerializeToString(&str);
|
||||||
|
std::vector<uint8_t> configAsVec(str.begin(), str.end());
|
||||||
|
service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
||||||
@@ -98,16 +113,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
|||||||
const uint64_t alert_id = config.alert(0).id();
|
const uint64_t alert_id = config.alert(0).id();
|
||||||
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
|
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
|
||||||
|
|
||||||
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
|
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
|
||||||
int64_t bucketSizeNs =
|
sendConfig(service, config);
|
||||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
|
|
||||||
|
|
||||||
ConfigKey cfgKey;
|
auto processor = service->mProcessor;
|
||||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
|
||||||
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
|
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||||
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||||
|
|
||||||
|
int64_t bucketStartTimeNs = processor->mTimeBaseNs;
|
||||||
|
int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
|
||||||
|
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
|
||||||
|
|
||||||
sp<AnomalyTracker> anomalyTracker =
|
sp<AnomalyTracker> anomalyTracker =
|
||||||
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
|
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
|
||||||
|
|
||||||
@@ -158,12 +175,13 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
|||||||
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
|
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
|
||||||
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
|
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
|
||||||
(uint32_t)alarmFiredTimestampSec0);
|
(uint32_t)alarmFiredTimestampSec0);
|
||||||
|
EXPECT_EQ(alarmFiredTimestampSec0,
|
||||||
|
processor->getAnomalyAlarmMonitor()->getRegisteredAlarmTimeSec());
|
||||||
|
|
||||||
// Anomaly alarm fired.
|
// Anomaly alarm fired.
|
||||||
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
|
auto alarmTriggerEvent = CreateBatterySaverOnEvent(alarmFiredTimestampSec0 * NS_PER_SEC);
|
||||||
static_cast<uint32_t>(alarmFiredTimestampSec0));
|
processor->OnLogEvent(alarmTriggerEvent.get(), alarmFiredTimestampSec0 * NS_PER_SEC);
|
||||||
ASSERT_EQ(1u, alarmSet.size());
|
|
||||||
processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
|
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
|
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
@@ -179,39 +197,39 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
|||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Acquire wakelock wl1.
|
// Acquire wakelock wl1.
|
||||||
acquire_event =
|
acquire_event = CreateAcquireWakelockEvent(
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11,
|
roundedBucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11, attributionUids2,
|
||||||
attributionUids2, attributionTags2, "wl1");
|
attributionTags2, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
|
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
|
||||||
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
|
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
|
||||||
(uint64_t)alarmFiredTimestampSec1);
|
(uint64_t)alarmFiredTimestampSec1);
|
||||||
|
|
||||||
// Release wakelock wl1.
|
// Release wakelock wl1.
|
||||||
release_event =
|
int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10;
|
||||||
CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10,
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
|
||||||
attributionUids2, attributionTags2, "wl1");
|
attributionTags2, "wl1");
|
||||||
processor->OnLogEvent(release_event.get());
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(refractory_period_sec +
|
EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
|
||||||
(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
|
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
|
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
|
||||||
static_cast<uint32_t>(alarmFiredTimestampSec1));
|
static_cast<uint32_t>(alarmFiredTimestampSec1));
|
||||||
ASSERT_EQ(0u, alarmSet.size());
|
ASSERT_EQ(0u, alarmSet.size());
|
||||||
|
|
||||||
// Acquire wakelock wl1 near the end of bucket #0.
|
// Acquire wakelock wl1 near the end of bucket #0.
|
||||||
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 2,
|
acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 2,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionUids1, attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
|
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
|
|
||||||
// Release the event at early bucket #1.
|
// Release the event at early bucket #1.
|
||||||
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1,
|
release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1;
|
||||||
attributionUids1, attributionTags1, "wl1");
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
|
||||||
processor->OnLogEvent(release_event.get());
|
attributionTags1, "wl1");
|
||||||
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
// Anomaly detected when stopping the alarm. The refractory period does not change.
|
// Anomaly detected when stopping the alarm. The refractory period does not change.
|
||||||
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
|
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
|
||||||
@@ -236,17 +254,17 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
|||||||
|
|
||||||
// Condition turns true.
|
// Condition turns true.
|
||||||
screen_off_event =
|
screen_off_event =
|
||||||
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
|
CreateScreenStateChangedEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
|
||||||
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
|
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
|
||||||
processor->OnLogEvent(screen_off_event.get());
|
processor->OnLogEvent(screen_off_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
|
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
|
|
||||||
// Condition turns to false.
|
// Condition turns to false.
|
||||||
screen_on_event =
|
int64_t condition_false_time = bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1;
|
||||||
CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1,
|
screen_on_event = CreateScreenStateChangedEvent(
|
||||||
android::view::DisplayStateEnum::DISPLAY_STATE_ON);
|
condition_false_time, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
|
||||||
processor->OnLogEvent(screen_on_event.get());
|
processor->OnLogEvent(screen_on_event.get(), condition_false_time);
|
||||||
// Condition turns to false. Cancelled the alarm.
|
// Condition turns to false. Cancelled the alarm.
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
// Detected one anomaly.
|
// Detected one anomaly.
|
||||||
@@ -262,12 +280,11 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
|
|||||||
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
|
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
|
|
||||||
release_event =
|
release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC;
|
||||||
CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC,
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
|
||||||
attributionUids2, attributionTags2, "wl1");
|
attributionTags2, "wl1");
|
||||||
processor->OnLogEvent(release_event.get());
|
processor->OnLogEvent(release_event.get());
|
||||||
EXPECT_EQ(refractory_period_sec +
|
EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
|
||||||
(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
|
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
}
|
}
|
||||||
@@ -279,16 +296,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
|
|||||||
const uint64_t alert_id = config.alert(0).id();
|
const uint64_t alert_id = config.alert(0).id();
|
||||||
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
|
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
|
||||||
|
|
||||||
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
|
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
|
||||||
int64_t bucketSizeNs =
|
sendConfig(service, config);
|
||||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
|
|
||||||
|
|
||||||
ConfigKey cfgKey;
|
auto processor = service->mProcessor;
|
||||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
|
||||||
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
|
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||||
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||||
|
|
||||||
|
int64_t bucketStartTimeNs = processor->mTimeBaseNs;
|
||||||
|
int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
|
||||||
|
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
|
||||||
|
|
||||||
sp<AnomalyTracker> anomalyTracker =
|
sp<AnomalyTracker> anomalyTracker =
|
||||||
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
|
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
|
||||||
|
|
||||||
@@ -298,96 +317,97 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
|
|||||||
|
|
||||||
// Acquire wakelock "wc1" in bucket #0.
|
// Acquire wakelock "wc1" in bucket #0.
|
||||||
auto acquire_event =
|
auto acquire_event =
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
|
CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionUids1, attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
|
EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Release wakelock "wc1" in bucket #0.
|
// Release wakelock "wc1" in bucket #0.
|
||||||
auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
|
int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 1;
|
||||||
attributionUids1, attributionTags1, "wl1");
|
auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
|
||||||
processor->OnLogEvent(release_event.get());
|
attributionTags1, "wl1");
|
||||||
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Acquire wakelock "wc1" in bucket #1.
|
// Acquire wakelock "wc1" in bucket #1.
|
||||||
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1,
|
acquire_event =
|
||||||
attributionUids2, attributionTags2, "wl1");
|
CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 1,
|
||||||
|
attributionUids2, attributionTags2, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
|
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC + 1,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + 100,
|
release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 100;
|
||||||
attributionUids2, attributionTags2, "wl1");
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
|
||||||
processor->OnLogEvent(release_event.get());
|
attributionTags2, "wl1");
|
||||||
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Acquire wakelock "wc2" in bucket #2.
|
// Acquire wakelock "wc2" in bucket #2.
|
||||||
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
|
acquire_event =
|
||||||
attributionUids3, attributionTags3, "wl2");
|
CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + 1,
|
||||||
|
attributionUids3, attributionTags3, "wl2");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
|
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
|
||||||
|
|
||||||
// Release wakelock "wc2" in bucket #2.
|
// Release wakelock "wc2" in bucket #2.
|
||||||
release_event =
|
release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC;
|
||||||
CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
|
||||||
attributionUids3, attributionTags3, "wl2");
|
attributionTags3, "wl2");
|
||||||
processor->OnLogEvent(release_event.get());
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
||||||
EXPECT_EQ(refractory_period_sec +
|
EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
|
||||||
(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
|
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
|
||||||
|
|
||||||
// Acquire wakelock "wc1" in bucket #2.
|
// Acquire wakelock "wc1" in bucket #2.
|
||||||
acquire_event =
|
acquire_event =
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
|
CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC,
|
||||||
attributionUids2, attributionTags2, "wl1");
|
attributionUids2, attributionTags2, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
|
EXPECT_EQ((roundedBucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3 + 1,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Release wakelock "wc1" in bucket #2.
|
// Release wakelock "wc1" in bucket #2.
|
||||||
release_event =
|
release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3.5 * NS_PER_SEC;
|
||||||
CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC,
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
|
||||||
attributionUids2, attributionTags2, "wl1");
|
attributionTags2, "wl1");
|
||||||
processor->OnLogEvent(release_event.get());
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(refractory_period_sec +
|
EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
|
||||||
(int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) /
|
|
||||||
NS_PER_SEC +
|
|
||||||
1,
|
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
acquire_event =
|
acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 4,
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4,
|
attributionUids3, attributionTags3, "wl2");
|
||||||
attributionUids3, attributionTags3, "wl2");
|
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
acquire_event =
|
acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 5,
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5,
|
attributionUids1, attributionTags1, "wl1");
|
||||||
attributionUids1, attributionTags1, "wl1");
|
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
|
EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
|
EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
||||||
|
|
||||||
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 2,
|
release_event_time = roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC + 2;
|
||||||
attributionUids3, attributionTags3, "wl2");
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
|
||||||
processor->OnLogEvent(release_event.get());
|
attributionTags3, "wl2");
|
||||||
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 6,
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
attributionUids1, attributionTags1, "wl1");
|
release_event = CreateReleaseWakelockEvent(release_event_time + 4, attributionUids1,
|
||||||
processor->OnLogEvent(release_event.get());
|
attributionTags1, "wl1");
|
||||||
|
processor->OnLogEvent(release_event.get(), release_event_time + 4);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
|
||||||
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
|
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
|
||||||
EXPECT_EQ(refractory_period_sec + (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC +
|
EXPECT_EQ(refractory_period_sec +
|
||||||
|
(int64_t)(roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC) /
|
||||||
|
NS_PER_SEC +
|
||||||
1,
|
1,
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
}
|
}
|
||||||
@@ -396,20 +416,22 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
|
|||||||
const int num_buckets = 2;
|
const int num_buckets = 2;
|
||||||
const uint64_t threshold_ns = 3 * NS_PER_SEC;
|
const uint64_t threshold_ns = 3 * NS_PER_SEC;
|
||||||
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
|
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
|
||||||
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
|
|
||||||
int64_t bucketSizeNs =
|
|
||||||
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
|
|
||||||
|
|
||||||
const uint64_t alert_id = config.alert(0).id();
|
const uint64_t alert_id = config.alert(0).id();
|
||||||
|
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
|
||||||
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
|
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
|
||||||
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
|
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
|
||||||
|
|
||||||
ConfigKey cfgKey;
|
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
|
||||||
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
|
sendConfig(service, config);
|
||||||
|
|
||||||
|
auto processor = service->mProcessor;
|
||||||
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
|
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
|
||||||
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
|
||||||
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
|
||||||
|
|
||||||
|
int64_t bucketStartTimeNs = processor->mTimeBaseNs;
|
||||||
|
int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
|
||||||
|
|
||||||
sp<AnomalyTracker> anomalyTracker =
|
sp<AnomalyTracker> anomalyTracker =
|
||||||
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
|
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
|
||||||
|
|
||||||
@@ -418,81 +440,81 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
|
|||||||
processor->OnLogEvent(screen_off_event.get());
|
processor->OnLogEvent(screen_off_event.get());
|
||||||
|
|
||||||
// Acquire wakelock "wc1" in bucket #0.
|
// Acquire wakelock "wc1" in bucket #0.
|
||||||
auto acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 100,
|
auto acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 100,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionUids1, attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
|
EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Acquire the wakelock "wc1" again.
|
// Acquire the wakelock "wc1" again.
|
||||||
acquire_event =
|
acquire_event =
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
|
CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionUids1, attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
// The alarm does not change.
|
// The alarm does not change.
|
||||||
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
|
EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// Anomaly alarm fired late.
|
// Anomaly alarm fired late.
|
||||||
const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
|
const int64_t firedAlarmTimestampNs = roundedBucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
|
||||||
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
|
auto alarmTriggerEvent = CreateBatterySaverOnEvent(firedAlarmTimestampNs);
|
||||||
static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
|
processor->OnLogEvent(alarmTriggerEvent.get(), firedAlarmTimestampNs);
|
||||||
ASSERT_EQ(1u, alarmSet.size());
|
|
||||||
processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
|
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
|
acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs - 100,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionUids1, attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
|
int64_t release_event_time = bucketStartTimeNs + 2 * bucketSizeNs + 1;
|
||||||
attributionUids1, attributionTags1, "wl1");
|
auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
|
||||||
processor->OnLogEvent(release_event.get());
|
attributionTags1, "wl1");
|
||||||
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
// Within the refractory period. No anomaly.
|
// Within the refractory period. No anomaly.
|
||||||
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
// A new wakelock, but still within refractory period.
|
// A new wakelock, but still within refractory period.
|
||||||
acquire_event =
|
acquire_event = CreateAcquireWakelockEvent(
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC,
|
roundedBucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC, attributionUids1,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
|
|
||||||
release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
|
release_event =
|
||||||
attributionUids1, attributionTags1, "wl1");
|
CreateReleaseWakelockEvent(roundedBucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
|
||||||
|
attributionUids1, attributionTags1, "wl1");
|
||||||
// Still in the refractory period. No anomaly.
|
// Still in the refractory period. No anomaly.
|
||||||
processor->OnLogEvent(release_event.get());
|
processor->OnLogEvent(release_event.get());
|
||||||
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
|
||||||
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
|
||||||
|
|
||||||
acquire_event =
|
acquire_event = CreateAcquireWakelockEvent(
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5,
|
roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 5, attributionUids1,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
|
EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
|
|
||||||
release_event =
|
release_event_time = roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 4;
|
||||||
CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4,
|
release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(release_event.get());
|
processor->OnLogEvent(release_event.get(), release_event_time);
|
||||||
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
|
|
||||||
acquire_event =
|
acquire_event = CreateAcquireWakelockEvent(
|
||||||
CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3,
|
roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 3, attributionUids1,
|
||||||
attributionUids1, attributionTags1, "wl1");
|
attributionTags1, "wl1");
|
||||||
processor->OnLogEvent(acquire_event.get());
|
processor->OnLogEvent(acquire_event.get());
|
||||||
EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
|
EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
|
||||||
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user