summaryrefslogtreecommitdiff
path: root/statsd/src/metrics/DurationMetricProducer.h
blob: a36629216c9580e37522180ed2d75eea5a47b475 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <android/util/ProtoOutputStream.h>

#include <unordered_map>

#include "../anomaly/DurationAnomalyTracker.h"
#include "../condition/ConditionTracker.h"
#include "../matchers/matcher_util.h"
#include "MetricProducer.h"
#include "duration_helper/DurationTracker.h"
#include "duration_helper/MaxDurationTracker.h"
#include "duration_helper/OringDurationTracker.h"
#include "src/statsd_config.pb.h"
#include "stats_util.h"

using namespace std;

namespace android {
namespace os {
namespace statsd {

class DurationMetricProducer : public MetricProducer {
public:
    DurationMetricProducer(
            const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
            const vector<ConditionState>& initialConditionCache, const int whatIndex,
            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 = {},
            const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap = {},
            const vector<int>& slicedStateAtoms = {},
            const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});

    virtual ~DurationMetricProducer();

    sp<AnomalyTracker> addAnomalyTracker(const Alert& alert,
                                         const sp<AlarmMonitor>& anomalyAlarmMonitor,
                                         const UpdateStatus& updateStatus,
                                         const int64_t updateTimeNs) override;

    void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker, const int64_t updateTimeNs) override;

    void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
                        const HashableDimensionKey& primaryKey, const FieldValue& oldState,
                        const FieldValue& newState) override;

    MetricType getMetricType() const override {
        return METRIC_TYPE_DURATION;
    }

protected:
    void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;

    void onMatchedLogEventInternalLocked(
            const size_t matcherIndex, const MetricDimensionKey& eventKey,
            const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
            const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;

private:
    // Initializes true dimensions of the 'what' predicate. Only to be called during initialization.
    void initTrueDimensions(const int whatIndex, const int64_t startTimeNs);

    void handleMatchedLogEventValuesLocked(const size_t matcherIndex,
                                           const std::vector<FieldValue>& values,
                                           const int64_t eventTimeNs);
    void handleStartEvent(const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys,
                          bool condition, const int64_t eventTimeNs,
                          const vector<FieldValue>& eventValues);

    void onDumpReportLocked(const int64_t dumpTimeNs,
                            const bool include_current_partial_bucket,
                            const bool erase_data,
                            const DumpLatency dumpLatency,
                            std::set<string> *str_set,
                            android::util::ProtoOutputStream* protoOutput) override;

    void clearPastBucketsLocked(const int64_t dumpTimeNs) override;

    // Internal interface to handle condition change.
    void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;

    // Internal interface to handle active state change.
    void onActiveStateChangedLocked(const int64_t eventTimeNs, const bool isActive) override;

    // Internal interface to handle sliced condition change.
    void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;

    void onSlicedConditionMayChangeInternalLocked(const int64_t eventTimeNs);

    void onSlicedConditionMayChangeLocked_opt1(const int64_t eventTime);

    // Internal function to calculate the current used bytes.
    size_t byteSizeLocked() const override;

    void dumpStatesLocked(int out, bool verbose) const override;

    void dropDataLocked(const int64_t dropTimeNs) override;

    // Util function to flush the old packet.
    void flushIfNeededLocked(const int64_t& eventTime);

    void flushCurrentBucketLocked(const int64_t& eventTimeNs,
                                  const int64_t& nextBucketStartTimeNs) override;

    optional<InvalidConfigReason> 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;

    void addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker,
                                 const UpdateStatus& updateStatus, const int64_t updateTimeNs);

    const DurationMetric_AggregationType mAggregationType;

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

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

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

    // nest counting -- for the same key, stops must match the number of starts to make real stop
    const bool mNested;

    // The dimension from the atom predicate. e.g., uid, wakelock name.
    vector<Matcher> mInternalDimensions;

    bool mContainANYPositionInInternalDimensions;

    // This boolean is true iff When mInternalDimensions == mDimensionsInWhat
    bool mUseWhatDimensionAsInternalDimension;

    // Caches the current unsliced part condition.
    ConditionState mUnSlicedPartCondition;

    // Save the past buckets and we can clear when the StatsLogReport is dumped.
    std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>> mPastBuckets;

    // The duration trackers in the current bucket.
    std::unordered_map<HashableDimensionKey, std::unique_ptr<DurationTracker>>
            mCurrentSlicedDurationTrackerMap;

    const size_t mDimensionHardLimit;

    // Helper function to create a duration tracker given the metric aggregation type.
    std::unique_ptr<DurationTracker> createDurationTracker(
            const MetricDimensionKey& eventKey) const;

    // Util function to check whether the specified dimension hits the guardrail.
    bool hitGuardRailLocked(const MetricDimensionKey& newKey) const;

    static const size_t kBucketSize = sizeof(DurationBucket{});

    FRIEND_TEST(DurationMetricTrackerTest, TestNoCondition);
    FRIEND_TEST(DurationMetricTrackerTest, TestNonSlicedCondition);
    FRIEND_TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState);
    FRIEND_TEST(DurationMetricTrackerTest, TestFirstBucket);

    FRIEND_TEST(DurationMetricProducerTest, TestSumDurationAppUpgradeSplitDisabled);
    FRIEND_TEST(DurationMetricProducerTest, TestClearCurrentSlicedTrackerMapWhenStop);
    FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestSumDuration);
    FRIEND_TEST(DurationMetricProducerTest_PartialBucket,
                TestSumDurationWithSplitInFollowingBucket);
    FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDuration);
    FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextBucket);

    FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
    FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);

    FRIEND_TEST(MetricsManagerUtilDimLimitTest, TestDimLimit);

    FRIEND_TEST(ConfigUpdateDimLimitTest, TestDimLimit);
};

}  // namespace statsd
}  // namespace os
}  // namespace android