Snap for 8086475 from a51c7bc40555ddc8714d10308ea5e3b30bd8d907 to mainline-ipsec-release
Change-Id: Ic041177269261f5a3e47c1864c14b8c9abde15b3
diff --git a/statsd/src/FieldValue.cpp b/statsd/src/FieldValue.cpp
index c9ccfb9..e78edf0 100644
--- a/statsd/src/FieldValue.cpp
+++ b/statsd/src/FieldValue.cpp
@@ -415,6 +415,33 @@
}
}
+size_t Value::getSize() const {
+ size_t size = 0;
+ switch (type) {
+ case INT:
+ size = sizeof(int32_t);
+ break;
+ case LONG:
+ size = sizeof(int64_t);
+ break;
+ case FLOAT:
+ size = sizeof(float);
+ break;
+ case DOUBLE:
+ size = sizeof(double);
+ break;
+ case STRING:
+ size = sizeof(char) * str_value.length();
+ break;
+ case STORAGE:
+ size = sizeof(uint8_t) * storage_value.size();
+ break;
+ default:
+ break;
+ }
+ return size;
+}
+
bool equalDimensions(const std::vector<Matcher>& dimension_a,
const std::vector<Matcher>& dimension_b) {
bool eq = dimension_a.size() == dimension_b.size();
@@ -469,6 +496,14 @@
return false;
}
+size_t getSize(const std::vector<FieldValue>& fieldValues) {
+ size_t totalSize = 0;
+ for (const FieldValue& fieldValue : fieldValues) {
+ totalSize += fieldValue.getSize();
+ }
+ return totalSize;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/FieldValue.h b/statsd/src/FieldValue.h
index 538d742..81fe28c 100644
--- a/statsd/src/FieldValue.h
+++ b/statsd/src/FieldValue.h
@@ -161,6 +161,10 @@
return getDepth() >= depth && getRawPosAtDepth(depth) == kLastBitMask;
}
+ inline size_t getSize() const {
+ return sizeof(mField) + sizeof(mTag);
+ }
+
inline bool operator==(const Field& that) const {
return mTag == that.getTag() && mField == that.getField();
};
@@ -345,6 +349,8 @@
double getDouble() const;
+ size_t getSize() const;
+
Value(const Value& from);
bool operator==(const Value& that) const;
@@ -433,6 +439,10 @@
return false;
}
+ size_t getSize() const {
+ return mField.getSize() + mValue.getSize();
+ }
+
Field mField;
Value mValue;
Annotations mAnnotations;
@@ -457,6 +467,10 @@
// Returns true if dimension_a is a subset of dimension_b.
bool subsetDimensions(const std::vector<Matcher>& dimension_a,
const std::vector<Matcher>& dimension_b);
+
+// Estimate the memory size of the FieldValues. This is different from sizeof(FieldValue) because
+// the size is computed at runtime using the actual contents stored in the FieldValue.
+size_t getSize(const std::vector<FieldValue>& fieldValues);
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/metrics/EventMetricProducer.cpp b/statsd/src/metrics/EventMetricProducer.cpp
index cf994f4..31ad229 100644
--- a/statsd/src/metrics/EventMetricProducer.cpp
+++ b/statsd/src/metrics/EventMetricProducer.cpp
@@ -77,6 +77,7 @@
}
mConditionSliced = true;
}
+ mTotalSize = 0;
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
@@ -128,6 +129,7 @@
void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
mAggregatedAtoms.clear();
+ mTotalSize = 0;
StatsdStats::getInstance().noteBucketDropped(mMetricId);
}
@@ -154,6 +156,7 @@
void EventMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) {
mAggregatedAtoms.clear();
+ mTotalSize = 0;
}
void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
@@ -186,6 +189,7 @@
protoOutput->end(protoToken);
if (erase_data) {
mAggregatedAtoms.clear();
+ mTotalSize = 0;
}
}
@@ -207,16 +211,15 @@
AtomDimensionKey key(event.GetTagId(), HashableDimensionKey(event.getValues()));
std::vector<int64_t>& aggregatedTimestampsNs = mAggregatedAtoms[key];
+ if (aggregatedTimestampsNs.empty()) {
+ mTotalSize += getSize(key.getAtomFieldValues().getValues());
+ }
aggregatedTimestampsNs.push_back(elapsedTimeNs);
+ mTotalSize += sizeof(int64_t); // Add the size of the event timestamp
}
size_t EventMetricProducer::byteSizeLocked() const {
- size_t totalSize = 0;
- for (const auto& [atomDimensionKey, elapsedTimestampsNs] : mAggregatedAtoms) {
- totalSize += sizeof(FieldValue) * atomDimensionKey.getAtomFieldValues().getValues().size();
- totalSize += sizeof(int64_t) * elapsedTimestampsNs.size();
- }
- return totalSize;
+ return mTotalSize;
}
} // namespace statsd
diff --git a/statsd/src/metrics/EventMetricProducer.h b/statsd/src/metrics/EventMetricProducer.h
index 2e3b2e6..76747b6 100644
--- a/statsd/src/metrics/EventMetricProducer.h
+++ b/statsd/src/metrics/EventMetricProducer.h
@@ -96,6 +96,7 @@
// Maps the field/value pairs of an atom to a list of timestamps used to deduplicate atoms.
std::unordered_map<AtomDimensionKey, std::vector<int64_t>> mAggregatedAtoms;
+ size_t mTotalSize;
};
} // namespace statsd
diff --git a/tests/src/android/cts/statsd/alert/AnomalyDetectionTests.java b/tests/src/android/cts/statsd/alert/AnomalyDetectionTests.java
index 69e626c..f08a553 100644
--- a/tests/src/android/cts/statsd/alert/AnomalyDetectionTests.java
+++ b/tests/src/android/cts/statsd/alert/AnomalyDetectionTests.java
@@ -36,7 +36,7 @@
import com.android.os.AtomsProto.AnomalyDetected;
import com.android.os.AtomsProto.AppBreadcrumbReported;
import com.android.os.AtomsProto.Atom;
-import com.android.os.AtomsProto.CpuActiveTime;
+import com.android.os.AtomsProto.DebugElapsedClock;
import com.android.os.StatsLog.EventMetricData;
import com.android.tradefed.log.LogUtil.CLog;
import java.util.List;
@@ -370,10 +370,9 @@
// Test that anomaly detection for pulled metrics work.
public void testPulledAnomalyDetection() throws Exception {
- final int ATOM_ID = Atom.CPU_ACTIVE_TIME_FIELD_NUMBER; // A pulled atom
- final int SLICE_BY_FIELD = CpuActiveTime.UID_FIELD_NUMBER;
+ final int ATOM_ID = Atom.DEBUG_ELAPSED_CLOCK_FIELD_NUMBER; // A pulled atom
final int VALUE_FIELD =
- CpuActiveTime.TIME_MILLIS_FIELD_NUMBER; // Something that will be > 0.
+ DebugElapsedClock.ELAPSED_CLOCK_MILLIS_FIELD_NUMBER; // Something that will be > 0.
final int ATOM_MATCHER_ID = 300;
StatsdConfig.Builder config = getBaseConfig(10, 20, 0 /* threshold: value > 0 */)
@@ -388,11 +387,6 @@
.setWhat(ATOM_MATCHER_ID)
.setBucket(TimeUnit.CTS)
.setSamplingType(GaugeMetric.SamplingType.RANDOM_ONE_SAMPLE)
- // Slice by SLICE_BY_FIELD (typical usecase)
- .setDimensionsInWhat(FieldMatcher.newBuilder()
- .setField(ATOM_ID)
- .addChild(FieldMatcher.newBuilder().setField(SLICE_BY_FIELD))
- )
// Track the VALUE_FIELD (anomaly detection requires exactly one field here)
.setGaugeFieldsFilter(
FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
@@ -406,8 +400,7 @@
Thread.sleep(6_000); // Wait long enough to ensure AlarmManager signals >= 1 pull
List<EventMetricData> data = getEventMetricDataList();
- // There will likely be many anomalies (one for each dimension). There must be at least one.
- assertThat(data.size()).isAtLeast(1);
+ assertThat(data.size()).isEqualTo(1);
assertThat(data.get(0).getAtom().getAnomalyDetected().getAlertId()).isEqualTo(ALERT_ID);
}
diff --git a/tests/src/android/cts/statsd/atom/AtomTestCase.java b/tests/src/android/cts/statsd/atom/AtomTestCase.java
index a4c43e0..1f33c20 100644
--- a/tests/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/tests/src/android/cts/statsd/atom/AtomTestCase.java
@@ -404,17 +404,27 @@
return atomTimestamp.stream().map(p -> p.first).collect(Collectors.toList());
}
- protected void backfillGaugeMetricData(GaugeMetricDataWrapper dataWrapper) {
- for (GaugeMetricData gaugeMetricData : dataWrapper.getDataList()) {
+ protected GaugeMetricDataWrapper backfillGaugeMetricData(GaugeMetricDataWrapper dataWrapper) {
+ GaugeMetricDataWrapper.Builder dataWrapperBuilder = dataWrapper.toBuilder();
+ List<GaugeMetricData> backfilledMetricData = new ArrayList<>();
+ for (GaugeMetricData gaugeMetricData : dataWrapperBuilder.getDataList()) {
+ GaugeMetricData.Builder gaugeMetricDataBuilder = gaugeMetricData.toBuilder();
+ List<GaugeBucketInfo> backfilledBuckets = new ArrayList<>();
for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) {
- backfillGaugeBucket(bucketInfo.toBuilder());
+ backfilledBuckets.add(backfillGaugeBucket(bucketInfo.toBuilder()));
}
+ gaugeMetricDataBuilder.clearBucketInfo();
+ gaugeMetricDataBuilder.addAllBucketInfo(backfilledBuckets);
+ backfilledMetricData.add(gaugeMetricDataBuilder.build());
}
+ dataWrapperBuilder.clearData();
+ dataWrapperBuilder.addAllData(backfilledMetricData);
+ return dataWrapperBuilder.build();
}
- private void backfillGaugeBucket(GaugeBucketInfo.Builder bucketInfoBuilder) {
+ private GaugeBucketInfo backfillGaugeBucket(GaugeBucketInfo.Builder bucketInfoBuilder) {
if (bucketInfoBuilder.getAtomCount() != 0) {
- return;
+ return bucketInfoBuilder.build();
}
List<Pair<Atom, Long>> atomTimestampData = new ArrayList<>();
for (StatsLog.AggregatedAtomInfo atomInfo : bucketInfoBuilder.getAggregatedAtomInfoList()) {
@@ -428,6 +438,7 @@
bucketInfoBuilder.addAtom(atomTimestamp.first);
bucketInfoBuilder.addElapsedTimestampNanos(atomTimestamp.second);
}
+ return bucketInfoBuilder.build();
}
/**
diff --git a/tests/src/android/cts/statsd/metric/GaugeMetricsTests.java b/tests/src/android/cts/statsd/metric/GaugeMetricsTests.java
index b5d6b83..db6a818 100644
--- a/tests/src/android/cts/statsd/metric/GaugeMetricsTests.java
+++ b/tests/src/android/cts/statsd/metric/GaugeMetricsTests.java
@@ -122,7 +122,7 @@
assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
assertThat(metricReport.hasGaugeMetrics()).isTrue();
StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
- backfillGaugeMetricData(gaugeData);
+ gaugeData = backfillGaugeMetricData(gaugeData);
assertThat(gaugeData.getDataCount()).isEqualTo(1);
int bucketCount = gaugeData.getData(0).getBucketInfoCount();
@@ -321,7 +321,7 @@
assertThat(metricReport.getIsActive()).isFalse();
StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
- backfillGaugeMetricData(gaugeData);
+ gaugeData = backfillGaugeMetricData(gaugeData);
assertThat(gaugeData.getDataCount()).isEqualTo(1);
assertThat(gaugeData.getData(0).getBucketInfoCount()).isEqualTo(2);