Merge "1/ Use FieldMatcher to specify the value fields in value metric. 2/ rename number_of_buckets as num_buckets 3/ use double for the Alert's threshold"

This commit is contained in:
TreeHugger Robot
2018-01-04 11:19:42 +00:00
committed by Android (Google) Code Review
16 changed files with 67 additions and 41 deletions

View File

@@ -34,11 +34,11 @@ namespace statsd {
AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey)
: mAlert(alert),
mConfigKey(configKey),
mNumOfPastBuckets(mAlert.number_of_buckets() - 1) {
mNumOfPastBuckets(mAlert.num_buckets() - 1) {
VLOG("AnomalyTracker() called");
if (mAlert.number_of_buckets() <= 0) {
if (mAlert.num_buckets() <= 0) {
ALOGE("Cannot create AnomalyTracker with %lld buckets",
(long long)mAlert.number_of_buckets());
(long long)mAlert.num_buckets());
return;
}
if (!mAlert.has_trigger_if_sum_gt()) {

View File

@@ -377,7 +377,8 @@ StatsdConfig build_fake_config() {
ValueMetric* valueMetric = config.add_value_metric();
valueMetric->set_id(11);
valueMetric->set_what(109);
valueMetric->set_value_field(KERNEL_WAKELOCK_COUNT_KEY);
valueMetric->mutable_value_field()->set_field(KERNEL_WAKELOCK_TAG_ID);
valueMetric->mutable_value_field()->add_child()->set_field(KERNEL_WAKELOCK_COUNT_KEY);
valueMetric->set_condition(201);
dimensions = valueMetric->mutable_dimensions();
dimensions->set_field(KERNEL_WAKELOCK_TAG_ID);

View File

@@ -351,6 +351,23 @@ bool IsSubDimension(const DimensionsValue& dimension, const DimensionsValue& sub
}
}
long getLongFromDimenValue(const DimensionsValue& dimensionValue) {
switch (dimensionValue.value_case()) {
case DimensionsValue::ValueCase::kValueInt:
return dimensionValue.value_int();
case DimensionsValue::ValueCase::kValueLong:
return dimensionValue.value_long();
case DimensionsValue::ValueCase::kValueBool:
return dimensionValue.value_bool() ? 1 : 0;
case DimensionsValue::ValueCase::kValueFloat:
return (int64_t)dimensionValue.value_float();
case DimensionsValue::ValueCase::kValueTuple:
case DimensionsValue::ValueCase::kValueStr:
case DimensionsValue::ValueCase::VALUE_NOT_SET:
return 0;
}
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -56,6 +56,8 @@ void DimensionsValueToString(const DimensionsValue& value, std::string *flattene
bool IsSubDimension(const DimensionsValue& dimension, const DimensionsValue& sub);
// Helper function to get long value from the DimensionsValue proto.
long getLongFromDimenValue(const DimensionsValue& dimensionValue);
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -98,9 +98,9 @@ DurationMetricProducer::~DurationMetricProducer() {
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(),
if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) {
ALOGW("invalid alert: threshold (%f) > possible recordable value (%d x %lld)",
alert.trigger_if_sum_gt(), alert.num_buckets(),
(long long)mBucketSizeNs);
return nullptr;
}

View File

@@ -17,6 +17,7 @@
#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "dimension.h"
#include "ValueMetricProducer.h"
#include "guardrail/StatsdStats.h"
#include "stats_log_util.h"
@@ -218,7 +219,8 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
// For scheduled pulled data, the effective event time is snap to the nearest
// bucket boundary to make bucket finalize.
uint64_t realEventTime = allData.at(0)->GetTimestampNs();
uint64_t eventTime = mStartTimeNs + ((realEventTime - mStartTimeNs)/mBucketSizeNs) * mBucketSizeNs;
uint64_t eventTime = mStartTimeNs +
((realEventTime - mStartTimeNs)/mBucketSizeNs) * mBucketSizeNs;
mCondition = false;
for (const auto& data : allData) {
@@ -272,7 +274,11 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
}
Interval& interval = mCurrentSlicedBucket[eventKey];
long value = get_value(event);
std::shared_ptr<FieldValueMap> valueFieldMap = getValueFields(event);
if (valueFieldMap->empty() || valueFieldMap->size() > 1) {
return;
}
const long value = getLongFromDimenValue(valueFieldMap->begin()->second);
if (mPullTagId != -1) { // for pulled events
if (mCondition == true) {
@@ -296,15 +302,11 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
}
}
long ValueMetricProducer::get_value(const LogEvent& event) {
status_t err = NO_ERROR;
long val = event.GetLong(mValueField, &err);
if (err == NO_ERROR) {
return val;
} else {
VLOG("Can't find value in message. %s", event.ToString().c_str());
return 0;
}
std::shared_ptr<FieldValueMap> ValueMetricProducer::getValueFields(const LogEvent& event) {
std::shared_ptr<FieldValueMap> valueFields =
std::make_shared<FieldValueMap>(event.getFieldValueMap());
filterFields(mValueField, valueFields.get());
return valueFields;
}
void ValueMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {

View File

@@ -70,7 +70,7 @@ private:
// Util function to flush the old packet.
void flushIfNeededLocked(const uint64_t& eventTime);
const int32_t mValueField;
const FieldMatcher mValueField;
std::shared_ptr<StatsPullerManager> mStatsPullerManager;
@@ -103,7 +103,7 @@ private:
// TODO: Add a lock to mPastBuckets.
std::unordered_map<HashableDimensionKey, std::vector<ValueBucket>> mPastBuckets;
long get_value(const LogEvent& event);
std::shared_ptr<FieldValueMap> getValueFields(const LogEvent& event);
// Util function to check whether the specified dimension hits the guardrail.
bool hitGuardRailLocked(const HashableDimensionKey& newKey);

View File

@@ -486,9 +486,9 @@ bool initAlerts(const StatsdConfig& config,
(long long)alert.metric_id());
return false;
}
if (alert.trigger_if_sum_gt() < 0 || alert.number_of_buckets() <= 0) {
ALOGW("invalid alert: threshold=%lld num_buckets= %d",
alert.trigger_if_sum_gt(), alert.number_of_buckets());
if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
ALOGW("invalid alert: threshold=%f num_buckets= %d",
alert.trigger_if_sum_gt(), alert.num_buckets());
return false;
}
const int metricIndex = itr->second;

View File

@@ -213,7 +213,7 @@ message ValueMetric {
optional int64 what = 2;
optional int32 value_field = 3;
optional FieldMatcher value_field = 3;
optional int64 condition = 4;
@@ -232,11 +232,11 @@ message Alert {
optional int64 metric_id = 2;
optional int32 number_of_buckets = 3;
optional int32 num_buckets = 3;
optional int32 refractory_period_secs = 4;
optional int64 trigger_if_sum_gt = 5;
optional double trigger_if_sum_gt = 5;
}
message AllowedLogSource {

View File

@@ -89,7 +89,7 @@ StatsdConfig buildGoodConfig() {
auto alert = config.add_alert();
alert->set_id(3);
alert->set_metric_id(3);
alert->set_number_of_buckets(10);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
@@ -138,7 +138,7 @@ StatsdConfig buildAlertWithUnknownMetric() {
auto alert = config.add_alert();
alert->set_id(3);
alert->set_metric_id(2);
alert->set_number_of_buckets(10);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;
@@ -222,7 +222,7 @@ StatsdConfig buildDimensionMetricsWithMultiTags() {
auto alert = config.add_alert();
alert->set_id(103);
alert->set_metric_id(3);
alert->set_number_of_buckets(10);
alert->set_num_buckets(10);
alert->set_refractory_period_secs(100);
alert->set_trigger_if_sum_gt(100);
return config;

View File

@@ -57,7 +57,7 @@ std::shared_ptr<DimToValMap> MockBucket(
TEST(AnomalyTrackerTest, TestConsecutiveBuckets) {
const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Alert alert;
alert.set_number_of_buckets(3);
alert.set_num_buckets(3);
alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
alert.set_trigger_if_sum_gt(2);
@@ -177,7 +177,7 @@ TEST(AnomalyTrackerTest, TestConsecutiveBuckets) {
TEST(AnomalyTrackerTest, TestSparseBuckets) {
const int64_t bucketSizeNs = 30 * NS_PER_SEC;
Alert alert;
alert.set_number_of_buckets(3);
alert.set_num_buckets(3);
alert.set_refractory_period_secs(2 * bucketSizeNs / NS_PER_SEC);
alert.set_trigger_if_sum_gt(2);

View File

@@ -195,7 +195,7 @@ TEST(CountMetricProducerTest, TestAnomalyDetection) {
alert.set_id(11);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(2);
alert.set_number_of_buckets(2);
alert.set_num_buckets(2);
alert.set_refractory_period_secs(1);
int64_t bucketStartTimeNs = 10000000000;

View File

@@ -199,7 +199,7 @@ TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
alert.set_id(101);
alert.set_metric_id(metricId);
alert.set_trigger_if_sum_gt(25);
alert.set_number_of_buckets(2);
alert.set_num_buckets(2);
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert);
int tagId = 1;

View File

@@ -217,7 +217,7 @@ TEST(MaxDurationTrackerTest, TestAnomalyDetection) {
alert.set_id(101);
alert.set_metric_id(metricId);
alert.set_trigger_if_sum_gt(32 * NS_PER_SEC);
alert.set_number_of_buckets(2);
alert.set_num_buckets(2);
alert.set_refractory_period_secs(1);
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;

View File

@@ -265,7 +265,7 @@ TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) {
alert.set_id(101);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
alert.set_number_of_buckets(2);
alert.set_num_buckets(2);
alert.set_refractory_period_secs(1);
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;
@@ -327,7 +327,7 @@ TEST(OringDurationTrackerTest, TestAnomalyDetection) {
alert.set_id(101);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(40 * NS_PER_SEC);
alert.set_number_of_buckets(2);
alert.set_num_buckets(2);
alert.set_refractory_period_secs(1);
unordered_map<HashableDimensionKey, vector<DurationBucket>> buckets;

View File

@@ -51,7 +51,8 @@ TEST(ValueMetricProducerTest, TestNonDimensionalEvents) {
ValueMetric metric;
metric.set_id(metricId);
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
metric.set_value_field(2);
metric.mutable_value_field()->set_field(tagId);
metric.mutable_value_field()->add_child()->set_field(2);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// TODO: pending refactor of StatsPullerManager
@@ -127,7 +128,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
ValueMetric metric;
metric.set_id(metricId);
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
metric.set_value_field(2);
metric.mutable_value_field()->set_field(tagId);
metric.mutable_value_field()->add_child()->set_field(2);
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
@@ -203,7 +205,8 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
ValueMetric metric;
metric.set_id(metricId);
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
metric.set_value_field(2);
metric.mutable_value_field()->set_field(tagId);
metric.mutable_value_field()->add_child()->set_field(2);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
shared_ptr<MockStatsPullerManager> pullerManager =
@@ -244,13 +247,14 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
alert.set_id(101);
alert.set_metric_id(metricId);
alert.set_trigger_if_sum_gt(130);
alert.set_number_of_buckets(2);
alert.set_num_buckets(2);
alert.set_refractory_period_secs(3);
ValueMetric metric;
metric.set_id(metricId);
metric.mutable_bucket()->set_bucket_size_millis(bucketSizeNs / 1000000);
metric.set_value_field(2);
metric.mutable_value_field()->set_field(tagId);
metric.mutable_value_field()->add_child()->set_field(2);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,