Merge "Support sliced condition change in GaugeMetric" into pi-dev

am: d9afdee26f

Change-Id: Ic6cbbb276661e6ab6e70ed05fd0b069ecac096f7
This commit is contained in:
Yao Chen
2018-03-27 19:34:48 +00:00
committed by android-build-merger
25 changed files with 167 additions and 409 deletions

View File

@@ -149,9 +149,9 @@ void CombinationConditionTracker::evaluateCondition(
}
}
ConditionState newCondition =
evaluateCombinationCondition(mChildren, mLogicalOperation, nonSlicedConditionCache);
if (!mSliced) {
ConditionState newCondition =
evaluateCombinationCondition(mChildren, mLogicalOperation, nonSlicedConditionCache);
bool nonSlicedChanged = (mNonSlicedConditionState != newCondition);
mNonSlicedConditionState = newCondition;
@@ -172,7 +172,7 @@ void CombinationConditionTracker::evaluateCondition(
break;
}
}
nonSlicedConditionCache[mIndex] = ConditionState::kUnknown;
nonSlicedConditionCache[mIndex] = newCondition;
VLOG("CombinationPredicate %lld sliced may changed? %d", (long long)mConditionId,
conditionChangedCache[mIndex] == true);
}

View File

@@ -289,9 +289,15 @@ void SimpleConditionTracker::evaluateCondition(
// The event doesn't match this condition. So we just report existing condition values.
conditionChangedCache[mIndex] = false;
if (mSliced) {
// if the condition result is sliced. metrics won't directly get value from the
// cache, so just set any value other than kNotEvaluated.
// if the condition result is sliced. The overall condition is true if any of the sliced
// condition is true
conditionCache[mIndex] = mInitialValue;
for (const auto& slicedCondition : mSlicedConditionState) {
if (slicedCondition.second > 0) {
conditionCache[mIndex] = ConditionState::kTrue;
break;
}
}
} else {
const auto& itr = mSlicedConditionState.find(DEFAULT_DIMENSION_KEY);
if (itr == mSlicedConditionState.end()) {

View File

@@ -141,7 +141,7 @@ void StateTracker::evaluateCondition(const LogEvent& event,
// one keys matched.
HashableDimensionKey primaryKey;
HashableDimensionKey state;
if (!filterValues(mPrimaryKeys, event.getValues(), &primaryKey) ||
if ((mPrimaryKeys.size() > 0 && !filterValues(mPrimaryKeys, event.getValues(), &primaryKey)) ||
!filterValues(mOutputDimensions, event.getValues(), &state)) {
ALOGE("Failed to filter fields in the event?? panic now!");
conditionCache[mIndex] =

View File

@@ -255,331 +255,6 @@ void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
}
StatsdConfig build_fake_config() {
// HACK: Hard code a test metric for counting screen on events...
StatsdConfig config;
config.set_id(12345);
int WAKE_LOCK_TAG_ID = 1111; // put a fake id here to make testing easier.
int WAKE_LOCK_UID_KEY_ID = 1;
int WAKE_LOCK_NAME_KEY = 3;
int WAKE_LOCK_STATE_KEY = 4;
int WAKE_LOCK_ACQUIRE_VALUE = 1;
int WAKE_LOCK_RELEASE_VALUE = 0;
int APP_USAGE_TAG_ID = 12345;
int APP_USAGE_UID_KEY_ID = 1;
int APP_USAGE_STATE_KEY = 2;
int APP_USAGE_FOREGROUND = 1;
int APP_USAGE_BACKGROUND = 0;
int SCREEN_EVENT_TAG_ID = 29;
int SCREEN_EVENT_STATE_KEY = 1;
int SCREEN_EVENT_ON_VALUE = 2;
int SCREEN_EVENT_OFF_VALUE = 1;
int UID_PROCESS_STATE_TAG_ID = 27;
int UID_PROCESS_STATE_UID_KEY = 1;
int KERNEL_WAKELOCK_TAG_ID = 1004;
int KERNEL_WAKELOCK_COUNT_KEY = 2;
int KERNEL_WAKELOCK_NAME_KEY = 1;
int DEVICE_TEMPERATURE_TAG_ID = 33;
int DEVICE_TEMPERATURE_KEY = 1;
// Count Screen ON events.
CountMetric* metric = config.add_count_metric();
metric->set_id(1); // METRIC_1
metric->set_what(102); // "SCREEN_TURNED_ON"
metric->set_bucket(ONE_MINUTE);
// Anomaly threshold for screen-on count.
// TODO(b/70627390): Uncomment once the bug is fixed.
/*Alert* alert = config.add_alert();
alert->set_id("ALERT_1");
alert->set_metric_name("METRIC_1");
alert->set_number_of_buckets(6);
alert->set_trigger_if_sum_gt(10);
alert->set_refractory_period_secs(30);
Alert::IncidentdDetails* details = alert->mutable_incidentd_details();
details->add_section(12);
details->add_section(13);*/
config.add_allowed_log_source("AID_ROOT");
config.add_allowed_log_source("AID_SYSTEM");
config.add_allowed_log_source("AID_BLUETOOTH");
config.add_allowed_log_source("com.android.statsd.dogfood");
config.add_allowed_log_source("com.android.systemui");
// Count process state changes, slice by uid.
metric = config.add_count_metric();
metric->set_id(2); // "METRIC_2"
metric->set_what(104);
metric->set_bucket(ONE_MINUTE);
FieldMatcher* dimensions = metric->mutable_dimensions_in_what();
dimensions->set_field(UID_PROCESS_STATE_TAG_ID);
dimensions->add_child()->set_field(UID_PROCESS_STATE_UID_KEY);
// Anomaly threshold for background count.
// TODO(b/70627390): Uncomment once the bug is fixed.
/*
alert = config.add_alert();
alert->set_id("ALERT_2");
alert->set_metric_name("METRIC_2");
alert->set_number_of_buckets(4);
alert->set_trigger_if_sum_gt(30);
alert->set_refractory_period_secs(20);
details = alert->mutable_incidentd_details();
details->add_section(14);
details->add_section(15);*/
// Count process state changes, slice by uid, while SCREEN_IS_OFF
metric = config.add_count_metric();
metric->set_id(3);
metric->set_what(104);
metric->set_bucket(ONE_MINUTE);
dimensions = metric->mutable_dimensions_in_what();
dimensions->set_field(UID_PROCESS_STATE_TAG_ID);
dimensions->add_child()->set_field(UID_PROCESS_STATE_UID_KEY);
metric->set_condition(202);
// Count wake lock, slice by uid, while SCREEN_IS_ON and app in background
metric = config.add_count_metric();
metric->set_id(4);
metric->set_what(107);
metric->set_bucket(ONE_MINUTE);
dimensions = metric->mutable_dimensions_in_what();
dimensions->set_field(WAKE_LOCK_TAG_ID);
dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
metric->set_condition(204);
MetricConditionLink* link = metric->add_links();
link->set_condition(203);
link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
// Duration of an app holding any wl, while screen on and app in background, slice by uid
DurationMetric* durationMetric = config.add_duration_metric();
durationMetric->set_id(5);
durationMetric->set_bucket(ONE_MINUTE);
durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
dimensions = durationMetric->mutable_dimensions_in_what();
dimensions->set_field(WAKE_LOCK_TAG_ID);
dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
durationMetric->set_what(205);
durationMetric->set_condition(204);
link = durationMetric->add_links();
link->set_condition(203);
link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
// max Duration of an app holding any wl, while screen on and app in background, slice by uid
durationMetric = config.add_duration_metric();
durationMetric->set_id(6);
durationMetric->set_bucket(ONE_MINUTE);
durationMetric->set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
dimensions = durationMetric->mutable_dimensions_in_what();
dimensions->set_field(WAKE_LOCK_TAG_ID);
dimensions->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
durationMetric->set_what(205);
durationMetric->set_condition(204);
link = durationMetric->add_links();
link->set_condition(203);
link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
// Duration of an app holding any wl, while screen on and app in background
durationMetric = config.add_duration_metric();
durationMetric->set_id(7);
durationMetric->set_bucket(ONE_MINUTE);
durationMetric->set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
durationMetric->set_what(205);
durationMetric->set_condition(204);
link = durationMetric->add_links();
link->set_condition(203);
link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
// Duration of screen on time.
durationMetric = config.add_duration_metric();
durationMetric->set_id(8);
durationMetric->set_bucket(ONE_MINUTE);
durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
durationMetric->set_what(201);
// Anomaly threshold for background count.
// TODO(b/70627390): Uncomment once the bug is fixed.
/*
alert = config.add_alert();
alert->set_id(308);
alert->set_metric_id(8);
alert->set_number_of_buckets(4);
alert->set_trigger_if_sum_gt(2000000000); // 2 seconds
alert->set_refractory_period_secs(120);
details = alert->mutable_incidentd_details();
details->add_section(-1);*/
// Value metric to count KERNEL_WAKELOCK when screen turned on
ValueMetric* valueMetric = config.add_value_metric();
valueMetric->set_id(11);
valueMetric->set_what(109);
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_in_what();
dimensions->set_field(KERNEL_WAKELOCK_TAG_ID);
dimensions->add_child()->set_field(KERNEL_WAKELOCK_NAME_KEY);
// This is for testing easier. We should never set bucket size this small.
durationMetric->set_bucket(ONE_MINUTE);
// Add an EventMetric to log process state change events.
EventMetric* eventMetric = config.add_event_metric();
eventMetric->set_id(9);
eventMetric->set_what(102); // "SCREEN_TURNED_ON"
// Add an GaugeMetric.
GaugeMetric* gaugeMetric = config.add_gauge_metric();
gaugeMetric->set_id(10);
gaugeMetric->set_what(101);
auto gaugeFieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields();
gaugeFieldMatcher->set_field(DEVICE_TEMPERATURE_TAG_ID);
gaugeFieldMatcher->add_child()->set_field(DEVICE_TEMPERATURE_KEY);
durationMetric->set_bucket(ONE_MINUTE);
// Event matchers.
AtomMatcher* temperatureAtomMatcher = config.add_atom_matcher();
temperatureAtomMatcher->set_id(101); // "DEVICE_TEMPERATURE"
temperatureAtomMatcher->mutable_simple_atom_matcher()->set_atom_id(
DEVICE_TEMPERATURE_TAG_ID);
AtomMatcher* eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(102); // "SCREEN_TURNED_ON"
SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(SCREEN_EVENT_TAG_ID);
FieldValueMatcher* fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
fieldValueMatcher->set_field(SCREEN_EVENT_STATE_KEY);
fieldValueMatcher->set_eq_int(SCREEN_EVENT_ON_VALUE);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(103); // "SCREEN_TURNED_OFF"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(SCREEN_EVENT_TAG_ID);
fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
fieldValueMatcher->set_field(SCREEN_EVENT_STATE_KEY);
fieldValueMatcher->set_eq_int(SCREEN_EVENT_OFF_VALUE);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(104); // "PROCESS_STATE_CHANGE"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(UID_PROCESS_STATE_TAG_ID);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(105); // "APP_GOES_BACKGROUND"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(APP_USAGE_TAG_ID);
fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
fieldValueMatcher->set_field(APP_USAGE_STATE_KEY);
fieldValueMatcher->set_eq_int(APP_USAGE_BACKGROUND);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(106); // "APP_GOES_FOREGROUND"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(APP_USAGE_TAG_ID);
fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
fieldValueMatcher->set_field(APP_USAGE_STATE_KEY);
fieldValueMatcher->set_eq_int(APP_USAGE_FOREGROUND);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(107); // "APP_GET_WL"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(WAKE_LOCK_TAG_ID);
fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
fieldValueMatcher->set_field(WAKE_LOCK_STATE_KEY);
fieldValueMatcher->set_eq_int(WAKE_LOCK_ACQUIRE_VALUE);
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(108); //"APP_RELEASE_WL"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(WAKE_LOCK_TAG_ID);
fieldValueMatcher = simpleAtomMatcher->add_field_value_matcher();
fieldValueMatcher->set_field(WAKE_LOCK_STATE_KEY);
fieldValueMatcher->set_eq_int(WAKE_LOCK_RELEASE_VALUE);
// pulled events
eventMatcher = config.add_atom_matcher();
eventMatcher->set_id(109); // "KERNEL_WAKELOCK"
simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
simpleAtomMatcher->set_atom_id(KERNEL_WAKELOCK_TAG_ID);
// Predicates.............
Predicate* predicate = config.add_predicate();
predicate->set_id(201); // "SCREEN_IS_ON"
SimplePredicate* simplePredicate = predicate->mutable_simple_predicate();
simplePredicate->set_start(102); // "SCREEN_TURNED_ON"
simplePredicate->set_stop(103);
simplePredicate->set_count_nesting(false);
predicate = config.add_predicate();
predicate->set_id(202); // "SCREEN_IS_OFF"
simplePredicate = predicate->mutable_simple_predicate();
simplePredicate->set_start(103);
simplePredicate->set_stop(102); // "SCREEN_TURNED_ON"
simplePredicate->set_count_nesting(false);
predicate = config.add_predicate();
predicate->set_id(203); // "APP_IS_BACKGROUND"
simplePredicate = predicate->mutable_simple_predicate();
simplePredicate->set_start(105);
simplePredicate->set_stop(106);
FieldMatcher* predicate_dimension1 = simplePredicate->mutable_dimensions();
predicate_dimension1->set_field(APP_USAGE_TAG_ID);
predicate_dimension1->add_child()->set_field(APP_USAGE_UID_KEY_ID);
simplePredicate->set_count_nesting(false);
predicate = config.add_predicate();
predicate->set_id(204); // "APP_IS_BACKGROUND_AND_SCREEN_ON"
Predicate_Combination* combination_predicate = predicate->mutable_combination();
combination_predicate->set_operation(LogicalOperation::AND);
combination_predicate->add_predicate(203);
combination_predicate->add_predicate(201);
predicate = config.add_predicate();
predicate->set_id(205); // "WL_HELD_PER_APP_PER_NAME"
simplePredicate = predicate->mutable_simple_predicate();
simplePredicate->set_start(107);
simplePredicate->set_stop(108);
FieldMatcher* predicate_dimension = simplePredicate->mutable_dimensions();
predicate_dimension1->set_field(WAKE_LOCK_TAG_ID);
predicate_dimension->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
predicate_dimension->add_child()->set_field(WAKE_LOCK_NAME_KEY);
simplePredicate->set_count_nesting(true);
predicate = config.add_predicate();
predicate->set_id(206); // "WL_HELD_PER_APP"
simplePredicate = predicate->mutable_simple_predicate();
simplePredicate->set_start(107);
simplePredicate->set_stop(108);
simplePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
predicate_dimension = simplePredicate->mutable_dimensions();
predicate_dimension->set_field(WAKE_LOCK_TAG_ID);
predicate_dimension->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
simplePredicate->set_count_nesting(true);
return config;
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -117,7 +117,8 @@ void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
}
}
void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
void CountMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}

View File

@@ -61,7 +61,7 @@ private:
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;

View File

@@ -169,7 +169,8 @@ unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
// 1. If combination condition, logical operation is AND, only one sliced child predicate.
// 2. No condition in dimension
// 3. The links covers all dimension fields in the sliced child condition predicate.
void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(const uint64_t eventTime) {
void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition,
const uint64_t eventTime) {
if (mMetric2ConditionLinks.size() != 1 ||
!mHasLinksToAllConditionDimensionsInTracker ||
!mDimensionsInCondition.empty()) {
@@ -241,7 +242,8 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(const uint64_
// SlicedConditionChange optimization case 2:
// 1. If combination condition, logical operation is AND, only one sliced child predicate.
// 2. Has dimensions_in_condition and it equals to the output dimensions of the sliced predicate.
void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(const uint64_t eventTime) {
void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(bool condition,
const uint64_t eventTime) {
if (mMetric2ConditionLinks.size() > 1 || !mSameConditionDimensionsInTracker) {
return;
}
@@ -322,7 +324,8 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(const uint64_
}
}
void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
flushIfNeededLocked(eventTime);
@@ -333,20 +336,20 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eve
bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex);
if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker &&
mDimensionsInCondition.empty()) {
onSlicedConditionMayChangeLocked_opt1(eventTime);
onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTime);
return;
}
if (changeDimTrackable && mSameConditionDimensionsInTracker &&
mMetric2ConditionLinks.size() <= 1) {
onSlicedConditionMayChangeLocked_opt2(eventTime);
onSlicedConditionMayChangeLocked_opt2(overallCondition, eventTime);
return;
}
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (auto& pair : whatIt.second) {
pair.second->onSlicedConditionMayChange(eventTime);
pair.second->onSlicedConditionMayChange(overallCondition, eventTime);
}
}
@@ -372,7 +375,7 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eve
if (newTracker != nullptr) {
newTracker->setEventKey(MetricDimensionKey(
whatIt.first, conditionDimension));
newTracker->onSlicedConditionMayChange(eventTime);
newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}
@@ -398,7 +401,7 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eve
if (newTracker != nullptr) {
newTracker->setEventKey(
MetricDimensionKey(whatIt.first, conditionDimension));
newTracker->onSlicedConditionMayChange(eventTime);
newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}

View File

@@ -68,10 +68,10 @@ private:
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
void onSlicedConditionMayChangeLocked_opt1(const uint64_t eventTime);
void onSlicedConditionMayChangeLocked_opt2(const uint64_t eventTime);
void onSlicedConditionMayChangeLocked_opt1(bool overallCondition, const uint64_t eventTime);
void onSlicedConditionMayChangeLocked_opt2(bool overallCondition, const uint64_t eventTime);
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;

View File

@@ -79,7 +79,8 @@ void EventMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
mProto->clear();
}
void EventMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
void EventMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const uint64_t eventTime) {
}
std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& protoOutput) {

View File

@@ -53,7 +53,7 @@ private:
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
void dropDataLocked(const uint64_t dropTimeNs) override;

View File

@@ -115,8 +115,9 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric
mStatsPullerManager->RegisterReceiver(mPullTagId, this, bucketSizeMills);
}
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
(long long)mBucketSizeNs, (long long)mStartTimeNs);
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs,
mConditionSliced);
}
// for testing
@@ -155,7 +156,7 @@ void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
ProtoOutputStream* protoOutput) {
VLOG("gauge metric %lld report now...", (long long)mMetricId);
VLOG("Gauge metric %lld report now...", (long long)mMetricId);
flushIfNeededLocked(dumpTimeNs);
if (mPastBuckets.empty()) {
@@ -168,7 +169,7 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
for (const auto& pair : mPastBuckets) {
const MetricDimensionKey& dimensionKey = pair.first;
VLOG(" dimension key %s", dimensionKey.toString().c_str());
VLOG("Gauge dimension key %s", dimensionKey.toString().c_str());
uint64_t wrapperToken =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
@@ -221,8 +222,9 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
}
}
protoOutput->end(bucketInfoToken);
VLOG("\t bucket [%lld - %lld] includes %d atoms.", (long long)bucket.mBucketStartNs,
(long long)bucket.mBucketEndNs, (int)bucket.mGaugeAtoms.size());
VLOG("Gauge \t bucket [%lld - %lld] includes %d atoms.",
(long long)bucket.mBucketStartNs, (long long)bucket.mBucketEndNs,
(int)bucket.mGaugeAtoms.size());
}
protoOutput->end(wrapperToken);
}
@@ -233,27 +235,6 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
}
void GaugeMetricProducer::pullLocked() {
vector<std::shared_ptr<LogEvent>> allData;
if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
ALOGE("Stats puller failed for tag: %d", mPullTagId);
return;
}
for (const auto& data : allData) {
onMatchedLogEventLocked(0, *data);
}
}
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
const uint64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
flushIfNeededLocked(eventTime);
mCondition = conditionMet;
// Push mode. No need to proactively pull the gauge data.
if (mPullTagId == -1) {
return;
}
bool triggerPuller = false;
switch(mSamplingType) {
// When the metric wants to do random sampling and there is already one gauge atom for the
@@ -275,17 +256,37 @@ void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
vector<std::shared_ptr<LogEvent>> allData;
if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
ALOGE("Stats puller failed for tag: %d", mPullTagId);
ALOGE("Gauge Stats puller failed for tag: %d", mPullTagId);
return;
}
for (const auto& data : allData) {
onMatchedLogEventLocked(0, *data);
}
flushIfNeededLocked(eventTime);
}
void GaugeMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
const uint64_t eventTime) {
VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
flushIfNeededLocked(eventTime);
mCondition = conditionMet;
if (mPullTagId != -1) {
pullLocked();
} // else: Push mode. No need to proactively pull the gauge data.
}
void GaugeMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const uint64_t eventTime) {
VLOG("GaugeMetric %lld onSlicedConditionMayChange overall condition %d", (long long)mMetricId,
overallCondition);
flushIfNeededLocked(eventTime);
// If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
// pull for every dimension.
mCondition = overallCondition;
if (mPullTagId != -1) {
pullLocked();
} // else: Push mode. No need to proactively pull the gauge data.
}
std::shared_ptr<vector<FieldValue>> GaugeMetricProducer::getGaugeFields(const LogEvent& event) {
@@ -337,7 +338,7 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked(
uint64_t eventTimeNs = event.GetElapsedTimestampNs();
mTagId = event.GetTagId();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
VLOG("Gauge Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
return;
}
@@ -403,8 +404,8 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
if (eventTimeNs < currentBucketEndTimeNs) {
VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
(long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
VLOG("Gauge eventTime is %lld, less than next bucket start time %lld",
(long long)eventTimeNs, (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
return;
}
@@ -414,7 +415,7 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
mCurrentBucketNum += numBucketsForward;
VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
VLOG("Gauge metric %lld: new bucket start time: %lld", (long long)mMetricId,
(long long)mCurrentBucketStartTimeNs);
}
@@ -433,7 +434,7 @@ void GaugeMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs)
info.mGaugeAtoms = slice.second;
auto& bucketList = mPastBuckets[slice.first];
bucketList.push_back(info);
VLOG("gauge metric %lld, dump key value: %s", (long long)mMetricId,
VLOG("Gauge gauge metric %lld, dump key value: %s", (long long)mMetricId,
slice.first.toString().c_str());
}

View File

@@ -100,7 +100,7 @@ private:
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
@@ -155,6 +155,7 @@ private:
const size_t mDimensionHardLimit;
FRIEND_TEST(GaugeMetricProducerTest, TestWithCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestWithSlicedCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestNoCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade);
FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithUpgrade);

View File

@@ -33,7 +33,6 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo
bool condition;
ConditionKey conditionKey;
std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
if (mConditionSliced) {
for (const auto& link : mMetric2ConditionLinks) {

View File

@@ -98,9 +98,9 @@ public:
onConditionChangedLocked(condition, eventTime);
}
void onSlicedConditionMayChange(const uint64_t eventTime) {
void onSlicedConditionMayChange(bool overallCondition, const uint64_t eventTime) {
std::lock_guard<std::mutex> lock(mMutex);
onSlicedConditionMayChangeLocked(eventTime);
onSlicedConditionMayChangeLocked(overallCondition, eventTime);
}
bool isConditionSliced() const {
@@ -163,7 +163,8 @@ public:
protected:
virtual void onConditionChangedLocked(const bool condition, const uint64_t eventTime) = 0;
virtual void onSlicedConditionMayChangeLocked(const uint64_t eventTime) = 0;
virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
const uint64_t eventTime) = 0;
virtual void onDumpReportLocked(const uint64_t dumpTimeNs,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual size_t byteSizeLocked() const = 0;

View File

@@ -326,7 +326,8 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
// notification, and the metric can query the sliced conditions that are
// interesting to it.
} else {
mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(eventTime);
mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(conditionCache[i],
eventTime);
}
}
}

View File

@@ -134,7 +134,8 @@ ValueMetricProducer::~ValueMetricProducer() {
}
}
void ValueMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}

View File

@@ -93,7 +93,7 @@ private:
void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
// Internal interface to handle sliced condition change.
void onSlicedConditionMayChangeLocked(const uint64_t eventTime) override;
void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;

View File

@@ -92,7 +92,7 @@ public:
const bool stopAll) = 0;
virtual void noteStopAll(const uint64_t eventTime) = 0;
virtual void onSlicedConditionMayChange(const uint64_t timestamp) = 0;
virtual void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) = 0;
virtual void onConditionChanged(bool condition, const uint64_t timestamp) = 0;
// Flush stale buckets if needed, and return true if the tracker has no on-going duration

View File

@@ -245,7 +245,8 @@ bool MaxDurationTracker::flushIfNeeded(
return flushCurrentBucket(eventTimeNs, output);
}
void MaxDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) {
void MaxDurationTracker::onSlicedConditionMayChange(bool overallCondition,
const uint64_t timestamp) {
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& pair : mInfos) {
if (pair.second.state == kStopped) {

View File

@@ -53,7 +53,7 @@ public:
const uint64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>*) override;
void onSlicedConditionMayChange(const uint64_t timestamp) override;
void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) override;
void onConditionChanged(bool condition, const uint64_t timestamp) override;
int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,

View File

@@ -214,7 +214,8 @@ bool OringDurationTracker::flushIfNeeded(
return flushCurrentBucket(eventTimeNs, output);
}
void OringDurationTracker::onSlicedConditionMayChange(const uint64_t timestamp) {
void OringDurationTracker::onSlicedConditionMayChange(bool overallCondition,
const uint64_t timestamp) {
vector<pair<HashableDimensionKey, int>> startedToPaused;
vector<pair<HashableDimensionKey, int>> pausedToStarted;
if (!mStarted.empty()) {

View File

@@ -45,7 +45,7 @@ public:
const bool stopAll) override;
void noteStopAll(const uint64_t eventTime) override;
void onSlicedConditionMayChange(const uint64_t timestamp) override;
void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) override;
void onConditionChanged(bool condition, const uint64_t timestamp) override;
bool flushCurrentBucket(

View File

@@ -64,16 +64,6 @@ MATCHER_P(StatsdConfigEq, id, 0) {
const int64_t testConfigId = 12345;
TEST(ConfigManagerTest, TestFakeConfig) {
auto metricsManager = std::make_unique<MetricsManager>(
ConfigKey(0, testConfigId), build_fake_config(), 1000, new UidMap(),
new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t){},
[](const sp<IStatsCompanionService>&){}),
new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t){},
[](const sp<IStatsCompanionService>&){}));
EXPECT_TRUE(metricsManager->isConfigValid());
}
/**
* Test the addOrUpdate and remove methods
*/

View File

@@ -338,6 +338,82 @@ TEST(GaugeMetricProducerTest, TestWithCondition) {
->mValue.int_value);
}
TEST(GaugeMetricProducerTest, TestWithSlicedCondition) {
const int conditionTag = 65;
GaugeMetric metric;
metric.set_id(1111111);
metric.set_bucket(ONE_MINUTE);
metric.mutable_gauge_fields_filter()->set_include_all(true);
metric.set_condition(StringToId("APP_DIED"));
auto dim = metric.mutable_dimensions_in_what();
dim->set_field(tagId);
dim->add_child()->set_field(1);
dim = metric.mutable_dimensions_in_condition();
dim->set_field(conditionTag);
dim->add_child()->set_field(1);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, _, _, _, _, _))
.WillRepeatedly(
Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
const vector<Matcher>& dimensionFields, const bool isSubsetDim,
const bool isPartialLink,
std::unordered_set<HashableDimensionKey>* dimensionKeySet) {
dimensionKeySet->clear();
int pos[] = {1, 0, 0};
Field f(conditionTag, pos, 0);
HashableDimensionKey key;
key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
dimensionKeySet->insert(key);
return ConditionState::kTrue;
}));
shared_ptr<MockStatsPullerManager> pullerManager =
make_shared<StrictMock<MockStatsPullerManager>>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event->write(1000);
event->write(100);
event->init();
data->push_back(event);
return true;
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
pullerManager);
gaugeProducer.setBucketSize(60 * NS_PER_SEC);
gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(1UL, key.getDimensionKeyInCondition().getValues().size());
EXPECT_EQ(1000000, key.getDimensionKeyInCondition().getValues()[0].mValue.int_value);
EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
event->write(1000);
event->write(110);
event->init();
allData.push_back(event);
gaugeProducer.onDataPulled(allData);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
}
TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
sp<AlarmMonitor> alarmMonitor;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();

View File

@@ -209,7 +209,7 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange) {
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
tracker.onSlicedConditionMayChange(eventStartTimeNs + 5);
tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 5);
tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
@@ -249,9 +249,9 @@ TEST(OringDurationTrackerTest, TestDurationConditionChange2) {
tracker.noteStart(kEventKey1, true, eventStartTimeNs, key1);
// condition to false; record duration 5n
tracker.onSlicedConditionMayChange(eventStartTimeNs + 5);
tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 5);
// condition to true.
tracker.onSlicedConditionMayChange(eventStartTimeNs + 1000);
tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 1000);
// 2nd duration: 1000ns
tracker.noteStop(kEventKey1, eventStartTimeNs + durationTimeNs, false);
@@ -291,7 +291,7 @@ TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) {
tracker.noteStop(kEventKey1, eventStartTimeNs + 3, false);
tracker.onSlicedConditionMayChange(eventStartTimeNs + 15);
tracker.onSlicedConditionMayChange(true, eventStartTimeNs + 15);
tracker.noteStop(kEventKey1, eventStartTimeNs + 2003, false);