summaryrefslogtreecommitdiff
path: root/statsd/src
diff options
context:
space:
mode:
Diffstat (limited to 'statsd/src')
-rw-r--r--statsd/src/FieldValue.cpp11
-rw-r--r--statsd/src/FieldValue.h2
-rw-r--r--statsd/src/StatsLogProcessor.h2
-rw-r--r--statsd/src/guardrail/stats_log_enums.proto2
-rw-r--r--statsd/src/metrics/MetricsManager.h2
-rw-r--r--statsd/src/metrics/NumericValueMetricProducer.cpp14
-rw-r--r--statsd/src/metrics/NumericValueMetricProducer.h15
-rw-r--r--statsd/src/metrics/ValueMetricProducer.h1
-rw-r--r--statsd/src/metrics/parsing_utils/metrics_manager_util.cpp32
-rw-r--r--statsd/src/statsd_config.proto2
10 files changed, 71 insertions, 12 deletions
diff --git a/statsd/src/FieldValue.cpp b/statsd/src/FieldValue.cpp
index aa129a44..84fad927 100644
--- a/statsd/src/FieldValue.cpp
+++ b/statsd/src/FieldValue.cpp
@@ -60,6 +60,17 @@ bool Field::matches(const Matcher& matcher) const {
return false;
}
+std::vector<Matcher> dedupFieldMatchers(const std::vector<Matcher>& fieldMatchers) {
+ std::vector<Matcher> dedupedFieldMatchers;
+ for (size_t i = 0; i < fieldMatchers.size(); i++) {
+ if (std::find(dedupedFieldMatchers.begin(), dedupedFieldMatchers.end(), fieldMatchers[i]) ==
+ dedupedFieldMatchers.end()) {
+ dedupedFieldMatchers.push_back(fieldMatchers[i]);
+ }
+ }
+ return dedupedFieldMatchers;
+}
+
void translateFieldMatcher(int tag, const FieldMatcher& matcher, int depth, int* pos, int* mask,
std::vector<Matcher>* output) {
if (depth > kMaxLogDepth) {
diff --git a/statsd/src/FieldValue.h b/statsd/src/FieldValue.h
index 2ac71cb8..66b54755 100644
--- a/statsd/src/FieldValue.h
+++ b/statsd/src/FieldValue.h
@@ -463,6 +463,8 @@ bool isAttributionUidField(const FieldValue& value);
/* returns uid if the field is uid field, or -1 if the field is not a uid field */
int getUidIfExists(const FieldValue& value);
+std::vector<Matcher> dedupFieldMatchers(const std::vector<Matcher>& fieldMatchers);
+
void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output);
bool isAttributionUidField(const Field& field, const Value& value);
diff --git a/statsd/src/StatsLogProcessor.h b/statsd/src/StatsLogProcessor.h
index c1c7dd63..b6d66af9 100644
--- a/statsd/src/StatsLogProcessor.h
+++ b/statsd/src/StatsLogProcessor.h
@@ -485,6 +485,8 @@ private:
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithValueFieldPositionALL);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithMultipleAggTypes);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithDefaultAggType);
FRIEND_TEST(KllMetricE2eTest, TestInitWithKllFieldPositionALL);
diff --git a/statsd/src/guardrail/stats_log_enums.proto b/statsd/src/guardrail/stats_log_enums.proto
index 7b4c79a4..c468d52e 100644
--- a/statsd/src/guardrail/stats_log_enums.proto
+++ b/statsd/src/guardrail/stats_log_enums.proto
@@ -151,6 +151,8 @@ enum InvalidConfigReasonEnum {
INVALID_CONFIG_REASON_METRIC_INCORRECT_PULL_PROBABILITY = 93;
INVALID_CONFIG_REASON_GAUGE_METRIC_PUSHED_WITH_PULL_PROBABILITY = 94;
INVALID_CONFIG_REASON_GAUGE_METRIC_RANDOM_ONE_SAMPLE_WITH_PULL_PROBABILITY = 95;
+ INVALID_CONFIG_REASON_VALUE_METRIC_DEFINES_SINGLE_AND_MULTIPLE_AGG_TYPES = 96;
+ INVALID_CONFIG_REASON_VALUE_METRIC_AGG_TYPES_DNE_VALUE_FIELDS_SIZE = 97;
};
enum InvalidQueryReason {
diff --git a/statsd/src/metrics/MetricsManager.h b/statsd/src/metrics/MetricsManager.h
index 2072d61b..4ccee562 100644
--- a/statsd/src/metrics/MetricsManager.h
+++ b/statsd/src/metrics/MetricsManager.h
@@ -437,6 +437,8 @@ private:
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithMultipleAggTypes);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithDefaultAggType);
};
} // namespace statsd
diff --git a/statsd/src/metrics/NumericValueMetricProducer.cpp b/statsd/src/metrics/NumericValueMetricProducer.cpp
index 4024ccef..88c4d16e 100644
--- a/statsd/src/metrics/NumericValueMetricProducer.cpp
+++ b/statsd/src/metrics/NumericValueMetricProducer.cpp
@@ -22,6 +22,7 @@
#include <limits.h>
#include <stdlib.h>
+#include "FieldValue.h"
#include "guardrail/StatsdStats.h"
#include "metrics/parsing_utils/metrics_manager_util.h"
#include "stats_log_util.h"
@@ -70,7 +71,7 @@ NumericValueMetricProducer::NumericValueMetricProducer(
: ValueMetricProducer(metric.id(), key, protoHash, pullOptions, bucketOptions, whatOptions,
conditionOptions, stateOptions, activationOptions, guardrailOptions),
mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()),
- mAggregationType(metric.aggregation_type()),
+ mAggregationTypes(whatOptions.aggregationTypes),
mIncludeSampleSize(metric.has_include_sample_size()
? metric.include_sample_size()
: metric.aggregation_type() == ValueMetric_AggregationType_AVG),
@@ -80,7 +81,8 @@ NumericValueMetricProducer::NumericValueMetricProducer(
mUseZeroDefaultBase(metric.use_zero_default_base()),
mHasGlobalBase(false),
mMaxPullDelayNs(metric.has_max_pull_delay_sec() ? metric.max_pull_delay_sec() * NS_PER_SEC
- : StatsdStats::kPullMaxDelayNs) {
+ : StatsdStats::kPullMaxDelayNs),
+ mDedupedFieldMatchers(dedupFieldMatchers(whatOptions.fieldMatchers)) {
// TODO(b/186677791): Use initializer list to initialize mUploadThreshold.
if (metric.has_threshold()) {
mUploadThreshold = metric.threshold();
@@ -274,9 +276,9 @@ void NumericValueMetricProducer::accumulateEvents(const vector<shared_ptr<LogEve
// Get dimensions_in_what key and value indices.
HashableDimensionKey dimensionsInWhat;
- vector<int> valueIndices(mFieldMatchers.size(), -1);
+ vector<int> valueIndices(mDedupedFieldMatchers.size(), -1);
const LogEvent& eventRef = transformedEvent == nullptr ? *data : *transformedEvent;
- if (!filterValues(mDimensionsInWhat, mFieldMatchers, eventRef.getValues(),
+ if (!filterValues(mDimensionsInWhat, mDedupedFieldMatchers, eventRef.getValues(),
dimensionsInWhat, valueIndices)) {
StatsdStats::getInstance().noteBadValueType(mMetricId);
}
@@ -478,7 +480,7 @@ bool NumericValueMetricProducer::aggregateFields(const int64_t eventTimeNs,
}
if (interval.hasValue()) {
- switch (mAggregationType) {
+ switch (getAggregationTypeLocked(i)) {
case ValueMetric::SUM:
// for AVG, we add up and take average when flushing the bucket
case ValueMetric::AVG:
@@ -664,7 +666,7 @@ bool NumericValueMetricProducer::valuePassesThreshold(const Interval& interval)
}
Value NumericValueMetricProducer::getFinalValue(const Interval& interval) const {
- if (mAggregationType != ValueMetric::AVG) {
+ if (getAggregationTypeLocked(interval.aggIndex) != ValueMetric::AVG) {
return interval.aggregate;
} else {
double sum = interval.aggregate.type == LONG ? (double)interval.aggregate.long_value
diff --git a/statsd/src/metrics/NumericValueMetricProducer.h b/statsd/src/metrics/NumericValueMetricProducer.h
index 775fc1af..9c123f64 100644
--- a/statsd/src/metrics/NumericValueMetricProducer.h
+++ b/statsd/src/metrics/NumericValueMetricProducer.h
@@ -142,12 +142,16 @@ private:
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
- void combineValueFields(pair<LogEvent, vector<int>>& eventValues, const LogEvent& newEvent,
- const vector<int>& newValueIndices) const;
+ void combineValueFields(pair<LogEvent, std::vector<int>>& eventValues, const LogEvent& newEvent,
+ const std::vector<int>& newValueIndices) const;
+
+ ValueMetric::AggregationType getAggregationTypeLocked(int index) const {
+ return mAggregationTypes.size() == 1 ? mAggregationTypes[0] : mAggregationTypes[index];
+ }
const bool mUseAbsoluteValueOnReset;
- const ValueMetric::AggregationType mAggregationType;
+ const std::vector<ValueMetric::AggregationType> mAggregationTypes;
const bool mIncludeSampleSize;
@@ -171,6 +175,9 @@ private:
const int64_t mMaxPullDelayNs;
+ // Deduped value fields for matching.
+ const std::vector<Matcher> mDedupedFieldMatchers;
+
// For anomaly detection.
std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
@@ -232,6 +239,8 @@ private:
FRIEND_TEST(NumericValueMetricProducerTest,
TestSlicedStateWithMultipleDimensionsMissingDataInPull);
FRIEND_TEST(NumericValueMetricProducerTest, TestUploadThreshold);
+ FRIEND_TEST(NumericValueMetricProducerTest, TestMultipleAggTypesPulled);
+ FRIEND_TEST(NumericValueMetricProducerTest, TestMultipleAggTypesPushed);
FRIEND_TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed);
FRIEND_TEST(NumericValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed);
diff --git a/statsd/src/metrics/ValueMetricProducer.h b/statsd/src/metrics/ValueMetricProducer.h
index 92541029..d10fc091 100644
--- a/statsd/src/metrics/ValueMetricProducer.h
+++ b/statsd/src/metrics/ValueMetricProducer.h
@@ -88,6 +88,7 @@ public:
const sp<EventMatcherWizard>& matcherWizard;
const FieldMatcher& dimensionsInWhat;
const vector<Matcher>& fieldMatchers;
+ const vector<ValueMetric::AggregationType> aggregationTypes;
};
struct ConditionOptions {
diff --git a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index f0c5bb25..dfdcc65f 100644
--- a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -922,6 +922,27 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
return nullopt;
}
+ std::vector<ValueMetric::AggregationType> aggregationTypes;
+ if (metric.aggregation_types_size() != 0) {
+ if (metric.has_aggregation_type()) {
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_VALUE_METRIC_DEFINES_SINGLE_AND_MULTIPLE_AGG_TYPES,
+ metric.id());
+ return nullopt;
+ }
+ if (metric.aggregation_types_size() != (int)fieldMatchers.size()) {
+ invalidConfigReason = InvalidConfigReason(
+ INVALID_CONFIG_REASON_VALUE_METRIC_AGG_TYPES_DNE_VALUE_FIELDS_SIZE,
+ metric.id());
+ return nullopt;
+ }
+ for (int i = 0; i < metric.aggregation_types_size(); i++) {
+ aggregationTypes.push_back(metric.aggregation_types(i));
+ }
+ } else { // aggregation_type() is set or default is used.
+ aggregationTypes.push_back(metric.aggregation_type());
+ }
+
int trackerIndex;
invalidConfigReason = handleMetricWithAtomMatchingTrackers(
metric.what(), metric.id(), metricIndex,
@@ -1019,7 +1040,7 @@ optional<sp<MetricProducer>> createNumericValueMetricProducerAndUpdateMetadata(
{timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
conditionCorrectionThresholdNs, getAppUpgradeBucketSplit(metric)},
{containsAnyPositionInDimensionsInWhat, shouldUseNestedDimensions, trackerIndex,
- matcherWizard, metric.dimensions_in_what(), fieldMatchers},
+ matcherWizard, metric.dimensions_in_what(), fieldMatchers, aggregationTypes},
{conditionIndex, metric.links(), initialConditionCache, wizard},
{metric.state_link(), slicedStateAtoms, stateGroupMap},
{eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit});
@@ -1171,8 +1192,13 @@ optional<sp<MetricProducer>> createKllMetricProducerAndUpdateMetadata(
key, metric, metricHash, {/*pullTagId=*/-1, pullerManager},
{timeBaseNs, currentTimeNs, bucketSizeNs, metric.min_bucket_size_nanos(),
/*conditionCorrectionThresholdNs=*/nullopt, getAppUpgradeBucketSplit(metric)},
- {containsAnyPositionInDimensionsInWhat, shouldUseNestedDimensions, trackerIndex,
- matcherWizard, metric.dimensions_in_what(), fieldMatchers},
+ {containsAnyPositionInDimensionsInWhat,
+ shouldUseNestedDimensions,
+ trackerIndex,
+ matcherWizard,
+ metric.dimensions_in_what(),
+ fieldMatchers,
+ {}},
{conditionIndex, metric.links(), initialConditionCache, wizard},
{metric.state_link(), slicedStateAtoms, stateGroupMap},
{eventActivationMap, eventDeactivationMap}, {dimensionSoftLimit, dimensionHardLimit});
diff --git a/statsd/src/statsd_config.proto b/statsd/src/statsd_config.proto
index b49d3e89..cbd60ee3 100644
--- a/statsd/src/statsd_config.proto
+++ b/statsd/src/statsd_config.proto
@@ -395,6 +395,8 @@ message ValueMetric {
}
optional AggregationType aggregation_type = 8 [default = SUM];
+ repeated AggregationType aggregation_types = 25;
+
optional bool include_sample_size = 22;
optional int64 min_bucket_size_nanos = 10;