Support sliced condition change in GaugeMetric
TODO: We need CTS to verify the behavior.
Bug: 73958484
Test: statsd_test
Change-Id: I56406983ddede12bc6a2e12188693a0c51ccae5c
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 8e8a529..afa5140 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -117,7 +117,8 @@
}
}
-void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
+void CountMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index ef738ac..fd9f0e0 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -61,7 +61,7 @@
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;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index c6b9405..c28bb88 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -169,7 +169,8 @@
// 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 @@
// 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(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 @@
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 @@
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 @@
if (newTracker != nullptr) {
newTracker->setEventKey(
MetricDimensionKey(whatIt.first, conditionDimension));
- newTracker->onSlicedConditionMayChange(eventTime);
+ newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
whatIt.second[conditionDimension] = std::move(newTracker);
}
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 985749d..75f2391 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -68,10 +68,10 @@
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;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index bd8b293..42a5a3a 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -79,7 +79,8 @@
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) {
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index d6f81fd..93c6c9a 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -53,7 +53,7 @@
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;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 49034ac..89e86cc 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -107,8 +107,9 @@
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
@@ -147,7 +148,7 @@
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()) {
@@ -160,7 +161,7 @@
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);
@@ -213,8 +214,9 @@
}
}
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);
}
@@ -225,27 +227,6 @@
}
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
@@ -267,17 +248,37 @@
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) {
@@ -329,7 +330,7 @@
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;
}
@@ -395,8 +396,8 @@
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;
}
@@ -406,7 +407,7 @@
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);
}
@@ -425,7 +426,7 @@
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());
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index dd6aff4..c442362 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -100,7 +100,7 @@
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;
@@ -151,6 +151,7 @@
static const size_t kBucketSize = sizeof(GaugeBucket{});
FRIEND_TEST(GaugeMetricProducerTest, TestWithCondition);
+ FRIEND_TEST(GaugeMetricProducerTest, TestWithSlicedCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestNoCondition);
FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade);
FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithUpgrade);
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index f4495a1..bf529c8 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -33,7 +33,6 @@
bool condition;
ConditionKey conditionKey;
-
std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
if (mConditionSliced) {
for (const auto& link : mMetric2ConditionLinks) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index ea45f43..53db2f6 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -98,9 +98,9 @@
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 @@
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;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index c773d4f..1be082a 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -326,7 +326,8 @@
// 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);
}
}
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 767260d..38fd12b 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -126,7 +126,8 @@
}
}
-void ValueMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
+void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
+ const uint64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index be57183..c9ec29d 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -93,7 +93,7 @@
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;
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 991a76a..609fe1f 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -92,7 +92,7 @@
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
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index c9547cf..a0463b0 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -245,7 +245,8 @@
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) {
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 0452d37..1f42abc 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -53,7 +53,7 @@
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,
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index b418a85..47e9116 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -210,7 +210,8 @@
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()) {
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 610e3ea..7ea56c9 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -45,7 +45,7 @@
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(