Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69000e6e authored by tsaichristine's avatar tsaichristine
Browse files

Slice by state in CountMetricProducer

- When a log event is matched to the "what" atom of a metric,
MetricProducer parses the event for state primary key(s) and queries
StateTracker for the correct state values
- CountMetricProducer writes state information to the dump report proto
- Added e2e CountMetric tests that push events to StatsLogProcessor and
check that the resulting dump report is correct

Test: bit statsd_test:*
Bug: 136566566
Bug: 142124705
Change-Id: I9ca5b097151c0c73a617f3b16c8c3584b068cd82
parent 15cc75b6
Loading
Loading
Loading
Loading
+28 −8
Original line number Diff line number Diff line
@@ -59,10 +59,11 @@ android::hash_t hashDimension(const HashableDimensionKey& value) {
    return JenkinsHashWhiten(hash);
}

bool filterValues(const Matcher& matcherField, const vector<FieldValue>& values, Value* output) {
bool filterValues(const Matcher& matcherField, const vector<FieldValue>& values,
                  FieldValue* output) {
    for (const auto& value : values) {
        if (value.mField.matches(matcherField)) {
            (*output) = value.mValue;
            (*output) = value;
            return true;
        }
    }
@@ -106,7 +107,6 @@ void getDimensionForCondition(const std::vector<FieldValue>& eventValues,

    size_t count = conditionDimension->getValues().size();
    if (count != links.conditionFields.size()) {
        // ALOGE("WTF condition link is bad");
        return;
    }

@@ -118,6 +118,26 @@ void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
    }
}

void getDimensionForState(const std::vector<FieldValue>& eventValues, const Metric2State& link,
                          HashableDimensionKey* statePrimaryKey) {
    // First, get the dimension from the event using the "what" fields from the
    // MetricStateLinks.
    filterValues(link.metricFields, eventValues, statePrimaryKey);

    // Then check that the statePrimaryKey size equals the number of state fields
    size_t count = statePrimaryKey->getValues().size();
    if (count != link.stateFields.size()) {
        return;
    }

    // For each dimension Value in the statePrimaryKey, set the field and tag
    // using the state atom fields from MetricStateLinks.
    for (size_t i = 0; i < count; i++) {
        statePrimaryKey->mutableValue(i)->mField.setField(link.stateFields[i].mMatcher.getField());
        statePrimaryKey->mutableValue(i)->mField.setTag(link.stateFields[i].mMatcher.getTag());
    }
}

bool LessThan(const vector<FieldValue>& s1, const vector<FieldValue>& s2) {
    if (s1.size() != s2.size()) {
        return s1.size() < s2.size();
@@ -185,11 +205,11 @@ string HashableDimensionKey::toString() const {

bool MetricDimensionKey::operator==(const MetricDimensionKey& that) const {
    return mDimensionKeyInWhat == that.getDimensionKeyInWhat() &&
           mDimensionKeyInCondition == that.getDimensionKeyInCondition();
           mStateValuesKey == that.getStateValuesKey();
};

string MetricDimensionKey::toString() const {
    return mDimensionKeyInWhat.toString() + mDimensionKeyInCondition.toString();
    return mDimensionKeyInWhat.toString() + mStateValuesKey.toString();
}

bool MetricDimensionKey::operator<(const MetricDimensionKey& that) const {
@@ -199,7 +219,7 @@ bool MetricDimensionKey::operator<(const MetricDimensionKey& that) const {
        return false;
    }

    return mDimensionKeyInCondition < that.getDimensionKeyInCondition();
    return mStateValuesKey < that.getStateValuesKey();
}

}  // namespace statsd
+28 −16
Original line number Diff line number Diff line
@@ -34,6 +34,12 @@ struct Metric2Condition {
    std::vector<Matcher> conditionFields;
};

struct Metric2State {
    int32_t stateAtomId;
    std::vector<Matcher> metricFields;
    std::vector<Matcher> stateFields;
};

class HashableDimensionKey {
public:
    explicit HashableDimensionKey(const std::vector<FieldValue>& values) {
@@ -78,15 +84,14 @@ private:
class MetricDimensionKey {
public:
    explicit MetricDimensionKey(const HashableDimensionKey& dimensionKeyInWhat,
                                const HashableDimensionKey& dimensionKeyInCondition)
        : mDimensionKeyInWhat(dimensionKeyInWhat),
          mDimensionKeyInCondition(dimensionKeyInCondition) {};
                                const HashableDimensionKey& stateValuesKey)
        : mDimensionKeyInWhat(dimensionKeyInWhat), mStateValuesKey(stateValuesKey){};

    MetricDimensionKey(){};

    MetricDimensionKey(const MetricDimensionKey& that)
        : mDimensionKeyInWhat(that.getDimensionKeyInWhat()),
          mDimensionKeyInCondition(that.getDimensionKeyInCondition()) {};
          mStateValuesKey(that.getStateValuesKey()){};

    MetricDimensionKey& operator=(const MetricDimensionKey& from) = default;

@@ -96,16 +101,16 @@ class MetricDimensionKey {
        return mDimensionKeyInWhat;
    }

    inline const HashableDimensionKey& getDimensionKeyInCondition() const {
        return mDimensionKeyInCondition;
    inline const HashableDimensionKey& getStateValuesKey() const {
        return mStateValuesKey;
    }

    inline void setDimensionKeyInCondition(const HashableDimensionKey& key) {
        mDimensionKeyInCondition = key;
    inline void setStateValuesKey(const HashableDimensionKey& key) {
        mStateValuesKey = key;
    }

    bool hasDimensionKeyInCondition() const {
        return mDimensionKeyInCondition.getValues().size() > 0;
    bool hasStateValuesKey() const {
        return mStateValuesKey.getValues().size() > 0;
    }

    bool operator==(const MetricDimensionKey& that) const;
@@ -114,7 +119,7 @@ class MetricDimensionKey {

private:
    HashableDimensionKey mDimensionKeyInWhat;
      HashableDimensionKey mDimensionKeyInCondition;
    HashableDimensionKey mStateValuesKey;
};

android::hash_t hashDimension(const HashableDimensionKey& key);
@@ -124,7 +129,7 @@ android::hash_t hashDimension(const HashableDimensionKey& key);
 * The value of the FieldValue is output.
 */
bool filterValues(const Matcher& matcherField, const std::vector<FieldValue>& values,
                  Value* output);
                  FieldValue* output);

/**
 * Creating HashableDimensionKeys from FieldValues using matcher.
@@ -152,6 +157,13 @@ void getDimensionForCondition(const std::vector<FieldValue>& eventValues,
                              const Metric2Condition& links,
                              HashableDimensionKey* conditionDimension);

/**
 * Get dimension values using metric's "what" fields and fill statePrimaryKey's
 * mField information using "state" fields.
 */
void getDimensionForState(const std::vector<FieldValue>& eventValues, const Metric2State& link,
                          HashableDimensionKey* statePrimaryKey);

}  // namespace statsd
}  // namespace os
}  // namespace android
@@ -172,7 +184,7 @@ template <>
struct hash<MetricDimensionKey> {
    std::size_t operator()(const MetricDimensionKey& key) const {
        android::hash_t hash = hashDimension(key.getDimensionKeyInWhat());
        hash = android::JenkinsHashMix(hash, hashDimension(key.getDimensionKeyInCondition()));
        hash = android::JenkinsHashMix(hash, hashDimension(key.getStateValuesKey()));
        return android::JenkinsHashWhiten(hash);
    }
};
+4 −3
Original line number Diff line number Diff line
@@ -263,9 +263,10 @@ private:
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);

    FRIEND_TEST(CountMetricE2eTest, TestWithSimpleState);
    FRIEND_TEST(CountMetricE2eTest, TestWithMappedState);
    FRIEND_TEST(CountMetricE2eTest, TestWithMultipleStates);
    FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
    FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
    FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
    FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields);

    FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
    FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
+19 −21
Original line number Diff line number Diff line
@@ -57,10 +57,9 @@ const int FIELD_ID_IS_ACTIVE = 14;
const int FIELD_ID_DATA = 1;
// for CountMetricData
const int FIELD_ID_DIMENSION_IN_WHAT = 1;
const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
const int FIELD_ID_SLICE_BY_STATE = 6;
const int FIELD_ID_BUCKET_INFO = 3;
const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
const int FIELD_ID_DIMENSION_LEAF_IN_CONDITION = 5;
// for CountBucketInfo
const int FIELD_ID_COUNT = 3;
const int FIELD_ID_BUCKET_NUM = 4;
@@ -102,7 +101,13 @@ CountMetricProducer::CountMetricProducer(
        mConditionSliced = true;
    }

    // TODO(tsaichristine): b/142124705 handle metric state links
    for (const auto& stateLink : metric.state_link()) {
        Metric2State ms;
        ms.stateAtomId = stateLink.state_atom_id();
        translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
        translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
        mMetric2StateLinks.push_back(ms);
    }

    flushIfNeededLocked(startTimeNs);
    // Adjust start for partial bucket
@@ -132,10 +137,9 @@ void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
            (unsigned long)mCurrentSlicedCounter->size());
    if (verbose) {
        for (const auto& it : *mCurrentSlicedCounter) {
            fprintf(out, "\t(what)%s\t(condition)%s  %lld\n",
            fprintf(out, "\t(what)%s\t(state)%s  %lld\n",
                    it.first.getDimensionKeyInWhat().toString().c_str(),
                it.first.getDimensionKeyInCondition().toString().c_str(),
                (unsigned long long)it.second);
                    it.first.getStateValuesKey().toString().c_str(), (unsigned long long)it.second);
        }
    }
}
@@ -196,22 +200,16 @@ void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                    FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
            writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), str_set, protoOutput);
            protoOutput->end(dimensionToken);

            if (dimensionKey.hasDimensionKeyInCondition()) {
                uint64_t dimensionInConditionToken = protoOutput->start(
                        FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
                writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(),
                                      str_set, protoOutput);
                protoOutput->end(dimensionInConditionToken);
            }
        } else {
            writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInWhat(),
                                           FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
            if (dimensionKey.hasDimensionKeyInCondition()) {
                writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInCondition(),
                                               FIELD_ID_DIMENSION_LEAF_IN_CONDITION,
                                               str_set, protoOutput);
        }
        // Then fill slice_by_state.
        for (auto state : dimensionKey.getStateValuesKey().getValues()) {
            uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
                                                     FIELD_ID_SLICE_BY_STATE);
            writeStateToProto(state, protoOutput);
            protoOutput->end(stateToken);
        }
        // Then fill bucket_info (CountBucketInfo).
        for (const auto& bucket : counter.second) {
@@ -282,7 +280,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked(
    int64_t eventTimeNs = event.GetElapsedTimestampNs();
    flushIfNeededLocked(eventTimeNs);

    if (condition == false) {
    if (!condition) {
        return;
    }

+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ public:

    virtual ~CountMetricProducer();

    void onStateChanged(int atomId, const HashableDimensionKey& primaryKey, int oldState,
    void onStateChanged(int32_t atomId, const HashableDimensionKey& primaryKey, int oldState,
                        int newState) override;

protected:
Loading