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

Commit cfa32e13 authored by Tej Singh's avatar Tej Singh
Browse files

Perform update for duration metric

Creates a new metric if the metric is new/needs replacement.
Preserves the metrics that can be preserved. Ensures that indices are
updated, including within duration trackers.

Does not handle if a condition is true for a new metric based on an
existing condition.

Test: atest statsd_test
Bug: 162323124
Change-Id: Ibe0baf54678c1c6efde5aeba6a4b9b7fa2634c55
parent 07e62587
Loading
Loading
Loading
Loading
+88 −7
Original line number Diff line number Diff line
@@ -17,14 +17,17 @@
#define DEBUG false

#include "Log.h"

#include "DurationMetricProducer.h"
#include "guardrail/StatsdStats.h"
#include "stats_util.h"
#include "stats_log_util.h"

#include <limits.h>
#include <stdlib.h>

#include "guardrail/StatsdStats.h"
#include "metrics/parsing_utils/metrics_manager_util.h"
#include "stats_log_util.h"
#include "stats_util.h"

using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
using android::util::FIELD_TYPE_FLOAT;
@@ -64,8 +67,8 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;

DurationMetricProducer::DurationMetricProducer(
        const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
        const vector<ConditionState>& initialConditionCache, const size_t startIndex,
        const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
        const vector<ConditionState>& initialConditionCache, const int startIndex,
        const int stopIndex, const int stopAllIndex, const bool nesting,
        const sp<ConditionWizard>& wizard, const uint64_t protoHash,
        const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
        const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
@@ -143,6 +146,84 @@ DurationMetricProducer::~DurationMetricProducer() {
    VLOG("~DurationMetric() called");
}

bool DurationMetricProducer::onConfigUpdatedLocked(
        const StatsdConfig& config, const int configIndex, const int metricIndex,
        const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
        const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
        const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
        const sp<EventMatcherWizard>& matcherWizard,
        const vector<sp<ConditionTracker>>& allConditionTrackers,
        const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
        const unordered_map<int64_t, int>& metricToActivationMap,
        unordered_map<int, vector<int>>& trackerToMetricMap,
        unordered_map<int, vector<int>>& conditionToMetricMap,
        unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
        unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
        vector<int>& metricsWithActivation) {
    if (!MetricProducer::onConfigUpdatedLocked(
                config, configIndex, metricIndex, allAtomMatchingTrackers,
                oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
                allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
                trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
                deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
        return false;
    }

    const DurationMetric& metric = config.duration_metric(configIndex);
    const auto& what_it = conditionTrackerMap.find(metric.what());
    if (what_it == conditionTrackerMap.end()) {
        ALOGE("DurationMetric's \"what\" is not present in the config");
        return false;
    }

    const Predicate& durationWhat = config.predicate(what_it->second);
    if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
        ALOGE("DurationMetric's \"what\" must be a simple condition");
        return false;
    }

    const SimplePredicate& simplePredicate = durationWhat.simple_predicate();

    // Update indices: mStartIndex, mStopIndex, mStopAllIndex, mConditionIndex and MetricsManager
    // maps.
    if (!handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
                                              metric.has_dimensions_in_what(),
                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
                                              trackerToMetricMap, mStartIndex)) {
        ALOGE("Duration metrics must specify a valid start event matcher");
        return false;
    }

    if (simplePredicate.has_stop() &&
        !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
                                              metric.has_dimensions_in_what(),
                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
                                              trackerToMetricMap, mStopIndex)) {
        return false;
    }

    if (simplePredicate.has_stop_all() &&
        !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
                                              metric.has_dimensions_in_what(),
                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
                                              trackerToMetricMap, mStopAllIndex)) {
        return false;
    }

    if (metric.has_condition() &&
        !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
                                    metric.links(), allConditionTrackers, mConditionTrackerIndex,
                                    conditionToMetricMap)) {
        return false;
    }

    for (const auto& it : mCurrentSlicedDurationTrackerMap) {
        it.second->onConfigUpdated(wizard, mConditionTrackerIndex);
    }

    return true;
}

sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
        const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) {
    std::lock_guard<std::mutex> lock(mMutex);
@@ -550,7 +631,7 @@ void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
    }

    // Handles Stopall events.
    if (matcherIndex == mStopAllIndex) {
    if ((int)matcherIndex == mStopAllIndex) {
        for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
            whatIt.second->noteStopAll(event.GetElapsedTimestampNs());
        }
@@ -598,7 +679,7 @@ void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
    }

    // Handles Stop events.
    if (matcherIndex == mStopIndex) {
    if ((int)matcherIndex == mStopIndex) {
        if (mUseWhatDimensionAsInternalDimension) {
            auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
            if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
+23 −5
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ class DurationMetricProducer : public MetricProducer {
public:
    DurationMetricProducer(
            const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
            const vector<ConditionState>& initialConditionCache, const size_t startIndex,
            const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
            const vector<ConditionState>& initialConditionCache, const int startIndex,
            const int stopIndex, const int stopAllIndex, const bool nesting,
            const sp<ConditionWizard>& wizard, const uint64_t protoHash,
            const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
            const int64_t startTimeNs,
@@ -112,16 +112,32 @@ private:
    void flushCurrentBucketLocked(const int64_t& eventTimeNs,
                                  const int64_t& nextBucketStartTimeNs) override;

    bool onConfigUpdatedLocked(
            const StatsdConfig& config, const int configIndex, const int metricIndex,
            const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
            const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
            const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
            const sp<EventMatcherWizard>& matcherWizard,
            const std::vector<sp<ConditionTracker>>& allConditionTrackers,
            const std::unordered_map<int64_t, int>& conditionTrackerMap,
            const sp<ConditionWizard>& wizard,
            const std::unordered_map<int64_t, int>& metricToActivationMap,
            std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
            std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
            std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
            std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
            std::vector<int>& metricsWithActivation) override;

    const DurationMetric_AggregationType mAggregationType;

    // Index of the SimpleAtomMatcher which defines the start.
    const size_t mStartIndex;
    int mStartIndex;

    // Index of the SimpleAtomMatcher which defines the stop.
    const size_t mStopIndex;
    int mStopIndex;

    // Index of the SimpleAtomMatcher which defines the stop all for all dimensions.
    const size_t mStopAllIndex;
    int mStopAllIndex;

    // nest counting -- for the same key, stops must match the number of starts to make real stop
    const bool mNested;
@@ -167,6 +183,8 @@ private:
                TestSumDurationWithSplitInFollowingBucket);
    FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDuration);
    FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextBucket);

    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
};

}  // namespace statsd
+1 −0
Original line number Diff line number Diff line
@@ -569,6 +569,7 @@ protected:
    FRIEND_TEST(ConfigUpdateTest, TestUpdateCountMetrics);
    FRIEND_TEST(ConfigUpdateTest, TestUpdateEventMetrics);
    FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
    FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
};

+9 −1
Original line number Diff line number Diff line
@@ -89,6 +89,12 @@ public:

    virtual ~DurationTracker(){};

    void onConfigUpdated(const sp<ConditionWizard>& wizard, const int conditionTrackerIndex) {
        sp<ConditionWizard> tmpWizard = mWizard;
        mWizard = wizard;
        mConditionTrackerIndex = conditionTrackerIndex;
    };

    virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
                           const ConditionKey& conditionKey) = 0;
    virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
@@ -191,7 +197,7 @@ protected:

    sp<ConditionWizard> mWizard;

    const int mConditionTrackerIndex;
    int mConditionTrackerIndex;

    const int64_t mBucketSizeNs;

@@ -217,6 +223,8 @@ protected:
    FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
    FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
    FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);

    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
};

}  // namespace statsd
+38 −1
Original line number Diff line number Diff line
@@ -697,6 +697,43 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
        }
        newMetricProducers.push_back(producer.value());
    }
    for (int i = 0; i < config.duration_metric_size(); i++, metricIndex++) {
        const DurationMetric& metric = config.duration_metric(i);
        newMetricProducerMap[metric.id()] = metricIndex;
        optional<sp<MetricProducer>> producer;
        switch (metricsToUpdate[metricIndex]) {
            case UPDATE_PRESERVE: {
                producer = updateMetric(
                        config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
                        oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
                        allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
                        oldMetricProducers, metricToActivationMap, trackerToMetricMap,
                        conditionToMetricMap, activationAtomTrackerToMetricMap,
                        deactivationAtomTrackerToMetricMap, metricsWithActivation);
                break;
            }
            case UPDATE_REPLACE:
            case UPDATE_NEW: {
                producer = createDurationMetricProducerAndUpdateMetadata(
                        key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
                        allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
                        conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
                        allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
                        conditionToMetricMap, activationAtomTrackerToMetricMap,
                        deactivationAtomTrackerToMetricMap, metricsWithActivation);
                break;
            }
            default: {
                ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
                      (long long)metric.id());
                return false;
            }
        }
        if (!producer) {
            return false;
        }
        newMetricProducers.push_back(producer.value());
    }
    for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
        newMetricProducerMap[config.event_metric(i).id()] = metricIndex;
        const EventMetric& metric = config.event_metric(i);
@@ -770,7 +807,7 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
        }
        newMetricProducers.push_back(producer.value());
    }
    // TODO: perform update for value, duration metric.
    // TODO: perform update for value metric.

    const set<int> atomsAllowedFromAnyUid(config.whitelisted_atom_ids().begin(),
                                          config.whitelisted_atom_ids().end());
Loading