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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
|
/*
* 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 "anomaly/AlarmMonitor.h"
#include "anomaly/AlarmTracker.h"
#include "anomaly/AnomalyTracker.h"
#include "condition/ConditionTracker.h"
#include "config/ConfigKey.h"
#include "external/StatsPullerManager.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h"
#include "logd/LogEvent.h"
#include "matchers/LogMatchingTracker.h"
#include "metrics/MetricProducer.h"
#include "packages/UidMap.h"
#include <unordered_map>
namespace android {
namespace os {
namespace statsd {
// A MetricsManager is responsible for managing metrics from one single config source.
class MetricsManager : public virtual android::RefBase, public virtual PullUidProvider {
public:
MetricsManager(const ConfigKey& configKey, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor);
virtual ~MetricsManager();
// Return whether the configuration is valid.
bool isConfigValid() const;
bool checkLogCredentials(const LogEvent& event);
bool eventSanityCheck(const LogEvent& event);
void onLogEvent(const LogEvent& event);
void onAnomalyAlarmFired(
const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
void onPeriodicAlarmFired(
const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version);
void notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, const int uid);
void onUidMapReceived(const int64_t& eventTimeNs);
void onStatsdInitCompleted(const int64_t& elapsedTimeNs);
void init();
vector<int32_t> getPullAtomUids(int32_t atomId) override;
bool shouldWriteToDisk() const {
return mNoReportMetricIds.size() != mAllMetricProducers.size();
}
bool shouldPersistLocalHistory() const {
return mShouldPersistHistory;
}
void dumpStates(FILE* out, bool verbose);
inline bool isInTtl(const int64_t timestampNs) const {
return mTtlNs <= 0 || timestampNs < mTtlEndNs;
};
inline bool hashStringInReport() const {
return mHashStringsInReport;
};
inline bool versionStringsInReport() const {
return mVersionStringsInReport;
};
inline bool installerInReport() const {
return mInstallerInReport;
};
void refreshTtl(const int64_t currentTimestampNs) {
if (mTtlNs > 0) {
mTtlEndNs = currentTimestampNs + mTtlNs;
}
};
// Returns the elapsed realtime when this metric manager last reported metrics. If this config
// has not yet dumped any reports, this is the time the metricsmanager was initialized.
inline int64_t getLastReportTimeNs() const {
return mLastReportTimeNs;
};
inline int64_t getLastReportWallClockNs() const {
return mLastReportWallClockNs;
};
inline size_t getNumMetrics() const {
return mAllMetricProducers.size();
}
virtual void dropData(const int64_t dropTimeNs);
virtual void onDumpReport(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);
// Computes the total byte size of all metrics managed by a single config source.
// Does not change the state.
virtual size_t byteSize();
// Returns whether or not this config is active.
// The config is active if any metric in the config is active.
inline bool isActive() const {
return mIsActive;
}
void loadActiveConfig(const ActiveConfig& config, int64_t currentTimeNs);
void writeActiveConfigToProtoOutputStream(
int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
// Returns true if at least one piece of metadata is written.
bool writeMetadataToProto(int64_t currentWallClockTimeNs,
int64_t systemElapsedTimeNs,
metadata::StatsMetadata* statsMetadata);
void loadMetadata(const metadata::StatsMetadata& metadata,
int64_t currentWallClockTimeNs,
int64_t systemElapsedTimeNs);
private:
// For test only.
inline int64_t getTtlEndNs() const { return mTtlEndNs; }
const ConfigKey mConfigKey;
sp<UidMap> mUidMap;
bool mConfigValid = false;
bool mHashStringsInReport = false;
bool mVersionStringsInReport = false;
bool mInstallerInReport = false;
const int64_t mTtlNs;
int64_t mTtlEndNs;
int64_t mLastReportTimeNs;
int64_t mLastReportWallClockNs;
sp<StatsPullerManager> mPullerManager;
// The uid log sources from StatsdConfig.
std::vector<int32_t> mAllowedUid;
// The pkg log sources from StatsdConfig.
std::vector<std::string> mAllowedPkg;
// The combined uid sources (after translating pkg name to uid).
// Logs from uids that are not in the list will be ignored to avoid spamming.
std::set<int32_t> mAllowedLogSources;
// To guard access to mAllowedLogSources
mutable std::mutex mAllowedLogSourcesMutex;
const std::set<int32_t> mWhitelistedAtomIds;
// We can pull any atom from these uids.
std::set<int32_t> mDefaultPullUids;
// Uids that specific atoms can pull from.
// This is a map<atom id, set<uids>>
std::map<int32_t, std::set<int32_t>> mPullAtomUids;
// Packages that specific atoms can be pulled from.
std::map<int32_t, std::set<std::string>> mPullAtomPackages;
// All uids to pull for this atom. NOTE: Does not include the default uids for memory.
std::map<int32_t, std::set<int32_t>> mCombinedPullAtomUids;
// Contains the annotations passed in with StatsdConfig.
std::list<std::pair<const int64_t, const int32_t>> mAnnotations;
const bool mShouldPersistHistory;
// All event tags that are interesting to my metrics.
std::set<int> mTagIds;
// We only store the sp of LogMatchingTracker, MetricProducer, and ConditionTracker in
// MetricsManager. There are relationships between them, and the relationships are denoted by
// index instead of pointers. The reasons for this are: (1) the relationship between them are
// complicated, so storing index instead of pointers reduces the risk that A holds B's sp, and B
// holds A's sp. (2) When we evaluate matcher results, or condition results, we can quickly get
// the related results from a cache using the index.
// Hold all the atom matchers from the config.
std::vector<sp<LogMatchingTracker>> mAllAtomMatchers;
// Hold all the conditions from the config.
std::vector<sp<ConditionTracker>> mAllConditionTrackers;
// Hold all metrics from the config.
std::vector<sp<MetricProducer>> mAllMetricProducers;
// Hold all alert trackers.
std::vector<sp<AnomalyTracker>> mAllAnomalyTrackers;
// Hold all periodic alarm trackers.
std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers;
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.
// 1st filter: check if the event tag id is in mTagIds.
// 2nd filter: if it is, we parse the event because there is at least one member is interested.
// then pass to all LogMatchingTrackers (itself also filter events by ids).
// 3nd filter: for LogMatchingTrackers that matched this event, we pass this event to the
// ConditionTrackers and MetricProducers that use this matcher.
// 4th filter: for ConditionTrackers that changed value due to this event, we pass
// new conditions to metrics that use this condition.
// The following map is initialized from the statsd_config.
// Maps from the index of the LogMatchingTracker to index of MetricProducer.
std::unordered_map<int, std::vector<int>> mTrackerToMetricMap;
// Maps from LogMatchingTracker to ConditionTracker
std::unordered_map<int, std::vector<int>> mTrackerToConditionMap;
// Maps from ConditionTracker to MetricProducer
std::unordered_map<int, std::vector<int>> mConditionToMetricMap;
// 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;
// Maps AlertIds to the index of the corresponding AnomalyTracker stored in mAllAnomalyTrackers.
// The map is used in LoadMetadata to more efficiently lookup AnomalyTrackers from an AlertId.
std::unordered_map<int64_t, int> mAlertTrackerMap;
std::vector<int> mMetricIndexesWithActivation;
void initLogSourceWhiteList();
void initPullAtomSources();
// The metrics that don't need to be uploaded or even reported.
std::set<int64_t> mNoReportMetricIds;
// The config is active if any metric in the config is active.
bool mIsActive;
// The config is always active if any metric in the config does not have an activation signal.
bool mIsAlwaysActive;
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition);
FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents);
FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written);
FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk);
FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
FRIEND_TEST(MetricsManagerTest, TestLogSources);
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
FRIEND_TEST(StatsLogProcessorTest,
TestActivationOnBootMultipleActivationsDifferentActivationTypes);
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges);
FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields);
FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedState);
FRIEND_TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStateMapped);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSuperset);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
} // namespace os
} // namespace android
|