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

Commit 0d3813e3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support dimension in condition in metric producers."

parents 52c07474 9369446f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ LOCAL_CFLAGS += \

LOCAL_SRC_FILES := \
    $(statsd_common_src) \
    tests/dimension_test.cpp \
    tests/AnomalyMonitor_test.cpp \
    tests/anomaly/AnomalyTracker_test.cpp \
    tests/ConfigManager_test.cpp \
@@ -190,7 +191,8 @@ LOCAL_SRC_FILES := \
    tests/e2e/WakelockDuration_e2e_test.cpp \
    tests/e2e/MetricConditionLink_e2e_test.cpp \
    tests/e2e/Attribution_e2e_test.cpp \
    tests/e2e/GaugeMetric_e2e_test.cpp
    tests/e2e/GaugeMetric_e2e_test.cpp \
    tests/e2e/DimensionInCondition_e2e_test.cpp

LOCAL_STATIC_LIBRARIES := \
    $(statsd_common_static_libraries) \
+23 −3
Original line number Diff line number Diff line
@@ -67,12 +67,16 @@ android::hash_t hashDimensionsValue(const DimensionsValue& value) {
    return hashDimensionsValue(0, value);
}

android::hash_t hashMetricDimensionKey(int64_t seed, const MetricDimensionKey& dimensionKey) {
    android::hash_t hash = seed;
    hash = android::JenkinsHashMix(hash, std::hash<MetricDimensionKey>{}(dimensionKey));
    return JenkinsHashWhiten(hash);
}

using std::string;

string HashableDimensionKey::toString() const {
    string flattened;
    DimensionsValueToString(getDimensionsValue(), &flattened);
    return flattened;
    return DimensionsValueToString(getDimensionsValue());
}

bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) {
@@ -162,6 +166,22 @@ bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const {
    return LessThan(getDimensionsValue(), that.getDimensionsValue());
};

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

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

bool MetricDimensionKey::operator<(const MetricDimensionKey& that) const {
    return toString().compare(that.toString()) < 0;
};


}  // namespace statsd
}  // namespace os
}  // namespace android
 No newline at end of file
+60 −1
Original line number Diff line number Diff line
@@ -41,6 +41,10 @@ public:
        return mDimensionsValue;
    }

    inline DimensionsValue* getMutableDimensionsValue() {
        return &mDimensionsValue;
    }

    bool operator==(const HashableDimensionKey& that) const;

    bool operator<(const HashableDimensionKey& that) const;
@@ -53,8 +57,52 @@ private:
    DimensionsValue mDimensionsValue;
};

class MetricDimensionKey {
 public:
    explicit MetricDimensionKey(const HashableDimensionKey& dimensionKeyInWhat,
                                const HashableDimensionKey& dimensionKeyInCondition)
        : mDimensionKeyInWhat(dimensionKeyInWhat),
          mDimensionKeyInCondition(dimensionKeyInCondition) {};

    MetricDimensionKey(){};

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

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

    std::string toString() const;

    inline const HashableDimensionKey& getDimensionKeyInWhat() const {
        return mDimensionKeyInWhat;
    }

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

    bool hasDimensionKeyInCondition() const {
        return mDimensionKeyInCondition.getDimensionsValue().has_field();
    }

    bool operator==(const MetricDimensionKey& that) const;

    bool operator<(const MetricDimensionKey& that) const;

    inline const char* c_str() const {
        return toString().c_str();
    }
  private:
      HashableDimensionKey mDimensionKeyInWhat;
      HashableDimensionKey mDimensionKeyInCondition;
};

bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2);

android::hash_t hashDimensionsValue(int64_t seed, const DimensionsValue& value);
android::hash_t hashDimensionsValue(const DimensionsValue& value);
android::hash_t hashMetricDimensionKey(int64_t see, const MetricDimensionKey& dimensionKey);

}  // namespace statsd
}  // namespace os
@@ -63,6 +111,7 @@ android::hash_t hashDimensionsValue(const DimensionsValue& value);
namespace std {

using android::os::statsd::HashableDimensionKey;
using android::os::statsd::MetricDimensionKey;

template <>
struct hash<HashableDimensionKey> {
@@ -71,4 +120,14 @@ struct hash<HashableDimensionKey> {
    }
};

template <>
struct hash<MetricDimensionKey> {
    std::size_t operator()(const MetricDimensionKey& key) const {
        android::hash_t hash = hashDimensionsValue(
            key.getDimensionKeyInWhat().getDimensionsValue());
        hash = android::JenkinsHashMix(hash,
                    hashDimensionsValue(key.getDimensionKeyInCondition().getDimensionsValue()));
        return android::JenkinsHashWhiten(hash);
    }
};
}  // namespace std
 No newline at end of file
+4 −1
Original line number Diff line number Diff line
@@ -104,7 +104,10 @@ private:
    FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
    FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);

    FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricNoLink);
    FRIEND_TEST(DimensionInConditionE2eTest, TestCountMetricWithLink);
    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricNoLink);
    FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetricWithLink);
};

}  // namespace statsd
+9 −9
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ void AnomalyTracker::flushPastBuckets(const int64_t& latestPastBucketNum) {
    }
}

void AnomalyTracker::addPastBucket(const HashableDimensionKey& key, const int64_t& bucketValue,
void AnomalyTracker::addPastBucket(const MetricDimensionKey& key, const int64_t& bucketValue,
                                   const int64_t& bucketNum) {
    flushPastBuckets(bucketNum);

@@ -147,7 +147,7 @@ void AnomalyTracker::addBucketToSum(const shared_ptr<DimToValMap>& bucket) {
    }
}

int64_t AnomalyTracker::getPastBucketValue(const HashableDimensionKey& key,
int64_t AnomalyTracker::getPastBucketValue(const MetricDimensionKey& key,
                                           const int64_t& bucketNum) const {
    const auto& bucket = mPastBuckets[index(bucketNum)];
    if (bucket == nullptr) {
@@ -157,7 +157,7 @@ int64_t AnomalyTracker::getPastBucketValue(const HashableDimensionKey& key,
    return itr == bucket->end() ? 0 : itr->second;
}

int64_t AnomalyTracker::getSumOverPastBuckets(const HashableDimensionKey& key) const {
int64_t AnomalyTracker::getSumOverPastBuckets(const MetricDimensionKey& key) const {
    const auto& itr = mSumOverPastBuckets.find(key);
    if (itr != mSumOverPastBuckets.end()) {
        return itr->second;
@@ -165,7 +165,7 @@ int64_t AnomalyTracker::getSumOverPastBuckets(const HashableDimensionKey& key) c
    return 0;
}

bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const HashableDimensionKey& key,
bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const MetricDimensionKey& key,
                                   const int64_t& currentBucketValue) {
    if (currentBucketNum > mMostRecentBucketNum + 1) {
        // TODO: This creates a needless 0 entry in mSumOverPastBuckets. Fix this.
@@ -175,7 +175,7 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const Hashab
            && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
}

void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const HashableDimensionKey& key) {
void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key) {
    // TODO: Why receive timestamp? RefractoryPeriod should always be based on real time right now.
    if (isInRefractoryPeriod(timestampNs, key)) {
        VLOG("Skipping anomaly declaration since within refractory period");
@@ -199,14 +199,14 @@ void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const HashableD

    StatsdStats::getInstance().noteAnomalyDeclared(mConfigKey, mAlert.id());

    // TODO: This should also take in the const HashableDimensionKey& key?
    // TODO: This should also take in the const MetricDimensionKey& key?
    android::util::stats_write(android::util::ANOMALY_DETECTED, mConfigKey.GetUid(),
                               mConfigKey.GetId(), mAlert.id());
}

void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs,
                                             const int64_t& currBucketNum,
                                             const HashableDimensionKey& key,
                                             const MetricDimensionKey& key,
                                             const int64_t& currentBucketValue) {
    if (detectAnomaly(currBucketNum, key, currentBucketValue)) {
        declareAnomaly(timestampNs, key);
@@ -214,7 +214,7 @@ void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs,
}

bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs,
                                          const HashableDimensionKey& key) {
                                          const MetricDimensionKey& key) {
    const auto& it = mRefractoryPeriodEndsSec.find(key);
    if (it != mRefractoryPeriodEndsSec.end()) {
        if ((timestampNs / NS_PER_SEC) <= it->second) {
@@ -226,7 +226,7 @@ bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs,
    return false;
}

void AnomalyTracker::informSubscribers(const HashableDimensionKey& key) {
void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) {
    VLOG("informSubscribers called.");
    if (mSubscriptions.empty()) {
        ALOGE("Attempt to call with no subscribers.");
Loading