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

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

Merge "Perform update for value metric"

parents 80944216 890f24a6
Loading
Loading
Loading
Loading
+46 −2
Original line number Diff line number Diff line
@@ -18,12 +18,14 @@
#include "Log.h"

#include "ValueMetricProducer.h"
#include "../guardrail/StatsdStats.h"
#include "../stats_log_util.h"

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

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

using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
using android::util::FIELD_TYPE_DOUBLE;
@@ -184,6 +186,48 @@ ValueMetricProducer::~ValueMetricProducer() {
    }
}

bool ValueMetricProducer::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 ValueMetric& metric = config.value_metric(configIndex);
    // Update appropriate indices: mWhatMatcherIndex, mConditionIndex and MetricsManager maps.
    if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, /*enforceOneAtom=*/false,
                                              allAtomMatchingTrackers, newAtomMatchingTrackerMap,
                                              trackerToMetricMap, mWhatMatcherIndex)) {
        return false;
    }

    if (metric.has_condition() &&
        !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
                                    metric.links(), allConditionTrackers, mConditionTrackerIndex,
                                    conditionToMetricMap)) {
        return false;
    }
    sp<EventMatcherWizard> tmpEventWizard = mEventMatcherWizard;
    mEventMatcherWizard = matcherWizard;
    return true;
}

void ValueMetricProducer::onStateChanged(int64_t eventTimeNs, int32_t atomId,
                                         const HashableDimensionKey& primaryKey,
                                         const FieldValue& oldState, const FieldValue& newState) {
+20 −2
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ struct PastValueBucket {
// - a condition change
// - an app upgrade
// - an alarm set to the end of the bucket
class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
class ValueMetricProducer : public MetricProducer, public virtual PullDataReceiver {
public:
    ValueMetricProducer(
            const ConfigKey& key, const ValueMetric& valueMetric, const int conditionIndex,
@@ -155,7 +155,23 @@ private:
    // causes the bucket to be invalidated will not notify StatsdStats.
    void skipCurrentBucket(const int64_t dropTimeNs, const BucketDropReason reason);

    const int mWhatMatcherIndex;
    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;

    int mWhatMatcherIndex;

    sp<EventMatcherWizard> mEventMatcherWizard;

@@ -370,6 +386,8 @@ private:
    FRIEND_TEST(ValueMetricProducerTest_PartialBucket, TestPulledValue);
    FRIEND_TEST(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse);

    FRIEND_TEST(ConfigUpdateTest, TestUpdateValueMetrics);

    friend class ValueMetricProducerTestHelper;
};

+40 −2
Original line number Diff line number Diff line
@@ -580,7 +580,6 @@ bool determineAllMetricUpdateStatuses(const StatsdConfig& config,
            return false;
        }
    }
    // TODO: determine update status for value metrics.
    return true;
}

@@ -749,8 +748,8 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
        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);
        newMetricProducerMap[metric.id()] = metricIndex;
        optional<sp<MetricProducer>> producer;
        switch (metricsToUpdate[metricIndex]) {
            case UPDATE_PRESERVE: {
@@ -784,6 +783,45 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
        }
        newMetricProducers.push_back(producer.value());
    }

    for (int i = 0; i < config.value_metric_size(); i++, metricIndex++) {
        const ValueMetric& metric = config.value_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 = createValueMetricProducerAndUpdateMetadata(
                        key, config, timeBaseNs, currentTimeNs, pullerManager, metric, metricIndex,
                        allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
                        conditionTrackerMap, initialConditionCache, wizard, matcherWizard,
                        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.gauge_metric_size(); i++, metricIndex++) {
        const GaugeMetric& metric = config.gauge_metric(i);
        newMetricProducerMap[metric.id()] = metricIndex;
+111 −86
Original line number Diff line number Diff line
@@ -599,6 +599,108 @@ optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
                                    eventDeactivationMap)};
}

optional<sp<MetricProducer>> createValueMetricProducerAndUpdateMetadata(
        const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
        const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
        const ValueMetric& metric, const int metricIndex,
        const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
        const unordered_map<int64_t, int>& atomMatchingTrackerMap,
        vector<sp<ConditionTracker>>& allConditionTrackers,
        const unordered_map<int64_t, int>& conditionTrackerMap,
        const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
        const sp<EventMatcherWizard>& matcherWizard,
        const unordered_map<int64_t, int>& stateAtomIdMap,
        const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
        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 (!metric.has_id() || !metric.has_what()) {
        ALOGE("cannot find metric id or \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
        return nullopt;
    }
    if (!metric.has_value_field()) {
        ALOGE("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
        return nullopt;
    }
    std::vector<Matcher> fieldMatchers;
    translateFieldMatcher(metric.value_field(), &fieldMatchers);
    if (fieldMatchers.size() < 1) {
        ALOGE("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
        return nullopt;
    }

    int trackerIndex;
    if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
                                              metric.has_dimensions_in_what(),
                                              allAtomMatchingTrackers, atomMatchingTrackerMap,
                                              trackerToMetricMap, trackerIndex)) {
        return nullopt;
    }

    sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
    // If it is pulled atom, it should be simple matcher with one tagId.
    if (atomMatcher->getAtomIds().size() != 1) {
        return nullopt;
    }
    int atomTagId = *(atomMatcher->getAtomIds().begin());
    int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;

    int conditionIndex = -1;
    if (metric.has_condition()) {
        if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
                                        metric.links(), allConditionTrackers, conditionIndex,
                                        conditionToMetricMap)) {
            return nullopt;
        }
    } else if (metric.links_size() > 0) {
        ALOGE("metrics has a MetricConditionLink but doesn't have a condition");
        return nullopt;
    }

    std::vector<int> slicedStateAtoms;
    unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
    if (metric.slice_by_state_size() > 0) {
        if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
                                    allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
            return nullopt;
        }
    } else if (metric.state_link_size() > 0) {
        ALOGE("ValueMetric has a MetricStateLink but doesn't have a sliced state");
        return nullopt;
    }

    // Check that all metric state links are a subset of dimensions_in_what fields.
    std::vector<Matcher> dimensionsInWhat;
    translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
    for (const auto& stateLink : metric.state_link()) {
        if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
            return nullopt;
        }
    }

    unordered_map<int, shared_ptr<Activation>> eventActivationMap;
    unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
    if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
                                          atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
                                          deactivationAtomTrackerToMetricMap, metricsWithActivation,
                                          eventActivationMap, eventDeactivationMap)) {
        return nullopt;
    }

    uint64_t metricHash;
    if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
        return nullopt;
    }

    return {new ValueMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
                                    metricHash, trackerIndex, matcherWizard, pullTagId, timeBaseNs,
                                    currentTimeNs, pullerManager, eventActivationMap,
                                    eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
}

optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
        const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
        const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
@@ -911,97 +1013,20 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t

    // build ValueMetricProducer
    for (int i = 0; i < config.value_metric_size(); i++) {
        const ValueMetric& metric = config.value_metric(i);
        if (!metric.has_what()) {
            ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
            return false;
        }
        if (!metric.has_value_field()) {
            ALOGW("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
            return false;
        }
        std::vector<Matcher> fieldMatchers;
        translateFieldMatcher(metric.value_field(), &fieldMatchers);
        if (fieldMatchers.size() < 1) {
            ALOGW("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
            return false;
        }

        int metricIndex = allMetricProducers.size();
        const ValueMetric& metric = config.value_metric(i);
        metricMap.insert({metric.id(), metricIndex});
        int trackerIndex;
        if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
                                                  metric.has_dimensions_in_what(),
                                                  allAtomMatchingTrackers, atomMatchingTrackerMap,
                                                  trackerToMetricMap, trackerIndex)) {
            return false;
        }

        sp<AtomMatchingTracker> atomMatcher = allAtomMatchingTrackers.at(trackerIndex);
        // If it is pulled atom, it should be simple matcher with one tagId.
        if (atomMatcher->getAtomIds().size() != 1) {
            return false;
        }
        int atomTagId = *(atomMatcher->getAtomIds().begin());
        int pullTagId = pullerManager->PullerForMatcherExists(atomTagId) ? atomTagId : -1;

        int conditionIndex = -1;
        if (metric.has_condition()) {
            bool good = handleMetricWithConditions(
                    metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
                    allConditionTrackers, conditionIndex, conditionToMetricMap);
            if (!good) {
                return false;
            }
        } else {
            if (metric.links_size() > 0) {
                ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
                return false;
            }
        }

        std::vector<int> slicedStateAtoms;
        unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
        if (metric.slice_by_state_size() > 0) {
            if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
                return false;
            }
        } else {
            if (metric.state_link_size() > 0) {
                ALOGW("ValueMetric has a MetricStateLink but doesn't have a sliced state");
                return false;
            }
        }

        // Check that all metric state links are a subset of dimensions_in_what fields.
        std::vector<Matcher> dimensionsInWhat;
        translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
        for (const auto& stateLink : metric.state_link()) {
            if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
                return false;
            }
        }

        unordered_map<int, shared_ptr<Activation>> eventActivationMap;
        unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
        bool success = handleMetricActivation(
                config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
        optional<sp<MetricProducer>> producer = createValueMetricProducerAndUpdateMetadata(
                key, config, timeBaseTimeNs, currentTimeNs, pullerManager, metric, metricIndex,
                allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
                conditionTrackerMap, initialConditionCache, wizard, matcherWizard, stateAtomIdMap,
                allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
                activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
                metricsWithActivation, eventActivationMap, eventDeactivationMap);
        if (!success) return false;

        uint64_t metricHash;
        if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
                metricsWithActivation);
        if (!producer) {
            return false;
        }

        sp<MetricProducer> valueProducer = new ValueMetricProducer(
                key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
                trackerIndex, matcherWizard, pullTagId, timeBaseTimeNs, currentTimeNs,
                pullerManager, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
                stateGroupMap);
        allMetricProducers.push_back(valueProducer);
        allMetricProducers.push_back(producer.value());
    }

    // Gauge metrics.
+21 −0
Original line number Diff line number Diff line
@@ -148,6 +148,27 @@ optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
        std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
        std::vector<int>& metricsWithActivation);

// Creates a CountMetricProducer and updates the vectors/maps used by MetricsManager with
// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
optional<sp<MetricProducer>> createValueMetricProducerAndUpdateMetadata(
        const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
        const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
        const ValueMetric& metric, const int metricIndex,
        const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
        const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
        std::vector<sp<ConditionTracker>>& allConditionTrackers,
        const std::unordered_map<int64_t, int>& conditionTrackerMap,
        const std::vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
        const sp<EventMatcherWizard>& matcherWizard,
        const std::unordered_map<int64_t, int>& stateAtomIdMap,
        const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
        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);

// Creates a GaugeMetricProducer and updates the vectors/maps used by MetricsManager with
// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
Loading