blob: 811a00e47ae5fcb0ce11a6911d05130439a9a1c8 [file] [log] [blame]
Yao Chencaf339d2017-10-06 16:01:10 -07001/*
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
Tej Singh484524a2018-02-01 15:10:05 -080017#define DEBUG false // STOPSHIP if true
Yao Chen10535b92017-11-27 11:31:55 -080018#include "Log.h"
19
Yangster-mac932ecec2018-02-01 10:23:52 -080020#include "metrics_manager_util.h"
21
Yao Chencaf339d2017-10-06 16:01:10 -070022#include "../condition/CombinationConditionTracker.h"
23#include "../condition/SimpleConditionTracker.h"
Yao Chen580ea3212018-02-26 14:21:54 -080024#include "../condition/StateTracker.h"
Chenjie Yub3dda412017-10-24 13:41:59 -070025#include "../external/StatsPullerManager.h"
Yao Chencaf339d2017-10-06 16:01:10 -070026#include "../matchers/CombinationLogMatchingTracker.h"
27#include "../matchers/SimpleLogMatchingTracker.h"
Yangster-mac932ecec2018-02-01 10:23:52 -080028#include "../metrics/CountMetricProducer.h"
29#include "../metrics/DurationMetricProducer.h"
30#include "../metrics/EventMetricProducer.h"
31#include "../metrics/GaugeMetricProducer.h"
32#include "../metrics/ValueMetricProducer.h"
33
Yao Chencaf339d2017-10-06 16:01:10 -070034#include "stats_util.h"
Yao Chen580ea3212018-02-26 14:21:54 -080035#include "statslog.h"
Yao Chencaf339d2017-10-06 16:01:10 -070036
37using std::set;
38using std::string;
39using std::unordered_map;
40using std::vector;
41
42namespace android {
43namespace os {
44namespace statsd {
45
Yao Chen8a8d16c2018-02-08 14:50:40 -080046namespace {
47
48bool hasLeafNode(const FieldMatcher& matcher) {
49 if (!matcher.has_field()) {
50 return false;
51 }
52 for (int i = 0; i < matcher.child_size(); ++i) {
53 if (hasLeafNode(matcher.child(i))) {
54 return true;
55 }
56 }
57 return true;
58}
59
60} // namespace
61
Yangster-mac94e197c2018-01-02 16:03:03 -080062bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
Yao Chen5154a372017-10-30 22:57:06 -070063 const bool usedForDimension,
Stefan Lafonb8c9aa82017-12-03 14:27:25 -080064 const vector<sp<LogMatchingTracker>>& allAtomMatchers,
Yangster-mac94e197c2018-01-02 16:03:03 -080065 const unordered_map<int64_t, int>& logTrackerMap,
Yao Chen5110bed2017-10-23 12:50:02 -070066 unordered_map<int, std::vector<int>>& trackerToMetricMap,
67 int& logTrackerIndex) {
68 auto logTrackerIt = logTrackerMap.find(what);
Yao Chen729093d2017-10-16 10:33:26 -070069 if (logTrackerIt == logTrackerMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080070 ALOGW("cannot find the AtomMatcher \"%lld\" in config", (long long)what);
Yao Chen5110bed2017-10-23 12:50:02 -070071 return false;
Yao Chen729093d2017-10-16 10:33:26 -070072 }
Yangster-mac20877162017-12-22 17:19:39 -080073 if (usedForDimension && allAtomMatchers[logTrackerIt->second]->getAtomIds().size() > 1) {
Yangster-mac94e197c2018-01-02 16:03:03 -080074 ALOGE("AtomMatcher \"%lld\" has more than one tag ids. When a metric has dimension, "
Stefan Lafon7c8f0a52017-11-21 14:49:09 -080075 "the \"what\" can only about one atom type.",
Yangster-mac94e197c2018-01-02 16:03:03 -080076 (long long)what);
Yao Chen5154a372017-10-30 22:57:06 -070077 return false;
78 }
Yao Chen5110bed2017-10-23 12:50:02 -070079 logTrackerIndex = logTrackerIt->second;
80 auto& metric_list = trackerToMetricMap[logTrackerIndex];
81 metric_list.push_back(metricIndex);
82 return true;
83}
84
85bool handleMetricWithConditions(
Yangster-mac94e197c2018-01-02 16:03:03 -080086 const int64_t condition, const int metricIndex,
87 const unordered_map<int64_t, int>& conditionTrackerMap,
Stefan Lafona5b51912017-12-05 21:43:52 -080088 const ::google::protobuf::RepeatedPtrField<::android::os::statsd::MetricConditionLink>&
Yao Chen5110bed2017-10-23 12:50:02 -070089 links,
90 vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
91 unordered_map<int, std::vector<int>>& conditionToMetricMap) {
92 auto condition_it = conditionTrackerMap.find(condition);
93 if (condition_it == conditionTrackerMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -080094 ALOGW("cannot find Predicate \"%lld\" in the config", (long long)condition);
Yao Chen5110bed2017-10-23 12:50:02 -070095 return false;
96 }
97
98 for (const auto& link : links) {
99 auto it = conditionTrackerMap.find(link.condition());
100 if (it == conditionTrackerMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800101 ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
Yao Chen5110bed2017-10-23 12:50:02 -0700102 return false;
103 }
104 allConditionTrackers[condition_it->second]->setSliced(true);
105 allConditionTrackers[it->second]->setSliced(true);
Yao Chen5154a372017-10-30 22:57:06 -0700106 // TODO: We need to verify the link is valid.
Yao Chen5110bed2017-10-23 12:50:02 -0700107 }
108 conditionIndex = condition_it->second;
109
110 // will create new vector if not exist before.
111 auto& metricList = conditionToMetricMap[condition_it->second];
112 metricList.push_back(metricIndex);
113 return true;
Yao Chen729093d2017-10-16 10:33:26 -0700114}
115
Yangster-mac20877162017-12-22 17:19:39 -0800116bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
Yangster-mac94e197c2018-01-02 16:03:03 -0800117 unordered_map<int64_t, int>& logTrackerMap,
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800118 vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
119 vector<AtomMatcher> matcherConfigs;
120 const int atomMatcherCount = config.atom_matcher_size();
121 matcherConfigs.reserve(atomMatcherCount);
122 allAtomMatchers.reserve(atomMatcherCount);
Yao Chencaf339d2017-10-06 16:01:10 -0700123
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800124 for (int i = 0; i < atomMatcherCount; i++) {
125 const AtomMatcher& logMatcher = config.atom_matcher(i);
Yao Chencaf339d2017-10-06 16:01:10 -0700126
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800127 int index = allAtomMatchers.size();
Yao Chencaf339d2017-10-06 16:01:10 -0700128 switch (logMatcher.contents_case()) {
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800129 case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
130 allAtomMatchers.push_back(new SimpleLogMatchingTracker(
Yangster-mac94e197c2018-01-02 16:03:03 -0800131 logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
Yao Chencaf339d2017-10-06 16:01:10 -0700132 break;
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800133 case AtomMatcher::ContentsCase::kCombination:
134 allAtomMatchers.push_back(
Yangster-mac94e197c2018-01-02 16:03:03 -0800135 new CombinationLogMatchingTracker(logMatcher.id(), index));
Yao Chencaf339d2017-10-06 16:01:10 -0700136 break;
137 default:
Yangster-mac94e197c2018-01-02 16:03:03 -0800138 ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
Yao Chencaf339d2017-10-06 16:01:10 -0700139 return false;
140 // continue;
141 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800142 if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800143 ALOGE("Duplicate AtomMatcher found!");
Yao Chencaf339d2017-10-06 16:01:10 -0700144 return false;
145 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800146 logTrackerMap[logMatcher.id()] = index;
Yao Chencaf339d2017-10-06 16:01:10 -0700147 matcherConfigs.push_back(logMatcher);
148 }
149
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800150 vector<bool> stackTracker2(allAtomMatchers.size(), false);
151 for (auto& matcher : allAtomMatchers) {
152 if (!matcher->init(matcherConfigs, allAtomMatchers, logTrackerMap, stackTracker2)) {
Yao Chencaf339d2017-10-06 16:01:10 -0700153 return false;
154 }
155 // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
Yangster-mac20877162017-12-22 17:19:39 -0800156 const set<int>& tagIds = matcher->getAtomIds();
Yao Chencaf339d2017-10-06 16:01:10 -0700157 allTagIds.insert(tagIds.begin(), tagIds.end());
158 }
159 return true;
160}
161
Yao Chen580ea3212018-02-26 14:21:54 -0800162/**
163 * A StateTracker is built from a SimplePredicate which has only "start", and no "stop"
164 * or "stop_all". The start must be an atom matcher that matches a state atom. It must
165 * have dimension, the dimension must be the state atom's primary fields plus exclusive state
166 * field. For example, the StateTracker is used in tracking UidProcessState and ScreenState.
167 *
168 */
169bool isStateTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) {
170 // 1. must not have "stop". must have "dimension"
171 if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) {
172 // TODO: need to check the start atom matcher too.
Yao Chenc40a19d2018-03-15 16:48:25 -0700173 auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(
174 simplePredicate.dimensions().field());
Yao Chen580ea3212018-02-26 14:21:54 -0800175 // 2. must be based on a state atom.
Yao Chenc40a19d2018-03-15 16:48:25 -0700176 if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
Yao Chen580ea3212018-02-26 14:21:54 -0800177 // 3. dimension must be primary fields + state field IN ORDER
178 size_t expectedDimensionCount = it->second.primaryFields.size() + 1;
179 vector<Matcher> dimensions;
180 translateFieldMatcher(simplePredicate.dimensions(), &dimensions);
181 if (dimensions.size() != expectedDimensionCount) {
182 return false;
183 }
184 // 3.1 check the primary fields first.
185 size_t index = 0;
186 for (const auto& field : it->second.primaryFields) {
187 Matcher matcher = getSimpleMatcher(it->first, field);
188 if (!(matcher == dimensions[index])) {
189 return false;
190 }
191 primaryKeys->push_back(matcher);
192 index++;
193 }
194 Matcher stateFieldMatcher =
195 getSimpleMatcher(it->first, it->second.exclusiveField);
196 // 3.2 last dimension should be the exclusive field.
197 if (!(dimensions.back() == stateFieldMatcher)) {
198 return false;
199 }
200 return true;
201 }
202 }
203 return false;
204} // namespace statsd
205
Yao Chenb3561512017-11-21 18:07:17 -0800206bool initConditions(const ConfigKey& key, const StatsdConfig& config,
Yangster-mac94e197c2018-01-02 16:03:03 -0800207 const unordered_map<int64_t, int>& logTrackerMap,
208 unordered_map<int64_t, int>& conditionTrackerMap,
Yao Chencaf339d2017-10-06 16:01:10 -0700209 vector<sp<ConditionTracker>>& allConditionTrackers,
210 unordered_map<int, std::vector<int>>& trackerToConditionMap) {
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800211 vector<Predicate> conditionConfigs;
212 const int conditionTrackerCount = config.predicate_size();
Yao Chen729093d2017-10-16 10:33:26 -0700213 conditionConfigs.reserve(conditionTrackerCount);
214 allConditionTrackers.reserve(conditionTrackerCount);
Yao Chencaf339d2017-10-06 16:01:10 -0700215
Yao Chen729093d2017-10-16 10:33:26 -0700216 for (int i = 0; i < conditionTrackerCount; i++) {
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800217 const Predicate& condition = config.predicate(i);
Yao Chencaf339d2017-10-06 16:01:10 -0700218 int index = allConditionTrackers.size();
219 switch (condition.contents_case()) {
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800220 case Predicate::ContentsCase::kSimplePredicate: {
Yao Chen580ea3212018-02-26 14:21:54 -0800221 vector<Matcher> primaryKeys;
222 if (isStateTracker(condition.simple_predicate(), &primaryKeys)) {
223 allConditionTrackers.push_back(new StateTracker(key, condition.id(), index,
224 condition.simple_predicate(),
225 logTrackerMap, primaryKeys));
226 } else {
227 allConditionTrackers.push_back(new SimpleConditionTracker(
228 key, condition.id(), index, condition.simple_predicate(),
229 logTrackerMap));
230 }
Yao Chencaf339d2017-10-06 16:01:10 -0700231 break;
232 }
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800233 case Predicate::ContentsCase::kCombination: {
Yao Chencaf339d2017-10-06 16:01:10 -0700234 allConditionTrackers.push_back(
Yangster-mac94e197c2018-01-02 16:03:03 -0800235 new CombinationConditionTracker(condition.id(), index));
Yao Chencaf339d2017-10-06 16:01:10 -0700236 break;
237 }
238 default:
Yangster-mac94e197c2018-01-02 16:03:03 -0800239 ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
Yao Chencaf339d2017-10-06 16:01:10 -0700240 return false;
241 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800242 if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800243 ALOGE("Duplicate Predicate found!");
Yao Chencaf339d2017-10-06 16:01:10 -0700244 return false;
245 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800246 conditionTrackerMap[condition.id()] = index;
Yao Chencaf339d2017-10-06 16:01:10 -0700247 conditionConfigs.push_back(condition);
248 }
249
250 vector<bool> stackTracker(allConditionTrackers.size(), false);
251 for (size_t i = 0; i < allConditionTrackers.size(); i++) {
252 auto& conditionTracker = allConditionTrackers[i];
253 if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
254 stackTracker)) {
255 return false;
256 }
257 for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) {
258 auto& conditionList = trackerToConditionMap[trackerIndex];
259 conditionList.push_back(i);
260 }
261 }
262 return true;
263}
264
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700265bool initMetrics(const ConfigKey& key, const StatsdConfig& config,
266 const int64_t timeBaseTimeNs, const int64_t currentTimeNs,
David Chenbd125272018-04-04 19:02:50 -0700267 UidMap& uidMap, const unordered_map<int64_t, int>& logTrackerMap,
Yangster-mac94e197c2018-01-02 16:03:03 -0800268 const unordered_map<int64_t, int>& conditionTrackerMap,
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800269 const vector<sp<LogMatchingTracker>>& allAtomMatchers,
Yao Chen729093d2017-10-16 10:33:26 -0700270 vector<sp<ConditionTracker>>& allConditionTrackers,
Yao Chencaf339d2017-10-06 16:01:10 -0700271 vector<sp<MetricProducer>>& allMetricProducers,
272 unordered_map<int, std::vector<int>>& conditionToMetricMap,
Yangster-mace2cd6d52017-11-09 20:38:30 -0800273 unordered_map<int, std::vector<int>>& trackerToMetricMap,
David Chenbd125272018-04-04 19:02:50 -0700274 unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
Yao Chen729093d2017-10-16 10:33:26 -0700275 sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
Yao Chen93fe3a32017-11-02 13:52:59 -0700276 const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
277 config.event_metric_size() + config.value_metric_size();
Yao Chen729093d2017-10-16 10:33:26 -0700278 allMetricProducers.reserve(allMetricsCount);
Chenjie Yu6736c892017-11-09 10:50:09 -0800279 StatsPullerManager statsPullerManager;
Yangster-mac20877162017-12-22 17:19:39 -0800280
Yao Chencaf339d2017-10-06 16:01:10 -0700281 // Build MetricProducers for each metric defined in config.
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700282 // build CountMetricProducer
Yao Chencaf339d2017-10-06 16:01:10 -0700283 for (int i = 0; i < config.count_metric_size(); i++) {
284 const CountMetric& metric = config.count_metric(i);
285 if (!metric.has_what()) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800286 ALOGW("cannot find \"what\" in CountMetric \"%lld\"", (long long)metric.id());
Yao Chencaf339d2017-10-06 16:01:10 -0700287 return false;
288 }
289
Yao Chen729093d2017-10-16 10:33:26 -0700290 int metricIndex = allMetricProducers.size();
Yangster-mac94e197c2018-01-02 16:03:03 -0800291 metricMap.insert({metric.id(), metricIndex});
Yao Chen5110bed2017-10-23 12:50:02 -0700292 int trackerIndex;
Yangster-mac468ff042018-01-17 12:26:34 -0800293 if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
294 metric.has_dimensions_in_what(),
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800295 allAtomMatchers, logTrackerMap, trackerToMetricMap,
Yao Chen5154a372017-10-30 22:57:06 -0700296 trackerIndex)) {
Yao Chencaf339d2017-10-06 16:01:10 -0700297 return false;
298 }
299
Yao Chen5110bed2017-10-23 12:50:02 -0700300 int conditionIndex = -1;
Yao Chencaf339d2017-10-06 16:01:10 -0700301 if (metric.has_condition()) {
Yao Chen10535b92017-11-27 11:31:55 -0800302 bool good = handleMetricWithConditions(
303 metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
304 allConditionTrackers, conditionIndex, conditionToMetricMap);
305 if (!good) {
306 return false;
307 }
Yao Chen5c925ad2017-11-15 14:15:46 -0800308 } else {
309 if (metric.links_size() > 0) {
Stefan Lafona5b51912017-12-05 21:43:52 -0800310 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
Yao Chen5c925ad2017-11-15 14:15:46 -0800311 return false;
312 }
Yao Chencaf339d2017-10-06 16:01:10 -0700313 }
Yao Chen5110bed2017-10-23 12:50:02 -0700314
Yao Chen93fe3a32017-11-02 13:52:59 -0700315 sp<MetricProducer> countProducer =
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700316 new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
Yao Chencaf339d2017-10-06 16:01:10 -0700317 allMetricProducers.push_back(countProducer);
318 }
319
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700320 // build DurationMetricProducer
Yao Chen729093d2017-10-16 10:33:26 -0700321 for (int i = 0; i < config.duration_metric_size(); i++) {
322 int metricIndex = allMetricProducers.size();
Yao Chen5110bed2017-10-23 12:50:02 -0700323 const DurationMetric& metric = config.duration_metric(i);
Yangster-mac94e197c2018-01-02 16:03:03 -0800324 metricMap.insert({metric.id(), metricIndex});
Yao Chen5154a372017-10-30 22:57:06 -0700325
326 auto what_it = conditionTrackerMap.find(metric.what());
327 if (what_it == conditionTrackerMap.end()) {
328 ALOGE("DurationMetric's \"what\" is invalid");
329 return false;
330 }
331
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800332 const Predicate& durationWhat = config.predicate(what_it->second);
Yao Chen5154a372017-10-30 22:57:06 -0700333
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800334 if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
Yao Chen5154a372017-10-30 22:57:06 -0700335 ALOGE("DurationMetric's \"what\" must be a simple condition");
336 return false;
337 }
338
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800339 const auto& simplePredicate = durationWhat.simple_predicate();
Yao Chen5154a372017-10-30 22:57:06 -0700340
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800341 bool nesting = simplePredicate.count_nesting();
Yao Chen0ea19902017-11-15 15:44:45 -0800342
Yao Chen5110bed2017-10-23 12:50:02 -0700343 int trackerIndices[3] = {-1, -1, -1};
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800344 if (!simplePredicate.has_start() ||
345 !handleMetricWithLogTrackers(simplePredicate.start(), metricIndex,
Yangster-mac468ff042018-01-17 12:26:34 -0800346 metric.has_dimensions_in_what(), allAtomMatchers,
Yao Chen5154a372017-10-30 22:57:06 -0700347 logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
Yao Chen5110bed2017-10-23 12:50:02 -0700348 ALOGE("Duration metrics must specify a valid the start event matcher");
Yao Chen729093d2017-10-16 10:33:26 -0700349 return false;
350 }
Yao Chencaf339d2017-10-06 16:01:10 -0700351
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800352 if (simplePredicate.has_stop() &&
353 !handleMetricWithLogTrackers(simplePredicate.stop(), metricIndex,
Yangster-mac468ff042018-01-17 12:26:34 -0800354 metric.has_dimensions_in_what(), allAtomMatchers,
Yao Chen5154a372017-10-30 22:57:06 -0700355 logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
Yao Chen5110bed2017-10-23 12:50:02 -0700356 return false;
Yao Chen729093d2017-10-16 10:33:26 -0700357 }
358
Stefan Lafon12d01fa2017-12-04 20:56:09 -0800359 if (simplePredicate.has_stop_all() &&
360 !handleMetricWithLogTrackers(simplePredicate.stop_all(), metricIndex,
Yangster-mac468ff042018-01-17 12:26:34 -0800361 metric.has_dimensions_in_what(), allAtomMatchers,
Yao Chen5154a372017-10-30 22:57:06 -0700362 logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
Yao Chen5110bed2017-10-23 12:50:02 -0700363 return false;
Yao Chen729093d2017-10-16 10:33:26 -0700364 }
365
Yangster-mac20877162017-12-22 17:19:39 -0800366 FieldMatcher internalDimensions = simplePredicate.dimensions();
Yao Chen5154a372017-10-30 22:57:06 -0700367
Yao Chen729093d2017-10-16 10:33:26 -0700368 int conditionIndex = -1;
369
Yao Chen5c925ad2017-11-15 14:15:46 -0800370 if (metric.has_condition()) {
Yao Chen10535b92017-11-27 11:31:55 -0800371 bool good = handleMetricWithConditions(
372 metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
373 allConditionTrackers, conditionIndex, conditionToMetricMap);
374 if (!good) {
375 return false;
376 }
Yao Chen5c925ad2017-11-15 14:15:46 -0800377 } else {
378 if (metric.links_size() > 0) {
Stefan Lafona5b51912017-12-05 21:43:52 -0800379 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
Yao Chen5c925ad2017-11-15 14:15:46 -0800380 return false;
381 }
Yao Chen729093d2017-10-16 10:33:26 -0700382 }
383
Yao Chen5154a372017-10-30 22:57:06 -0700384 sp<MetricProducer> durationMetric = new DurationMetricProducer(
Yao Chenb3561512017-11-21 18:07:17 -0800385 key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700386 trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs);
Yao Chen729093d2017-10-16 10:33:26 -0700387
388 allMetricProducers.push_back(durationMetric);
389 }
Yao Chen5110bed2017-10-23 12:50:02 -0700390
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700391 // build EventMetricProducer
Yao Chen5110bed2017-10-23 12:50:02 -0700392 for (int i = 0; i < config.event_metric_size(); i++) {
393 int metricIndex = allMetricProducers.size();
394 const EventMetric& metric = config.event_metric(i);
Yangster-mac94e197c2018-01-02 16:03:03 -0800395 metricMap.insert({metric.id(), metricIndex});
396 if (!metric.has_id() || !metric.has_what()) {
Yangster-macd1815dc2017-11-13 21:43:15 -0800397 ALOGW("cannot find the metric name or what in config");
Yao Chen5110bed2017-10-23 12:50:02 -0700398 return false;
399 }
400 int trackerIndex;
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800401 if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allAtomMatchers,
Yao Chen5154a372017-10-30 22:57:06 -0700402 logTrackerMap, trackerToMetricMap, trackerIndex)) {
Yao Chen5110bed2017-10-23 12:50:02 -0700403 return false;
404 }
405
406 int conditionIndex = -1;
407 if (metric.has_condition()) {
Yao Chen10535b92017-11-27 11:31:55 -0800408 bool good = handleMetricWithConditions(
409 metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
410 allConditionTrackers, conditionIndex, conditionToMetricMap);
411 if (!good) {
412 return false;
413 }
Yao Chen5c925ad2017-11-15 14:15:46 -0800414 } else {
415 if (metric.links_size() > 0) {
Stefan Lafona5b51912017-12-05 21:43:52 -0800416 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
Yao Chen5c925ad2017-11-15 14:15:46 -0800417 return false;
418 }
Yao Chen5110bed2017-10-23 12:50:02 -0700419 }
420
Yao Chen93fe3a32017-11-02 13:52:59 -0700421 sp<MetricProducer> eventMetric =
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700422 new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
Yao Chen93fe3a32017-11-02 13:52:59 -0700423
Yao Chen5110bed2017-10-23 12:50:02 -0700424 allMetricProducers.push_back(eventMetric);
425 }
426
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700427 // build ValueMetricProducer
Chenjie Yub3dda412017-10-24 13:41:59 -0700428 for (int i = 0; i < config.value_metric_size(); i++) {
429 const ValueMetric& metric = config.value_metric(i);
430 if (!metric.has_what()) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800431 ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
Chenjie Yub3dda412017-10-24 13:41:59 -0700432 return false;
433 }
434
Chenjie Yub3dda412017-10-24 13:41:59 -0700435 int metricIndex = allMetricProducers.size();
Yangster-mac94e197c2018-01-02 16:03:03 -0800436 metricMap.insert({metric.id(), metricIndex});
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700437 int trackerIndex;
Yangster-mac468ff042018-01-17 12:26:34 -0800438 if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
439 metric.has_dimensions_in_what(),
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800440 allAtomMatchers, logTrackerMap, trackerToMetricMap,
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700441 trackerIndex)) {
442 return false;
443 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700444
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800445 sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700446 // If it is pulled atom, it should be simple matcher with one tagId.
Yangster-mac20877162017-12-22 17:19:39 -0800447 if (atomMatcher->getAtomIds().size() != 1) {
Chenjie Yud9dfda72017-12-11 17:41:20 -0800448 return false;
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700449 }
Yangster-mac20877162017-12-22 17:19:39 -0800450 int atomTagId = *(atomMatcher->getAtomIds().begin());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800451 int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700452
453 int conditionIndex = -1;
454 if (metric.has_condition()) {
Yao Chen10535b92017-11-27 11:31:55 -0800455 bool good = handleMetricWithConditions(
456 metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
457 allConditionTrackers, conditionIndex, conditionToMetricMap);
458 if (!good) {
459 return false;
460 }
Yao Chen5c925ad2017-11-15 14:15:46 -0800461 } else {
462 if (metric.links_size() > 0) {
Stefan Lafona5b51912017-12-05 21:43:52 -0800463 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
Yao Chen5c925ad2017-11-15 14:15:46 -0800464 return false;
465 }
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700466 }
467
Yao Chenb3561512017-11-21 18:07:17 -0800468 sp<MetricProducer> valueProducer = new ValueMetricProducer(key, metric, conditionIndex,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700469 wizard, pullTagId,
470 timeBaseTimeNs, currentTimeNs);
Chenjie Yub3dda412017-10-24 13:41:59 -0700471 allMetricProducers.push_back(valueProducer);
472 }
Yangster1d4d6862017-10-31 12:58:51 -0700473
474 // Gauge metrics.
475 for (int i = 0; i < config.gauge_metric_size(); i++) {
476 const GaugeMetric& metric = config.gauge_metric(i);
477 if (!metric.has_what()) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800478 ALOGW("cannot find \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800479 return false;
480 }
481
Yangster-mac20877162017-12-22 17:19:39 -0800482 if ((!metric.gauge_fields_filter().has_include_all() ||
483 (metric.gauge_fields_filter().include_all() == false)) &&
484 !hasLeafNode(metric.gauge_fields_filter().fields())) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800485 ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
Chenjie Yu2b4fc9d2017-12-18 15:20:00 -0800486 return false;
487 }
Yangster-mac20877162017-12-22 17:19:39 -0800488 if ((metric.gauge_fields_filter().has_include_all() &&
489 metric.gauge_fields_filter().include_all() == true) &&
490 hasLeafNode(metric.gauge_fields_filter().fields())) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800491 ALOGW("Incorrect field filter setting in GaugeMetric %lld", (long long)metric.id());
Yangster1d4d6862017-10-31 12:58:51 -0700492 return false;
493 }
494
495 int metricIndex = allMetricProducers.size();
Yangster-mac94e197c2018-01-02 16:03:03 -0800496 metricMap.insert({metric.id(), metricIndex});
Yangster1d4d6862017-10-31 12:58:51 -0700497 int trackerIndex;
Yangster-mac468ff042018-01-17 12:26:34 -0800498 if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
499 metric.has_dimensions_in_what(),
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800500 allAtomMatchers, logTrackerMap, trackerToMetricMap,
Yangster1d4d6862017-10-31 12:58:51 -0700501 trackerIndex)) {
502 return false;
503 }
504
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800505 sp<LogMatchingTracker> atomMatcher = allAtomMatchers.at(trackerIndex);
Yangster1d4d6862017-10-31 12:58:51 -0700506 // If it is pulled atom, it should be simple matcher with one tagId.
Yangster-mac20877162017-12-22 17:19:39 -0800507 if (atomMatcher->getAtomIds().size() != 1) {
Chenjie Yud9dfda72017-12-11 17:41:20 -0800508 return false;
Yangster1d4d6862017-10-31 12:58:51 -0700509 }
Yangster-mac20877162017-12-22 17:19:39 -0800510 int atomTagId = *(atomMatcher->getAtomIds().begin());
Chenjie Yud9dfda72017-12-11 17:41:20 -0800511 int pullTagId = statsPullerManager.PullerForMatcherExists(atomTagId) ? atomTagId : -1;
Yangster1d4d6862017-10-31 12:58:51 -0700512
513 int conditionIndex = -1;
514 if (metric.has_condition()) {
Yao Chen10535b92017-11-27 11:31:55 -0800515 bool good = handleMetricWithConditions(
516 metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
517 allConditionTrackers, conditionIndex, conditionToMetricMap);
518 if (!good) {
519 return false;
520 }
Yao Chen5c925ad2017-11-15 14:15:46 -0800521 } else {
522 if (metric.links_size() > 0) {
Stefan Lafona5b51912017-12-05 21:43:52 -0800523 ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
Yao Chen5c925ad2017-11-15 14:15:46 -0800524 return false;
525 }
Yangster1d4d6862017-10-31 12:58:51 -0700526 }
527
Chenjie Yud9dfda72017-12-11 17:41:20 -0800528 sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700529 key, metric, conditionIndex, wizard, pullTagId, timeBaseTimeNs, currentTimeNs);
Yangster1d4d6862017-10-31 12:58:51 -0700530 allMetricProducers.push_back(gaugeProducer);
531 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800532 for (int i = 0; i < config.no_report_metric_size(); ++i) {
533 const auto no_report_metric = config.no_report_metric(i);
534 if (metricMap.find(no_report_metric) == metricMap.end()) {
Colin Cross054b0c02018-11-04 17:24:17 -0800535 ALOGW("no_report_metric %lld not exist", no_report_metric);
Yangster-mac94e197c2018-01-02 16:03:03 -0800536 return false;
537 }
538 noReportMetricIds.insert(no_report_metric);
539 }
David Chenbd125272018-04-04 19:02:50 -0700540 for (auto it : allMetricProducers) {
541 uidMap.addListener(it);
542 }
Yao Chencaf339d2017-10-06 16:01:10 -0700543 return true;
544}
545
Yangster-mac20877162017-12-22 17:19:39 -0800546bool initAlerts(const StatsdConfig& config,
Yangster-mac94e197c2018-01-02 16:03:03 -0800547 const unordered_map<int64_t, int>& metricProducerMap,
Yangster-mac932ecec2018-02-01 10:23:52 -0800548 const sp<AlarmMonitor>& anomalyAlarmMonitor,
Yangster-mace2cd6d52017-11-09 20:38:30 -0800549 vector<sp<MetricProducer>>& allMetricProducers,
550 vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800551 unordered_map<int64_t, int> anomalyTrackerMap;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800552 for (int i = 0; i < config.alert_size(); i++) {
553 const Alert& alert = config.alert(i);
Yangster-mac94e197c2018-01-02 16:03:03 -0800554 const auto& itr = metricProducerMap.find(alert.metric_id());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800555 if (itr == metricProducerMap.end()) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800556 ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
557 (long long)alert.metric_id());
Yangster-mace2cd6d52017-11-09 20:38:30 -0800558 return false;
559 }
Bookatz6bf98252018-03-14 10:44:24 -0700560 if (!alert.has_trigger_if_sum_gt()) {
561 ALOGW("invalid alert: missing threshold");
562 return false;
563 }
Yangster-maca7fb12d2018-01-03 17:17:20 -0800564 if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
565 ALOGW("invalid alert: threshold=%f num_buckets= %d",
566 alert.trigger_if_sum_gt(), alert.num_buckets());
Bookatzcc5adef2017-11-21 14:36:23 -0800567 return false;
568 }
Yangster-mace2cd6d52017-11-09 20:38:30 -0800569 const int metricIndex = itr->second;
Bookatz450099d2017-11-30 17:09:30 -0800570 sp<MetricProducer> metric = allMetricProducers[metricIndex];
Yangster-mac932ecec2018-02-01 10:23:52 -0800571 sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
Bookatz1476ef22018-02-13 12:26:01 -0800572 if (anomalyTracker == nullptr) {
573 // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
574 return false;
Bookatzcc5adef2017-11-21 14:36:23 -0800575 }
Bookatz1476ef22018-02-13 12:26:01 -0800576 anomalyTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
577 allAnomalyTrackers.push_back(anomalyTracker);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800578 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800579 for (int i = 0; i < config.subscription_size(); ++i) {
580 const Subscription& subscription = config.subscription(i);
Yangster-mac932ecec2018-02-01 10:23:52 -0800581 if (subscription.rule_type() != Subscription::ALERT) {
582 continue;
583 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800584 if (subscription.subscriber_information_case() ==
585 Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
586 ALOGW("subscription \"%lld\" has no subscriber info.\"",
587 (long long)subscription.id());
588 return false;
589 }
590 const auto& itr = anomalyTrackerMap.find(subscription.rule_id());
591 if (itr == anomalyTrackerMap.end()) {
592 ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
593 (long long)subscription.id(), (long long)subscription.rule_id());
594 return false;
595 }
596 const int anomalyTrackerIndex = itr->second;
597 allAnomalyTrackers[anomalyTrackerIndex]->addSubscription(subscription);
598 }
Yangster-mace2cd6d52017-11-09 20:38:30 -0800599 return true;
600}
601
Yangster-mac932ecec2018-02-01 10:23:52 -0800602bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
603 const sp<AlarmMonitor>& periodicAlarmMonitor,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700604 const int64_t timeBaseNs, const int64_t currentTimeNs,
Yangster-mac932ecec2018-02-01 10:23:52 -0800605 vector<sp<AlarmTracker>>& allAlarmTrackers) {
606 unordered_map<int64_t, int> alarmTrackerMap;
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700607 int64_t startMillis = timeBaseNs / 1000 / 1000;
608 int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
Yangster-mac932ecec2018-02-01 10:23:52 -0800609 for (int i = 0; i < config.alarm_size(); i++) {
610 const Alarm& alarm = config.alarm(i);
611 if (alarm.offset_millis() <= 0) {
612 ALOGW("Alarm offset_millis should be larger than 0.");
613 return false;
614 }
615 if (alarm.period_millis() <= 0) {
616 ALOGW("Alarm period_millis should be larger than 0.");
617 return false;
618 }
619 alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
620 allAlarmTrackers.push_back(
Yangster-macc04feba2018-04-02 14:37:33 -0700621 new AlarmTracker(startMillis, currentTimeMillis,
622 alarm, key, periodicAlarmMonitor));
Yangster-mac932ecec2018-02-01 10:23:52 -0800623 }
624 for (int i = 0; i < config.subscription_size(); ++i) {
625 const Subscription& subscription = config.subscription(i);
626 if (subscription.rule_type() != Subscription::ALARM) {
627 continue;
628 }
629 if (subscription.subscriber_information_case() ==
630 Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
631 ALOGW("subscription \"%lld\" has no subscriber info.\"",
632 (long long)subscription.id());
633 return false;
634 }
635 const auto& itr = alarmTrackerMap.find(subscription.rule_id());
636 if (itr == alarmTrackerMap.end()) {
637 ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
638 (long long)subscription.id(), (long long)subscription.rule_id());
639 return false;
640 }
641 const int trackerIndex = itr->second;
642 allAlarmTrackers[trackerIndex]->addSubscription(subscription);
643 }
644 return true;
645}
646
David Chenbd125272018-04-04 19:02:50 -0700647bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
Yangster-mac932ecec2018-02-01 10:23:52 -0800648 const sp<AlarmMonitor>& anomalyAlarmMonitor,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700649 const sp<AlarmMonitor>& periodicAlarmMonitor,
650 const int64_t timeBaseNs, const int64_t currentTimeNs,
651 set<int>& allTagIds,
Stefan Lafonb8c9aa82017-12-03 14:27:25 -0800652 vector<sp<LogMatchingTracker>>& allAtomMatchers,
Yao Chencaf339d2017-10-06 16:01:10 -0700653 vector<sp<ConditionTracker>>& allConditionTrackers,
654 vector<sp<MetricProducer>>& allMetricProducers,
Yangster-mace2cd6d52017-11-09 20:38:30 -0800655 vector<sp<AnomalyTracker>>& allAnomalyTrackers,
Yangster-mac932ecec2018-02-01 10:23:52 -0800656 vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
Yao Chencaf339d2017-10-06 16:01:10 -0700657 unordered_map<int, std::vector<int>>& conditionToMetricMap,
658 unordered_map<int, std::vector<int>>& trackerToMetricMap,
Yangster-mac94e197c2018-01-02 16:03:03 -0800659 unordered_map<int, std::vector<int>>& trackerToConditionMap,
David Chenbd125272018-04-04 19:02:50 -0700660 std::set<int64_t>& noReportMetricIds) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800661 unordered_map<int64_t, int> logTrackerMap;
662 unordered_map<int64_t, int> conditionTrackerMap;
663 unordered_map<int64_t, int> metricProducerMap;
Yao Chencaf339d2017-10-06 16:01:10 -0700664
Yangster-mac20877162017-12-22 17:19:39 -0800665 if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) {
Yao Chencaf339d2017-10-06 16:01:10 -0700666 ALOGE("initLogMatchingTrackers failed");
667 return false;
668 }
Tej Singh484524a2018-02-01 15:10:05 -0800669 VLOG("initLogMatchingTrackers succeed...");
Yao Chencaf339d2017-10-06 16:01:10 -0700670
Yao Chenb3561512017-11-21 18:07:17 -0800671 if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
Yao Chencaf339d2017-10-06 16:01:10 -0700672 trackerToConditionMap)) {
673 ALOGE("initConditionTrackers failed");
674 return false;
675 }
676
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700677 if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap,
678 logTrackerMap, conditionTrackerMap,
David Chenbd125272018-04-04 19:02:50 -0700679 allAtomMatchers, allConditionTrackers, allMetricProducers,
680 conditionToMetricMap, trackerToMetricMap, metricProducerMap,
681 noReportMetricIds)) {
Yao Chencaf339d2017-10-06 16:01:10 -0700682 ALOGE("initMetricProducers failed");
683 return false;
684 }
Yangster-mac932ecec2018-02-01 10:23:52 -0800685 if (!initAlerts(config, metricProducerMap, anomalyAlarmMonitor, allMetricProducers,
686 allAnomalyTrackers)) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800687 ALOGE("initAlerts failed");
688 return false;
689 }
Yangster-macc04feba2018-04-02 14:37:33 -0700690 if (!initAlarms(config, key, periodicAlarmMonitor,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700691 timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800692 ALOGE("initAlarms failed");
693 return false;
694 }
695
Yao Chencaf339d2017-10-06 16:01:10 -0700696 return true;
697}
698
699} // namespace statsd
700} // namespace os
701} // namespace android