blob: 226e4d13afb21b2dc0e92fc9313fbade2608a006 [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
17#include "../condition/CombinationConditionTracker.h"
18#include "../condition/SimpleConditionTracker.h"
Chenjie Yub3dda412017-10-24 13:41:59 -070019#include "../external/StatsPullerManager.h"
Yao Chencaf339d2017-10-06 16:01:10 -070020#include "../matchers/CombinationLogMatchingTracker.h"
21#include "../matchers/SimpleLogMatchingTracker.h"
22#include "CountMetricProducer.h"
Yao Chen729093d2017-10-16 10:33:26 -070023#include "DurationMetricProducer.h"
Yao Chen5110bed2017-10-23 12:50:02 -070024#include "EventMetricProducer.h"
Yangster1d4d6862017-10-31 12:58:51 -070025#include "GaugeMetricProducer.h"
Chenjie Yub3dda412017-10-24 13:41:59 -070026#include "ValueMetricProducer.h"
Yao Chencaf339d2017-10-06 16:01:10 -070027#include "stats_util.h"
28
29using std::set;
30using std::string;
31using std::unordered_map;
32using std::vector;
33
34namespace android {
35namespace os {
36namespace statsd {
37
Yao Chen5110bed2017-10-23 12:50:02 -070038bool handleMetricWithLogTrackers(const string what, const int metricIndex,
Yao Chen5154a372017-10-30 22:57:06 -070039 const bool usedForDimension,
40 const vector<sp<LogMatchingTracker>>& allLogEntryMatchers,
Yao Chen5110bed2017-10-23 12:50:02 -070041 const unordered_map<string, int>& logTrackerMap,
42 unordered_map<int, std::vector<int>>& trackerToMetricMap,
43 int& logTrackerIndex) {
44 auto logTrackerIt = logTrackerMap.find(what);
Yao Chen729093d2017-10-16 10:33:26 -070045 if (logTrackerIt == logTrackerMap.end()) {
Yao Chen5110bed2017-10-23 12:50:02 -070046 ALOGW("cannot find the LogEntryMatcher %s in config", what.c_str());
47 return false;
Yao Chen729093d2017-10-16 10:33:26 -070048 }
Yao Chen5154a372017-10-30 22:57:06 -070049 if (usedForDimension && allLogEntryMatchers[logTrackerIt->second]->getTagIds().size() > 1) {
50 ALOGE("LogEntryMatcher %s has more than one tag ids. When a metric has dimension, the "
51 "\"what\" can only about one atom type.",
52 what.c_str());
53 return false;
54 }
Yao Chen5110bed2017-10-23 12:50:02 -070055 logTrackerIndex = logTrackerIt->second;
56 auto& metric_list = trackerToMetricMap[logTrackerIndex];
57 metric_list.push_back(metricIndex);
58 return true;
59}
60
61bool handleMetricWithConditions(
62 const string condition, const int metricIndex,
63 const unordered_map<string, int>& conditionTrackerMap,
64 const ::google::protobuf::RepeatedPtrField<::android::os::statsd::EventConditionLink>&
65 links,
66 vector<sp<ConditionTracker>>& allConditionTrackers, int& conditionIndex,
67 unordered_map<int, std::vector<int>>& conditionToMetricMap) {
68 auto condition_it = conditionTrackerMap.find(condition);
69 if (condition_it == conditionTrackerMap.end()) {
70 ALOGW("cannot find the Condition %s in the config", condition.c_str());
71 return false;
72 }
73
74 for (const auto& link : links) {
75 auto it = conditionTrackerMap.find(link.condition());
76 if (it == conditionTrackerMap.end()) {
77 ALOGW("cannot find the Condition %s in the config", link.condition().c_str());
78 return false;
79 }
80 allConditionTrackers[condition_it->second]->setSliced(true);
81 allConditionTrackers[it->second]->setSliced(true);
Yao Chen5154a372017-10-30 22:57:06 -070082 // TODO: We need to verify the link is valid.
Yao Chen5110bed2017-10-23 12:50:02 -070083 }
84 conditionIndex = condition_it->second;
85
86 // will create new vector if not exist before.
87 auto& metricList = conditionToMetricMap[condition_it->second];
88 metricList.push_back(metricIndex);
89 return true;
Yao Chen729093d2017-10-16 10:33:26 -070090}
91
Yao Chencaf339d2017-10-06 16:01:10 -070092bool initLogTrackers(const StatsdConfig& config, unordered_map<string, int>& logTrackerMap,
93 vector<sp<LogMatchingTracker>>& allLogEntryMatchers, set<int>& allTagIds) {
94 vector<LogEntryMatcher> matcherConfigs;
Yao Chen729093d2017-10-16 10:33:26 -070095 const int logEntryMatcherCount = config.log_entry_matcher_size();
96 matcherConfigs.reserve(logEntryMatcherCount);
97 allLogEntryMatchers.reserve(logEntryMatcherCount);
Yao Chencaf339d2017-10-06 16:01:10 -070098
Yao Chen729093d2017-10-16 10:33:26 -070099 for (int i = 0; i < logEntryMatcherCount; i++) {
Yao Chencaf339d2017-10-06 16:01:10 -0700100 const LogEntryMatcher& logMatcher = config.log_entry_matcher(i);
101
102 int index = allLogEntryMatchers.size();
103 switch (logMatcher.contents_case()) {
104 case LogEntryMatcher::ContentsCase::kSimpleLogEntryMatcher:
105 allLogEntryMatchers.push_back(new SimpleLogMatchingTracker(
106 logMatcher.name(), index, logMatcher.simple_log_entry_matcher()));
107 break;
108 case LogEntryMatcher::ContentsCase::kCombination:
109 allLogEntryMatchers.push_back(
110 new CombinationLogMatchingTracker(logMatcher.name(), index));
111 break;
112 default:
113 ALOGE("Matcher %s malformed", logMatcher.name().c_str());
114 return false;
115 // continue;
116 }
117 if (logTrackerMap.find(logMatcher.name()) != logTrackerMap.end()) {
118 ALOGE("Duplicate LogEntryMatcher found!");
119 return false;
120 }
121 logTrackerMap[logMatcher.name()] = index;
122 matcherConfigs.push_back(logMatcher);
123 }
124
125 vector<bool> stackTracker2(allLogEntryMatchers.size(), false);
126 for (auto& matcher : allLogEntryMatchers) {
127 if (!matcher->init(matcherConfigs, allLogEntryMatchers, logTrackerMap, stackTracker2)) {
128 return false;
129 }
130 // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
131 const set<int>& tagIds = matcher->getTagIds();
132 allTagIds.insert(tagIds.begin(), tagIds.end());
133 }
134 return true;
135}
136
137bool initConditions(const StatsdConfig& config, const unordered_map<string, int>& logTrackerMap,
138 unordered_map<string, int>& conditionTrackerMap,
139 vector<sp<ConditionTracker>>& allConditionTrackers,
140 unordered_map<int, std::vector<int>>& trackerToConditionMap) {
141 vector<Condition> conditionConfigs;
Yao Chen729093d2017-10-16 10:33:26 -0700142 const int conditionTrackerCount = config.condition_size();
143 conditionConfigs.reserve(conditionTrackerCount);
144 allConditionTrackers.reserve(conditionTrackerCount);
Yao Chencaf339d2017-10-06 16:01:10 -0700145
Yao Chen729093d2017-10-16 10:33:26 -0700146 for (int i = 0; i < conditionTrackerCount; i++) {
Yao Chencaf339d2017-10-06 16:01:10 -0700147 const Condition& condition = config.condition(i);
148 int index = allConditionTrackers.size();
149 switch (condition.contents_case()) {
150 case Condition::ContentsCase::kSimpleCondition: {
151 allConditionTrackers.push_back(new SimpleConditionTracker(
152 condition.name(), index, condition.simple_condition(), logTrackerMap));
153 break;
154 }
155 case Condition::ContentsCase::kCombination: {
156 allConditionTrackers.push_back(
157 new CombinationConditionTracker(condition.name(), index));
158 break;
159 }
160 default:
161 ALOGE("Condition %s malformed", condition.name().c_str());
162 return false;
163 }
164 if (conditionTrackerMap.find(condition.name()) != conditionTrackerMap.end()) {
165 ALOGE("Duplicate Condition found!");
166 return false;
167 }
168 conditionTrackerMap[condition.name()] = index;
169 conditionConfigs.push_back(condition);
170 }
171
172 vector<bool> stackTracker(allConditionTrackers.size(), false);
173 for (size_t i = 0; i < allConditionTrackers.size(); i++) {
174 auto& conditionTracker = allConditionTrackers[i];
175 if (!conditionTracker->init(conditionConfigs, allConditionTrackers, conditionTrackerMap,
176 stackTracker)) {
177 return false;
178 }
179 for (const int trackerIndex : conditionTracker->getLogTrackerIndex()) {
180 auto& conditionList = trackerToConditionMap[trackerIndex];
181 conditionList.push_back(i);
182 }
183 }
184 return true;
185}
186
187bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& logTrackerMap,
188 const unordered_map<string, int>& conditionTrackerMap,
Yao Chen5154a372017-10-30 22:57:06 -0700189 const vector<sp<LogMatchingTracker>>& allLogEntryMatchers,
Yao Chen729093d2017-10-16 10:33:26 -0700190 vector<sp<ConditionTracker>>& allConditionTrackers,
Yao Chencaf339d2017-10-06 16:01:10 -0700191 vector<sp<MetricProducer>>& allMetricProducers,
192 unordered_map<int, std::vector<int>>& conditionToMetricMap,
193 unordered_map<int, std::vector<int>>& trackerToMetricMap) {
Yao Chen729093d2017-10-16 10:33:26 -0700194 sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
Yao Chen93fe3a32017-11-02 13:52:59 -0700195 const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
196 config.event_metric_size() + config.value_metric_size();
Yao Chen729093d2017-10-16 10:33:26 -0700197 allMetricProducers.reserve(allMetricsCount);
Chenjie Yu6736c892017-11-09 10:50:09 -0800198 StatsPullerManager statsPullerManager;
Yao Chen93fe3a32017-11-02 13:52:59 -0700199 uint64_t startTimeNs = time(nullptr) * NS_PER_SEC;
Yao Chen729093d2017-10-16 10:33:26 -0700200
Yao Chencaf339d2017-10-06 16:01:10 -0700201 // Build MetricProducers for each metric defined in config.
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700202 // build CountMetricProducer
Yao Chencaf339d2017-10-06 16:01:10 -0700203 for (int i = 0; i < config.count_metric_size(); i++) {
204 const CountMetric& metric = config.count_metric(i);
205 if (!metric.has_what()) {
206 ALOGW("cannot find what in CountMetric %lld", metric.metric_id());
207 return false;
208 }
209
Yao Chen729093d2017-10-16 10:33:26 -0700210 int metricIndex = allMetricProducers.size();
Yao Chen5110bed2017-10-23 12:50:02 -0700211 int trackerIndex;
Yao Chen5154a372017-10-30 22:57:06 -0700212 if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.dimension_size() > 0,
213 allLogEntryMatchers, logTrackerMap, trackerToMetricMap,
214 trackerIndex)) {
Yao Chencaf339d2017-10-06 16:01:10 -0700215 return false;
216 }
217
Yao Chen5110bed2017-10-23 12:50:02 -0700218 int conditionIndex = -1;
Yao Chencaf339d2017-10-06 16:01:10 -0700219 if (metric.has_condition()) {
Yao Chen5110bed2017-10-23 12:50:02 -0700220 handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
221 metric.links(), allConditionTrackers, conditionIndex,
222 conditionToMetricMap);
Yao Chencaf339d2017-10-06 16:01:10 -0700223 }
Yao Chen5110bed2017-10-23 12:50:02 -0700224
Yao Chen93fe3a32017-11-02 13:52:59 -0700225 sp<MetricProducer> countProducer =
226 new CountMetricProducer(metric, conditionIndex, wizard, startTimeNs);
Yao Chencaf339d2017-10-06 16:01:10 -0700227 allMetricProducers.push_back(countProducer);
228 }
229
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700230 // build DurationMetricProducer
Yao Chen729093d2017-10-16 10:33:26 -0700231 for (int i = 0; i < config.duration_metric_size(); i++) {
232 int metricIndex = allMetricProducers.size();
Yao Chen5110bed2017-10-23 12:50:02 -0700233 const DurationMetric& metric = config.duration_metric(i);
Yao Chen5154a372017-10-30 22:57:06 -0700234
235 auto what_it = conditionTrackerMap.find(metric.what());
236 if (what_it == conditionTrackerMap.end()) {
237 ALOGE("DurationMetric's \"what\" is invalid");
238 return false;
239 }
240
241 const Condition& durationWhat = config.condition(what_it->second);
242
243 if (durationWhat.contents_case() != Condition::ContentsCase::kSimpleCondition) {
244 ALOGE("DurationMetric's \"what\" must be a simple condition");
245 return false;
246 }
247
248 const auto& simpleCondition = durationWhat.simple_condition();
249
Yao Chen5110bed2017-10-23 12:50:02 -0700250 int trackerIndices[3] = {-1, -1, -1};
Yao Chen5154a372017-10-30 22:57:06 -0700251 if (!simpleCondition.has_start() ||
252 !handleMetricWithLogTrackers(simpleCondition.start(), metricIndex,
253 metric.dimension_size() > 0, allLogEntryMatchers,
254 logTrackerMap, trackerToMetricMap, trackerIndices[0])) {
Yao Chen5110bed2017-10-23 12:50:02 -0700255 ALOGE("Duration metrics must specify a valid the start event matcher");
Yao Chen729093d2017-10-16 10:33:26 -0700256 return false;
257 }
Yao Chencaf339d2017-10-06 16:01:10 -0700258
Yao Chen5154a372017-10-30 22:57:06 -0700259 if (simpleCondition.has_stop() &&
260 !handleMetricWithLogTrackers(simpleCondition.stop(), metricIndex,
261 metric.dimension_size() > 0, allLogEntryMatchers,
262 logTrackerMap, trackerToMetricMap, trackerIndices[1])) {
Yao Chen5110bed2017-10-23 12:50:02 -0700263 return false;
Yao Chen729093d2017-10-16 10:33:26 -0700264 }
265
Yao Chen5154a372017-10-30 22:57:06 -0700266 if (simpleCondition.has_stop_all() &&
267 !handleMetricWithLogTrackers(simpleCondition.stop_all(), metricIndex,
268 metric.dimension_size() > 0, allLogEntryMatchers,
269 logTrackerMap, trackerToMetricMap, trackerIndices[2])) {
Yao Chen5110bed2017-10-23 12:50:02 -0700270 return false;
Yao Chen729093d2017-10-16 10:33:26 -0700271 }
272
Yao Chen5154a372017-10-30 22:57:06 -0700273 vector<KeyMatcher> internalDimension;
274 internalDimension.insert(internalDimension.begin(), simpleCondition.dimension().begin(),
275 simpleCondition.dimension().end());
276
Yao Chen729093d2017-10-16 10:33:26 -0700277 int conditionIndex = -1;
278
279 if (metric.has_predicate()) {
Yao Chen5110bed2017-10-23 12:50:02 -0700280 handleMetricWithConditions(metric.predicate(), metricIndex, conditionTrackerMap,
281 metric.links(), allConditionTrackers, conditionIndex,
282 conditionToMetricMap);
Yao Chen729093d2017-10-16 10:33:26 -0700283 }
284
Yao Chen5154a372017-10-30 22:57:06 -0700285 sp<MetricProducer> durationMetric = new DurationMetricProducer(
286 metric, conditionIndex, trackerIndices[0], trackerIndices[1], trackerIndices[2],
Yao Chen93fe3a32017-11-02 13:52:59 -0700287 wizard, internalDimension, startTimeNs);
Yao Chen729093d2017-10-16 10:33:26 -0700288
289 allMetricProducers.push_back(durationMetric);
290 }
Yao Chen5110bed2017-10-23 12:50:02 -0700291
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700292 // build EventMetricProducer
Yao Chen5110bed2017-10-23 12:50:02 -0700293 for (int i = 0; i < config.event_metric_size(); i++) {
294 int metricIndex = allMetricProducers.size();
295 const EventMetric& metric = config.event_metric(i);
296 if (!metric.has_metric_id() || !metric.has_what()) {
297 ALOGW("cannot find the metric id or what in config");
298 return false;
299 }
300 int trackerIndex;
Yao Chen5154a372017-10-30 22:57:06 -0700301 if (!handleMetricWithLogTrackers(metric.what(), metricIndex, false, allLogEntryMatchers,
302 logTrackerMap, trackerToMetricMap, trackerIndex)) {
Yao Chen5110bed2017-10-23 12:50:02 -0700303 return false;
304 }
305
306 int conditionIndex = -1;
307 if (metric.has_condition()) {
308 handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
309 metric.links(), allConditionTrackers, conditionIndex,
310 conditionToMetricMap);
311 }
312
Yao Chen93fe3a32017-11-02 13:52:59 -0700313 sp<MetricProducer> eventMetric =
314 new EventMetricProducer(metric, conditionIndex, wizard, startTimeNs);
315
Yao Chen5110bed2017-10-23 12:50:02 -0700316 allMetricProducers.push_back(eventMetric);
317 }
318
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700319 // build ValueMetricProducer
Chenjie Yub3dda412017-10-24 13:41:59 -0700320 for (int i = 0; i < config.value_metric_size(); i++) {
321 const ValueMetric& metric = config.value_metric(i);
322 if (!metric.has_what()) {
323 ALOGW("cannot find what in ValueMetric %lld", metric.metric_id());
324 return false;
325 }
326
Chenjie Yub3dda412017-10-24 13:41:59 -0700327 int metricIndex = allMetricProducers.size();
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700328 int trackerIndex;
329 if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.dimension_size() > 0,
330 allLogEntryMatchers, logTrackerMap, trackerToMetricMap,
331 trackerIndex)) {
332 return false;
333 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700334
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700335 sp<LogMatchingTracker> atomMatcher = allLogEntryMatchers.at(trackerIndex);
336 // If it is pulled atom, it should be simple matcher with one tagId.
337 int pullTagId = -1;
338 for (int tagId : atomMatcher->getTagIds()) {
339 if (statsPullerManager.PullerForMatcherExists(tagId)) {
340 if (atomMatcher->getTagIds().size() != 1) {
341 return false;
342 }
343 pullTagId = tagId;
344 }
345 }
346
347 int conditionIndex = -1;
348 if (metric.has_condition()) {
349 handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
350 metric.links(), allConditionTrackers, conditionIndex,
351 conditionToMetricMap);
352 }
353
354 sp<MetricProducer> valueProducer =
Yao Chen93fe3a32017-11-02 13:52:59 -0700355 new ValueMetricProducer(metric, conditionIndex, wizard, pullTagId, startTimeNs);
Chenjie Yub3dda412017-10-24 13:41:59 -0700356 allMetricProducers.push_back(valueProducer);
357 }
Yangster1d4d6862017-10-31 12:58:51 -0700358
359 // Gauge metrics.
360 for (int i = 0; i < config.gauge_metric_size(); i++) {
361 const GaugeMetric& metric = config.gauge_metric(i);
362 if (!metric.has_what()) {
363 ALOGW("cannot find what in ValueMetric %lld", metric.metric_id());
364 return false;
365 }
366
367 int metricIndex = allMetricProducers.size();
368 int trackerIndex;
369 if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.dimension_size() > 0,
370 allLogEntryMatchers, logTrackerMap, trackerToMetricMap,
371 trackerIndex)) {
372 return false;
373 }
374
375 sp<LogMatchingTracker> atomMatcher = allLogEntryMatchers.at(trackerIndex);
376 // If it is pulled atom, it should be simple matcher with one tagId.
377 int pullTagId = -1;
378 for (int tagId : atomMatcher->getTagIds()) {
379 if (statsPullerManager.PullerForMatcherExists(tagId)) {
380 if (atomMatcher->getTagIds().size() != 1) {
381 return false;
382 }
383 pullTagId = tagId;
384 }
385 }
386
387 int conditionIndex = -1;
388 if (metric.has_condition()) {
389 handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
390 metric.links(), allConditionTrackers, conditionIndex,
391 conditionToMetricMap);
392 }
393
394 sp<MetricProducer> gaugeProducer =
395 new GaugeMetricProducer(metric, conditionIndex, wizard, pullTagId);
396 allMetricProducers.push_back(gaugeProducer);
397 }
Yao Chencaf339d2017-10-06 16:01:10 -0700398 return true;
399}
400
401bool initStatsdConfig(const StatsdConfig& config, set<int>& allTagIds,
402 vector<sp<LogMatchingTracker>>& allLogEntryMatchers,
403 vector<sp<ConditionTracker>>& allConditionTrackers,
404 vector<sp<MetricProducer>>& allMetricProducers,
405 unordered_map<int, std::vector<int>>& conditionToMetricMap,
406 unordered_map<int, std::vector<int>>& trackerToMetricMap,
407 unordered_map<int, std::vector<int>>& trackerToConditionMap) {
408 unordered_map<string, int> logTrackerMap;
409 unordered_map<string, int> conditionTrackerMap;
410
411 if (!initLogTrackers(config, logTrackerMap, allLogEntryMatchers, allTagIds)) {
412 ALOGE("initLogMatchingTrackers failed");
413 return false;
414 }
Yangster1d4d6862017-10-31 12:58:51 -0700415 ALOGD("initLogMatchingTrackers succeed...");
Yao Chencaf339d2017-10-06 16:01:10 -0700416
417 if (!initConditions(config, logTrackerMap, conditionTrackerMap, allConditionTrackers,
418 trackerToConditionMap)) {
419 ALOGE("initConditionTrackers failed");
420 return false;
421 }
422
Yao Chen5154a372017-10-30 22:57:06 -0700423 if (!initMetrics(config, logTrackerMap, conditionTrackerMap, allLogEntryMatchers,
424 allConditionTrackers, allMetricProducers, conditionToMetricMap,
425 trackerToMetricMap)) {
Yao Chencaf339d2017-10-06 16:01:10 -0700426 ALOGE("initMetricProducers failed");
427 return false;
428 }
429 return true;
430}
431
432} // namespace statsd
433} // namespace os
434} // namespace android