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

Commit 3a5ebf58 authored by Muhammad Qureshi's avatar Muhammad Qureshi
Browse files

Cancel Metric activations

Cancel Metric activations triggered by atom matchers

Bug: 128218061
Test: statsd_test
Test: statsd_localdrive
Change-Id: I90a705d74725c2aa04025e18e1fa77ec4fefc522
parent 9b5f87d2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -257,6 +257,9 @@ private:
    FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
    FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
};

}  // namespace statsd
+34 −20
Original line number Diff line number Diff line
@@ -70,11 +70,11 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo
bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) {
    bool isActive = mEventActivationMap.empty();
    for (auto& it : mEventActivationMap) {
        if (it.second.state == ActivationState::kActive &&
            elapsedTimestampNs > it.second.ttl_ns + it.second.activation_ns) {
            it.second.state = ActivationState::kNotActive;
        if (it.second->state == ActivationState::kActive &&
            elapsedTimestampNs > it.second->ttl_ns + it.second->activation_ns) {
            it.second->state = ActivationState::kNotActive;
        }
        if (it.second.state == ActivationState::kActive) {
        if (it.second->state == ActivationState::kActive) {
            isActive = true;
        }
    }
@@ -92,7 +92,8 @@ void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) {
    }
}

void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds) {
void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds,
                                   int deactivationTrackerIndex) {
    std::lock_guard<std::mutex> lock(mMutex);
    // When a metric producer does not depend on any activation, its mIsActive is true.
    // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
@@ -100,7 +101,12 @@ void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_secon
    if  (mEventActivationMap.empty()) {
        mIsActive = false;
    }
    mEventActivationMap[activationTrackerIndex].ttl_ns = ttl_seconds * NS_PER_SEC;
    std::shared_ptr<Activation> activation = std::make_shared<Activation>();
    activation->ttl_ns = ttl_seconds * NS_PER_SEC;
    mEventActivationMap.emplace(activationTrackerIndex, activation);
    if (-1 != deactivationTrackerIndex) {
        mEventDeactivationMap.emplace(deactivationTrackerIndex, activation);
    }
}

void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs) {
@@ -109,27 +115,35 @@ void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedT
        return;
    }
    if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT &&
        it->second.state == ActivationState::kNotActive) {
        it->second.state = ActivationState::kActiveOnBoot;
        it->second->state == ActivationState::kNotActive) {
        it->second->state = ActivationState::kActiveOnBoot;
        return;
    }
    it->second.activation_ns = elapsedTimestampNs;
    it->second.state = ActivationState::kActive;
    it->second->activation_ns = elapsedTimestampNs;
    it->second->state = ActivationState::kActive;
    mIsActive = true;
}

void MetricProducer::cancelEventActivationLocked(int deactivationTrackerIndex) {
    auto it = mEventDeactivationMap.find(deactivationTrackerIndex);
    if (it == mEventDeactivationMap.end()) {
        return;
    }
    it->second->state = ActivationState::kNotActive;
}

void MetricProducer::setActiveLocked(int64_t currentTimeNs, int64_t remainingTtlNs) {
    if (mEventActivationMap.size() == 0) {
        return;
    }
    for (auto& pair : mEventActivationMap) {
        auto& activation = pair.second;
        if (activation.ttl_ns >= remainingTtlNs) {
            activation.activation_ns = currentTimeNs + remainingTtlNs - activation.ttl_ns;
            activation.state = kActive;
        if (activation->ttl_ns >= remainingTtlNs) {
            activation->activation_ns = currentTimeNs + remainingTtlNs - activation->ttl_ns;
            activation->state = kActive;
            mIsActive = true;
            VLOG("setting new activation time to %lld, %lld, %lld",
                 (long long)activation.activation_ns, (long long)currentTimeNs,
            VLOG("setting new activation->time to %lld, %lld, %lld",
                 (long long)activation->activation_ns, (long long)currentTimeNs,
                 (long long)remainingTtlNs);
            return;
        }
@@ -140,8 +154,8 @@ void MetricProducer::setActiveLocked(int64_t currentTimeNs, int64_t remainingTtl
int64_t MetricProducer::getRemainingTtlNsLocked(int64_t currentTimeNs) const {
    int64_t maxTtl = 0;
    for (const auto& activation : mEventActivationMap) {
        if (activation.second.state == kActive) {
            maxTtl = std::max(maxTtl, activation.second.ttl_ns + activation.second.activation_ns -
        if (activation.second->state == kActive) {
            maxTtl = std::max(maxTtl, activation.second->ttl_ns + activation.second->activation_ns -
                                              currentTimeNs);
        }
    }
@@ -153,9 +167,9 @@ void MetricProducer::prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs) {
        return;
    }
    for (auto& activation : mEventActivationMap) {
        if (activation.second.state == kActiveOnBoot) {
            activation.second.state = kActive;
            activation.second.activation_ns = currentTimeNs;
        if (activation.second->state == kActiveOnBoot) {
            activation.second->state = kActive;
            activation.second->activation_ns = currentTimeNs;
            mIsActive = true;
        }
    }
+15 −2
Original line number Diff line number Diff line
@@ -228,6 +228,11 @@ public:
        activateLocked(activationTrackerIndex, elapsedTimestampNs);
    }

    void cancelEventActivation(int deactivationTrackerIndex) {
        std::lock_guard<std::mutex> lock(mMutex);
        cancelEventActivationLocked(deactivationTrackerIndex);
    }

    bool isActive() const {
        std::lock_guard<std::mutex> lock(mMutex);
        return isActiveLocked();
@@ -238,7 +243,8 @@ public:
        prepActiveForBootIfNecessaryLocked(currentTimeNs);
    }

    void addActivation(int activationTrackerIndex, int64_t ttl_seconds);
    void addActivation(int activationTrackerIndex, int64_t ttl_seconds,
                       int deactivationTrackerIndex = -1);

    inline void setActivationType(const MetricActivation::ActivationType& activationType) {
        mActivationType = activationType;
@@ -263,6 +269,7 @@ protected:
    bool evaluateActiveStateLocked(int64_t elapsedTimestampNs);

    void activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs);
    void cancelEventActivationLocked(int deactivationTrackerIndex);

    inline bool isActiveLocked() const {
        return mIsActive;
@@ -391,13 +398,19 @@ protected:
    };
    // When the metric producer has multiple activations, these activations are ORed to determine
    // whether the metric producer is ready to generate metrics.
    std::unordered_map<int, Activation> mEventActivationMap;
    std::unordered_map<int, std::shared_ptr<Activation>> mEventActivationMap;

    // Maps index of atom matcher for deactivation to Activation struct.
    std::unordered_map<int, std::shared_ptr<Activation>> mEventDeactivationMap;

    bool mIsActive;

    MetricActivation::ActivationType mActivationType;

    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);

    FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
    FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
+47 −9
Original line number Diff line number Diff line
@@ -74,7 +74,8 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
            timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
            mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
            mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
            mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
            mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
            mMetricIndexesWithActivation, mNoReportMetricIds);

    mHashStringsInReport = config.hash_strings_in_metric_report();
    mVersionStringsInReport = config.version_strings_in_metric_report();
@@ -344,24 +345,61 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
    int64_t eventTimeNs = event.GetElapsedTimestampNs();

    bool isActive = mIsAlwaysActive;
    for (int metric : mMetricIndexesWithActivation) {
        mAllMetricProducers[metric]->flushIfExpire(eventTimeNs);
        isActive |= mAllMetricProducers[metric]->isActive();

    // Set of metrics that are still active after flushing.
    unordered_set<int> activeMetricsIndices;

    // Update state of all metrics w/ activation conditions as of eventTimeNs.
    for (int metricIndex : mMetricIndexesWithActivation) {
        const sp<MetricProducer>& metric = mAllMetricProducers[metricIndex];
        metric->flushIfExpire(eventTimeNs);
        if (metric->isActive()) {
            // If this metric w/ activation condition is still active after
            // flushing, remember it.
            activeMetricsIndices.insert(metricIndex);
        }
    }

    mIsActive = isActive;
    mIsActive = isActive || !activeMetricsIndices.empty();

    if (mTagIds.find(tagId) == mTagIds.end()) {
        // not interesting...
        // Not interesting...
        return;
    }

    vector<MatchingState> matcherCache(mAllAtomMatchers.size(), MatchingState::kNotComputed);

    // Evaluate all atom matchers.
    for (auto& matcher : mAllAtomMatchers) {
        matcher->onLogEvent(event, mAllAtomMatchers, matcherCache);
    }

    // Set of metrics that received an activation cancellation.
    unordered_set<int> metricIndicesWithCanceledActivations;

    // Determine which metric activations received a cancellation and cancel them.
    for (const auto& it : mDeactivationAtomTrackerToMetricMap) {
        if (matcherCache[it.first] == MatchingState::kMatched) {
            for (int metricIndex : it.second) {
                mAllMetricProducers[metricIndex]->cancelEventActivation(it.first);
                metricIndicesWithCanceledActivations.insert(metricIndex);
            }
        }
    }

    // Determine whether any metrics are no longer active after cancelling metric activations.
    for (const int metricIndex : metricIndicesWithCanceledActivations) {
        const sp<MetricProducer>& metric = mAllMetricProducers[metricIndex];
        metric->flushIfExpire(eventTimeNs);
        if (!metric->isActive()) {
            activeMetricsIndices.erase(metricIndex);
        }
    }

    isActive |= !activeMetricsIndices.empty();


    // Determine which metric activations should be turned on and turn them on
    for (const auto& it : mActivationAtomTrackerToMetricMap) {
        if (matcherCache[it.first] == MatchingState::kMatched) {
            for (int metricIndex : it.second) {
@@ -406,12 +444,12 @@ void MetricsManager::onLogEvent(const LogEvent& event) {
        if (pair != mConditionToMetricMap.end()) {
            auto& metricList = pair->second;
            for (auto metricIndex : metricList) {
                // metric cares about non sliced condition, and it's changed.
                // Metric cares about non sliced condition, and it's changed.
                // Push the new condition to it directly.
                if (!mAllMetricProducers[metricIndex]->isConditionSliced()) {
                    mAllMetricProducers[metricIndex]->onConditionChanged(conditionCache[i],
                                                                         eventTimeNs);
                    // metric cares about sliced conditions, and it may have changed. Send
                    // Metric cares about sliced conditions, and it may have changed. Send
                    // notification, and the metric can query the sliced conditions that are
                    // interesting to it.
                } else {
+10 −4
Original line number Diff line number Diff line
@@ -225,18 +225,21 @@ private:

    // The following map is initialized from the statsd_config.

    // maps from the index of the LogMatchingTracker to index of MetricProducer.
    // Maps from the index of the LogMatchingTracker to index of MetricProducer.
    std::unordered_map<int, std::vector<int>> mTrackerToMetricMap;

    // maps from LogMatchingTracker to ConditionTracker
    // Maps from LogMatchingTracker to ConditionTracker
    std::unordered_map<int, std::vector<int>> mTrackerToConditionMap;

    // maps from ConditionTracker to MetricProducer
    // Maps from ConditionTracker to MetricProducer
    std::unordered_map<int, std::vector<int>> mConditionToMetricMap;

    // maps from life span triggering event to MetricProducers.
    // Maps from life span triggering event to MetricProducers.
    std::unordered_map<int, std::vector<int>> mActivationAtomTrackerToMetricMap;

    // Maps deactivation triggering event to MetricProducers.
    std::unordered_map<int, std::vector<int>> mDeactivationAtomTrackerToMetricMap;

    std::vector<int> mMetricIndexesWithActivation;

    void initLogSourceWhiteList();
@@ -281,6 +284,9 @@ private:
    FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
    FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
    FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);

    FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
    FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
Loading