1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "anomaly/AlarmMonitor.h"
20 #include "anomaly/AlarmTracker.h"
21 #include "anomaly/AnomalyTracker.h"
22 #include "condition/ConditionTracker.h"
23 #include "config/ConfigKey.h"
24 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
25 #include "logd/LogEvent.h"
26 #include "matchers/LogMatchingTracker.h"
27 #include "metrics/MetricProducer.h"
28 #include "packages/UidMap.h"
29 
30 #include <unordered_map>
31 
32 namespace android {
33 namespace os {
34 namespace statsd {
35 
36 // A MetricsManager is responsible for managing metrics from one single config source.
37 class MetricsManager : public PackageInfoListener {
38 public:
39     MetricsManager(const ConfigKey& configKey, const StatsdConfig& config,
40                    const int64_t timeBaseNs, const int64_t currentTimeNs,
41                    const sp<UidMap>& uidMap, const sp<AlarmMonitor>& anomalyAlarmMonitor,
42                    const sp<AlarmMonitor>& periodicAlarmMonitor);
43 
44     virtual ~MetricsManager();
45 
46     // Return whether the configuration is valid.
47     bool isConfigValid() const;
48 
49     void onLogEvent(const LogEvent& event);
50 
51     void onAnomalyAlarmFired(
52         const int64_t& timestampNs,
53         unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
54 
55     void onPeriodicAlarmFired(
56         const int64_t& timestampNs,
57         unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
58 
59     void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
60                           const int64_t version) override;
61 
62     void notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, const int uid) override;
63 
64     void onUidMapReceived(const int64_t& eventTimeNs) override;
65 
shouldAddUidMapListener()66     bool shouldAddUidMapListener() const {
67         return !mAllowedPkg.empty();
68     }
69 
shouldWriteToDisk()70     bool shouldWriteToDisk() const {
71         return mNoReportMetricIds.size() != mAllMetricProducers.size();
72     }
73 
74     void dumpStates(FILE* out, bool verbose);
75 
isInTtl(const int64_t timestampNs)76     inline bool isInTtl(const int64_t timestampNs) const {
77         return mTtlNs <= 0 || timestampNs < mTtlEndNs;
78     };
79 
hashStringInReport()80     inline bool hashStringInReport() const {
81         return mHashStringsInReport;
82     };
83 
refreshTtl(const int64_t currentTimestampNs)84     void refreshTtl(const int64_t currentTimestampNs) {
85         if (mTtlNs > 0) {
86             mTtlEndNs = currentTimestampNs + mTtlNs;
87         }
88     };
89 
90     // Returns the elapsed realtime when this metric manager last reported metrics. If this config
91     // has not yet dumped any reports, this is the time the metricsmanager was initialized.
getLastReportTimeNs()92     inline int64_t getLastReportTimeNs() const {
93         return mLastReportTimeNs;
94     };
95 
getLastReportWallClockNs()96     inline int64_t getLastReportWallClockNs() const {
97         return mLastReportWallClockNs;
98     };
99 
getNumMetrics()100     inline size_t getNumMetrics() const {
101         return mAllMetricProducers.size();
102     }
103 
104     virtual void dropData(const int64_t dropTimeNs);
105 
106     virtual void onDumpReport(const int64_t dumpTimeNs,
107                               const bool include_current_partial_bucket,
108                               std::set<string> *str_set,
109                               android::util::ProtoOutputStream* protoOutput);
110 
111     // Computes the total byte size of all metrics managed by a single config source.
112     // Does not change the state.
113     virtual size_t byteSize();
114 
115 private:
116     // For test only.
getTtlEndNs()117     inline int64_t getTtlEndNs() const { return mTtlEndNs; }
118 
119     const ConfigKey mConfigKey;
120 
121     sp<UidMap> mUidMap;
122 
123     bool mConfigValid = false;
124 
125     bool mHashStringsInReport = false;
126 
127     const int64_t mTtlNs;
128     int64_t mTtlEndNs;
129 
130     int64_t mLastReportTimeNs;
131     int64_t mLastReportWallClockNs;
132 
133     // The uid log sources from StatsdConfig.
134     std::vector<int32_t> mAllowedUid;
135 
136     // The pkg log sources from StatsdConfig.
137     std::vector<std::string> mAllowedPkg;
138 
139     // The combined uid sources (after translating pkg name to uid).
140     // Logs from uids that are not in the list will be ignored to avoid spamming.
141     std::set<int32_t> mAllowedLogSources;
142 
143     // Contains the annotations passed in with StatsdConfig.
144     std::list<std::pair<const int64_t, const int32_t>> mAnnotations;
145 
146     // To guard access to mAllowedLogSources
147     mutable std::mutex mAllowedLogSourcesMutex;
148 
149     // All event tags that are interesting to my metrics.
150     std::set<int> mTagIds;
151 
152     // We only store the sp of LogMatchingTracker, MetricProducer, and ConditionTracker in
153     // MetricsManager. There are relationships between them, and the relationships are denoted by
154     // index instead of pointers. The reasons for this are: (1) the relationship between them are
155     // complicated, so storing index instead of pointers reduces the risk that A holds B's sp, and B
156     // holds A's sp. (2) When we evaluate matcher results, or condition results, we can quickly get
157     // the related results from a cache using the index.
158 
159     // Hold all the atom matchers from the config.
160     std::vector<sp<LogMatchingTracker>> mAllAtomMatchers;
161 
162     // Hold all the conditions from the config.
163     std::vector<sp<ConditionTracker>> mAllConditionTrackers;
164 
165     // Hold all metrics from the config.
166     std::vector<sp<MetricProducer>> mAllMetricProducers;
167 
168     // Hold all alert trackers.
169     std::vector<sp<AnomalyTracker>> mAllAnomalyTrackers;
170 
171     // Hold all periodic alarm trackers.
172     std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers;
173 
174     // To make the log processing more efficient, we want to do as much filtering as possible
175     // before we go into individual trackers and conditions to match.
176 
177     // 1st filter: check if the event tag id is in mTagIds.
178     // 2nd filter: if it is, we parse the event because there is at least one member is interested.
179     //             then pass to all LogMatchingTrackers (itself also filter events by ids).
180     // 3nd filter: for LogMatchingTrackers that matched this event, we pass this event to the
181     //             ConditionTrackers and MetricProducers that use this matcher.
182     // 4th filter: for ConditionTrackers that changed value due to this event, we pass
183     //             new conditions to  metrics that use this condition.
184 
185     // The following map is initialized from the statsd_config.
186 
187     // maps from the index of the LogMatchingTracker to index of MetricProducer.
188     std::unordered_map<int, std::vector<int>> mTrackerToMetricMap;
189 
190     // maps from LogMatchingTracker to ConditionTracker
191     std::unordered_map<int, std::vector<int>> mTrackerToConditionMap;
192 
193     // maps from ConditionTracker to MetricProducer
194     std::unordered_map<int, std::vector<int>> mConditionToMetricMap;
195 
196     void initLogSourceWhiteList();
197 
198     // The metrics that don't need to be uploaded or even reported.
199     std::set<int64_t> mNoReportMetricIds;
200 
201     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
202     FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
203     FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
204     FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
205     FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
206     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
207     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
208     FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
209     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
210     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
211     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
212     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
213     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
214     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_OR_CombinationCondition);
215 
216     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_SimpleCondition);
217     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_SimpleCondition);
218     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_SimpleCondition);
219     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition);
220     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition);
221     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_PartialLink_AND_CombinationCondition);
222 
223     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
224     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
225     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
226     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
227     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
228 
229     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
230     FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
231 };
232 
233 }  // namespace statsd
234 }  // namespace os
235 }  // namespace android
236