blob: 35deffe5db97fa423414259328ff3614894a4d10 [file] [log] [blame]
Yao Chen729093d2017-10-16 10:33:26 -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
Yao Chen3c0b95c2017-12-16 14:34:20 -080017#define DEBUG false
Yao Chen5154a372017-10-30 22:57:06 -070018
Yao Chen729093d2017-10-16 10:33:26 -070019#include "Log.h"
Yao Chen5154a372017-10-30 22:57:06 -070020#include "DurationMetricProducer.h"
Yao Chenb3561512017-11-21 18:07:17 -080021#include "guardrail/StatsdStats.h"
Yao Chen729093d2017-10-16 10:33:26 -070022#include "stats_util.h"
Yangster-mac20877162017-12-22 17:19:39 -080023#include "stats_log_util.h"
Yao Chen729093d2017-10-16 10:33:26 -070024
Yao Chen729093d2017-10-16 10:33:26 -070025#include <limits.h>
26#include <stdlib.h>
27
yrob0378b02017-11-09 20:36:25 -080028using android::util::FIELD_COUNT_REPEATED;
yro2b0f8862017-11-06 14:27:31 -080029using android::util::FIELD_TYPE_BOOL;
30using android::util::FIELD_TYPE_FLOAT;
31using android::util::FIELD_TYPE_INT32;
32using android::util::FIELD_TYPE_INT64;
33using android::util::FIELD_TYPE_MESSAGE;
Yangster-macd1815dc2017-11-13 21:43:15 -080034using android::util::FIELD_TYPE_STRING;
yro2b0f8862017-11-06 14:27:31 -080035using android::util::ProtoOutputStream;
Yao Chen729093d2017-10-16 10:33:26 -070036using std::string;
37using std::unordered_map;
38using std::vector;
39
40namespace android {
41namespace os {
42namespace statsd {
43
yro2b0f8862017-11-06 14:27:31 -080044// for StatsLogReport
Yangster-mac94e197c2018-01-02 16:03:03 -080045const int FIELD_ID_ID = 1;
yro2b0f8862017-11-06 14:27:31 -080046const int FIELD_ID_DURATION_METRICS = 6;
Yangster-mac9def8e32018-04-17 13:55:51 -070047const int FIELD_ID_TIME_BASE = 9;
48const int FIELD_ID_BUCKET_SIZE = 10;
49const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11;
50const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12;
yro2b0f8862017-11-06 14:27:31 -080051// for DurationMetricDataWrapper
52const int FIELD_ID_DATA = 1;
53// for DurationMetricData
Yangster-mac468ff042018-01-17 12:26:34 -080054const int FIELD_ID_DIMENSION_IN_WHAT = 1;
55const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
56const int FIELD_ID_BUCKET_INFO = 3;
Yangster-mac9def8e32018-04-17 13:55:51 -070057const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
58const int FIELD_ID_DIMENSION_LEAF_IN_CONDITION = 5;
yro2b0f8862017-11-06 14:27:31 -080059// for DurationBucketInfo
yro2b0f8862017-11-06 14:27:31 -080060const int FIELD_ID_DURATION = 3;
Yangster-mac9def8e32018-04-17 13:55:51 -070061const int FIELD_ID_BUCKET_NUM = 4;
62const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
63const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
yro2b0f8862017-11-06 14:27:31 -080064
Yao Chenb3561512017-11-21 18:07:17 -080065DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const DurationMetric& metric,
Yao Chen729093d2017-10-16 10:33:26 -070066 const int conditionIndex, const size_t startIndex,
67 const size_t stopIndex, const size_t stopAllIndex,
Yao Chen0ea19902017-11-15 15:44:45 -080068 const bool nesting,
Yao Chen5154a372017-10-30 22:57:06 -070069 const sp<ConditionWizard>& wizard,
Yangster-mac20877162017-12-22 17:19:39 -080070 const FieldMatcher& internalDimensions,
Chenjie Yue1361ed2018-07-23 17:33:09 -070071 const int64_t timeBaseNs, const int64_t startTimeNs)
72 : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
Yao Chenf09569f2017-12-13 17:00:51 -080073 mAggregationType(metric.aggregation_type()),
Yao Chen729093d2017-10-16 10:33:26 -070074 mStartIndex(startIndex),
75 mStopIndex(stopIndex),
Yao Chen5154a372017-10-30 22:57:06 -070076 mStopAllIndex(stopAllIndex),
Yangster13fb7e42018-03-07 17:30:49 -080077 mNested(nesting),
78 mContainANYPositionInInternalDimensions(false) {
Yangster-macb8144812018-01-04 10:56:23 -080079 if (metric.has_bucket()) {
yro59cc24d2018-02-13 20:17:32 -080080 mBucketSizeNs =
81 TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
Yao Chen729093d2017-10-16 10:33:26 -070082 } else {
83 mBucketSizeNs = LLONG_MAX;
84 }
85
Yao Chen8a8d16c2018-02-08 14:50:40 -080086 if (metric.has_dimensions_in_what()) {
87 translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
Yangster13fb7e42018-03-07 17:30:49 -080088 mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
Yao Chen8a8d16c2018-02-08 14:50:40 -080089 }
90
91 if (internalDimensions.has_field()) {
92 translateFieldMatcher(internalDimensions, &mInternalDimensions);
Yangster13fb7e42018-03-07 17:30:49 -080093 mContainANYPositionInInternalDimensions = HasPositionANY(internalDimensions);
Yao Chen8a8d16c2018-02-08 14:50:40 -080094 }
Yangster-mace06cfd72018-03-10 23:22:59 -080095 if (mContainANYPositionInInternalDimensions) {
96 ALOGE("Position ANY in internal dimension not supported.");
97 }
98 if (mContainANYPositionInDimensionsInWhat) {
99 ALOGE("Position ANY in dimension_in_what not supported.");
100 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800101
102 if (metric.has_dimensions_in_condition()) {
103 translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition);
104 }
Yao Chen729093d2017-10-16 10:33:26 -0700105
Yangster-mac9def8e32018-04-17 13:55:51 -0700106 mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) ||
107 HasPositionALL(metric.dimensions_in_condition());
108
Yao Chen729093d2017-10-16 10:33:26 -0700109 if (metric.links().size() > 0) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800110 for (const auto& link : metric.links()) {
111 Metric2Condition mc;
112 mc.conditionId = link.condition();
113 translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
114 translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
115 mMetric2ConditionLinks.push_back(mc);
116 }
Yao Chen729093d2017-10-16 10:33:26 -0700117 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800118 mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
Yangster13fb7e42018-03-07 17:30:49 -0800119 mUnSlicedPartCondition = ConditionState::kUnknown;
Yao Chen729093d2017-10-16 10:33:26 -0700120
Yangster13fb7e42018-03-07 17:30:49 -0800121 mUseWhatDimensionAsInternalDimension = equalDimensions(mDimensionsInWhat, mInternalDimensions);
122 if (mWizard != nullptr && mConditionTrackerIndex >= 0) {
123 mSameConditionDimensionsInTracker =
124 mWizard->equalOutputDimensions(mConditionTrackerIndex, mDimensionsInCondition);
125 if (mMetric2ConditionLinks.size() == 1) {
126 mHasLinksToAllConditionDimensionsInTracker =
127 mWizard->equalOutputDimensions(mConditionTrackerIndex,
128 mMetric2ConditionLinks.begin()->conditionFields);
Yangster-mac53928882018-02-25 23:02:56 -0800129 }
Yangster-mac53928882018-02-25 23:02:56 -0800130 }
Chenjie Yue1361ed2018-07-23 17:33:09 -0700131 flushIfNeededLocked(startTimeNs);
132 // Adjust start for partial bucket
133 mCurrentBucketStartTimeNs = startTimeNs;
Yangster-mac94e197c2018-01-02 16:03:03 -0800134 VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700135 (long long)mBucketSizeNs, (long long)mTimeBaseNs);
Yao Chen729093d2017-10-16 10:33:26 -0700136}
137
138DurationMetricProducer::~DurationMetricProducer() {
139 VLOG("~DurationMetric() called");
140}
141
Yangster-mac932ecec2018-02-01 10:23:52 -0800142sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
143 const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) {
Bookatz857aaa52017-12-19 15:29:06 -0800144 std::lock_guard<std::mutex> lock(mMutex);
Bookatz423f7532018-03-08 15:45:14 -0800145 if (mAggregationType == DurationMetric_AggregationType_SUM) {
146 if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) {
147 ALOGW("invalid alert for SUM: threshold (%f) > possible recordable value (%d x %lld)",
148 alert.trigger_if_sum_gt(), alert.num_buckets(), (long long)mBucketSizeNs);
149 return nullptr;
150 }
151 }
Yangster-mac932ecec2018-02-01 10:23:52 -0800152 sp<DurationAnomalyTracker> anomalyTracker =
153 new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
Bookatz857aaa52017-12-19 15:29:06 -0800154 if (anomalyTracker != nullptr) {
155 mAnomalyTrackers.push_back(anomalyTracker);
156 }
157 return anomalyTracker;
Bookatz450099d2017-11-30 17:09:30 -0800158}
159
Yao Chen5154a372017-10-30 22:57:06 -0700160unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
Yangster-mac93694462018-01-22 20:49:31 -0800161 const MetricDimensionKey& eventKey) const {
Yao Chenf09569f2017-12-13 17:00:51 -0800162 switch (mAggregationType) {
Stefan Lafoncfed20b2017-11-18 09:26:53 -0800163 case DurationMetric_AggregationType_SUM:
Yao Chenb3561512017-11-21 18:07:17 -0800164 return make_unique<OringDurationTracker>(
Yangster-mac93694462018-01-22 20:49:31 -0800165 mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
David Chen27785a82018-01-19 17:06:45 -0800166 mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700167 mTimeBaseNs, mBucketSizeNs, mConditionSliced,
Yangster13fb7e42018-03-07 17:30:49 -0800168 mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
Stefan Lafoncfed20b2017-11-18 09:26:53 -0800169 case DurationMetric_AggregationType_MAX_SPARSE:
Yao Chenb3561512017-11-21 18:07:17 -0800170 return make_unique<MaxDurationTracker>(
Yangster-mac93694462018-01-22 20:49:31 -0800171 mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
David Chen27785a82018-01-19 17:06:45 -0800172 mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700173 mTimeBaseNs, mBucketSizeNs, mConditionSliced,
Yangster13fb7e42018-03-07 17:30:49 -0800174 mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
175 }
176}
177
178// SlicedConditionChange optimization case 1:
179// 1. If combination condition, logical operation is AND, only one sliced child predicate.
180// 2. No condition in dimension
181// 3. The links covers all dimension fields in the sliced child condition predicate.
Yao Chen427d3722018-03-22 15:21:52 -0700182void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition,
Yangster-macb142cc82018-03-30 15:22:08 -0700183 const int64_t eventTime) {
Yangster13fb7e42018-03-07 17:30:49 -0800184 if (mMetric2ConditionLinks.size() != 1 ||
185 !mHasLinksToAllConditionDimensionsInTracker ||
186 !mDimensionsInCondition.empty()) {
187 return;
188 }
189
190 bool currentUnSlicedPartCondition = true;
191 if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) {
192 ConditionState unslicedPartState =
193 mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex);
194 // When the unsliced part is still false, return directly.
195 if (mUnSlicedPartCondition == ConditionState::kFalse &&
196 unslicedPartState == ConditionState::kFalse) {
197 return;
198 }
199 mUnSlicedPartCondition = unslicedPartState;
200 currentUnSlicedPartCondition = mUnSlicedPartCondition > 0;
201 }
202
203 auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex);
204 auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex);
205
206 // The condition change is from the unsliced predicates.
207 // We need to find out the true dimensions from the sliced predicate and flip their condition
208 // state based on the new unsliced condition state.
209 if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr ||
210 (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) {
211 std::set<HashableDimensionKey> trueConditionDimensions;
212 mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, &trueConditionDimensions);
213 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
214 HashableDimensionKey linkedConditionDimensionKey;
215 getDimensionForCondition(whatIt.first.getValues(),
216 mMetric2ConditionLinks[0],
217 &linkedConditionDimensionKey);
218 if (trueConditionDimensions.find(linkedConditionDimensionKey) !=
219 trueConditionDimensions.end()) {
220 for (auto& condIt : whatIt.second) {
221 condIt.second->onConditionChanged(
222 currentUnSlicedPartCondition, eventTime);
223 }
224 }
225 }
226 } else {
227 // Handle the condition change from the sliced predicate.
228 if (currentUnSlicedPartCondition) {
229 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
230 HashableDimensionKey linkedConditionDimensionKey;
231 getDimensionForCondition(whatIt.first.getValues(),
232 mMetric2ConditionLinks[0],
233 &linkedConditionDimensionKey);
234 if (dimensionsChangedToTrue->find(linkedConditionDimensionKey) !=
235 dimensionsChangedToTrue->end()) {
236 for (auto& condIt : whatIt.second) {
237 condIt.second->onConditionChanged(true, eventTime);
238 }
239 }
240 if (dimensionsChangedToFalse->find(linkedConditionDimensionKey) !=
241 dimensionsChangedToFalse->end()) {
242 for (auto& condIt : whatIt.second) {
243 condIt.second->onConditionChanged(false, eventTime);
244 }
245 }
246 }
247 }
248 }
249}
250
251
252// SlicedConditionChange optimization case 2:
253// 1. If combination condition, logical operation is AND, only one sliced child predicate.
254// 2. Has dimensions_in_condition and it equals to the output dimensions of the sliced predicate.
Yao Chen427d3722018-03-22 15:21:52 -0700255void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(bool condition,
Yangster-macb142cc82018-03-30 15:22:08 -0700256 const int64_t eventTime) {
Yangster13fb7e42018-03-07 17:30:49 -0800257 if (mMetric2ConditionLinks.size() > 1 || !mSameConditionDimensionsInTracker) {
258 return;
259 }
260
261 auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex);
262 auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex);
263
264 bool currentUnSlicedPartCondition = true;
265 if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) {
266 ConditionState unslicedPartState =
267 mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex);
268 // When the unsliced part is still false, return directly.
269 if (mUnSlicedPartCondition == ConditionState::kFalse &&
270 unslicedPartState == ConditionState::kFalse) {
271 return;
272 }
273 mUnSlicedPartCondition = unslicedPartState;
274 currentUnSlicedPartCondition = mUnSlicedPartCondition > 0;
275 }
276
277 const std::set<HashableDimensionKey>* trueDimensionsToProcess = nullptr;
278 const std::set<HashableDimensionKey>* falseDimensionsToProcess = nullptr;
279
280 std::set<HashableDimensionKey> currentTrueConditionDimensions;
281 if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr ||
282 (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) {
283 mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, &currentTrueConditionDimensions);
284 trueDimensionsToProcess = &currentTrueConditionDimensions;
285 } else if (currentUnSlicedPartCondition) {
286 // Handles the condition change from the sliced predicate. If the unsliced condition state
287 // is not true, not need to do anything.
288 trueDimensionsToProcess = dimensionsChangedToTrue;
289 falseDimensionsToProcess = dimensionsChangedToFalse;
290 }
291
292 if (trueDimensionsToProcess == nullptr && falseDimensionsToProcess == nullptr) {
293 return;
294 }
295
296 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
297 if (falseDimensionsToProcess != nullptr) {
298 for (const auto& changedDim : *falseDimensionsToProcess) {
299 auto condIt = whatIt.second.find(changedDim);
300 if (condIt != whatIt.second.end()) {
301 condIt->second->onConditionChanged(false, eventTime);
302 }
303 }
304 }
305 if (trueDimensionsToProcess != nullptr) {
306 HashableDimensionKey linkedConditionDimensionKey;
307 if (!trueDimensionsToProcess->empty() && mMetric2ConditionLinks.size() == 1) {
308 getDimensionForCondition(whatIt.first.getValues(),
309 mMetric2ConditionLinks[0],
310 &linkedConditionDimensionKey);
311 }
312 for (auto& trueDim : *trueDimensionsToProcess) {
313 auto condIt = whatIt.second.find(trueDim);
314 if (condIt != whatIt.second.end()) {
315 condIt->second->onConditionChanged(
316 currentUnSlicedPartCondition, eventTime);
317 } else {
318 if (mMetric2ConditionLinks.size() == 0 ||
319 trueDim.contains(linkedConditionDimensionKey)) {
320 if (!whatIt.second.empty()) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700321 auto newEventKey = MetricDimensionKey(whatIt.first, trueDim);
322 if (hitGuardRailLocked(newEventKey)) {
323 continue;
324 }
Yangster13fb7e42018-03-07 17:30:49 -0800325 unique_ptr<DurationTracker> newTracker =
326 whatIt.second.begin()->second->clone(eventTime);
327 if (newTracker != nullptr) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700328 newTracker->setEventKey(newEventKey);
Yangster13fb7e42018-03-07 17:30:49 -0800329 newTracker->onConditionChanged(true, eventTime);
330 whatIt.second[trueDim] = std::move(newTracker);
331 }
332 }
333 }
334 }
335 }
336 }
Yao Chen5154a372017-10-30 22:57:06 -0700337 }
338}
339
Yao Chen427d3722018-03-22 15:21:52 -0700340void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
Yangster-macb142cc82018-03-30 15:22:08 -0700341 const int64_t eventTime) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800342 VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
Yangsterf2bee6f2017-11-29 12:01:05 -0800343 flushIfNeededLocked(eventTime);
Yangster-mac93694462018-01-22 20:49:31 -0800344
Yangster13fb7e42018-03-07 17:30:49 -0800345 if (!mConditionSliced) {
346 return;
347 }
348
349 bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex);
350 if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker &&
351 mDimensionsInCondition.empty()) {
Yao Chen427d3722018-03-22 15:21:52 -0700352 onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800353 return;
354 }
355
356 if (changeDimTrackable && mSameConditionDimensionsInTracker &&
357 mMetric2ConditionLinks.size() <= 1) {
Yao Chen427d3722018-03-22 15:21:52 -0700358 onSlicedConditionMayChangeLocked_opt2(overallCondition, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800359 return;
360 }
361
Yao Chen729093d2017-10-16 10:33:26 -0700362 // Now for each of the on-going event, check if the condition has changed for them.
Yangster-mac53928882018-02-25 23:02:56 -0800363 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
364 for (auto& pair : whatIt.second) {
Yao Chen427d3722018-03-22 15:21:52 -0700365 pair.second->onSlicedConditionMayChange(overallCondition, eventTime);
Yangster-mac53928882018-02-25 23:02:56 -0800366 }
Yao Chen729093d2017-10-16 10:33:26 -0700367 }
Yangster-mac93694462018-01-22 20:49:31 -0800368
Yangster-mac53928882018-02-25 23:02:56 -0800369 if (mDimensionsInCondition.empty()) {
370 return;
Yangster-mac93694462018-01-22 20:49:31 -0800371 }
Yangster-mac53928882018-02-25 23:02:56 -0800372
373 if (mMetric2ConditionLinks.empty()) {
374 std::unordered_set<HashableDimensionKey> conditionDimensionsKeySet;
375 mWizard->getMetConditionDimension(mConditionTrackerIndex, mDimensionsInCondition,
Yangster13fb7e42018-03-07 17:30:49 -0800376 !mSameConditionDimensionsInTracker,
Yangster-mac53928882018-02-25 23:02:56 -0800377 &conditionDimensionsKeySet);
378 for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) {
379 for (const auto& pair : whatIt.second) {
380 conditionDimensionsKeySet.erase(pair.first);
Yangster-mac93694462018-01-22 20:49:31 -0800381 }
Yangster-mac53928882018-02-25 23:02:56 -0800382 }
383 for (const auto& conditionDimension : conditionDimensionsKeySet) {
384 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
385 if (!whatIt.second.empty()) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700386 auto newEventKey = MetricDimensionKey(whatIt.first, conditionDimension);
387 if (hitGuardRailLocked(newEventKey)) {
388 continue;
389 }
Yangster-mac53928882018-02-25 23:02:56 -0800390 unique_ptr<DurationTracker> newTracker =
391 whatIt.second.begin()->second->clone(eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800392 if (newTracker != nullptr) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700393 newTracker->setEventKey(MetricDimensionKey(newEventKey));
Yao Chen427d3722018-03-22 15:21:52 -0700394 newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800395 whatIt.second[conditionDimension] = std::move(newTracker);
396 }
Yangster-mac53928882018-02-25 23:02:56 -0800397 }
398 }
399 }
400 } else {
401 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
402 ConditionKey conditionKey;
403 for (const auto& link : mMetric2ConditionLinks) {
404 getDimensionForCondition(whatIt.first.getValues(), link,
405 &conditionKey[link.conditionId]);
406 }
407 std::unordered_set<HashableDimensionKey> conditionDimensionsKeys;
408 mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
Yangster13fb7e42018-03-07 17:30:49 -0800409 !mSameConditionDimensionsInTracker,
410 !mHasLinksToAllConditionDimensionsInTracker,
Yangster-mac53928882018-02-25 23:02:56 -0800411 &conditionDimensionsKeys);
412
413 for (const auto& conditionDimension : conditionDimensionsKeys) {
414 if (!whatIt.second.empty() &&
415 whatIt.second.find(conditionDimension) == whatIt.second.end()) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700416 auto newEventKey = MetricDimensionKey(whatIt.first, conditionDimension);
417 if (hitGuardRailLocked(newEventKey)) {
418 continue;
419 }
Yangster-mac53928882018-02-25 23:02:56 -0800420 auto newTracker = whatIt.second.begin()->second->clone(eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800421 if (newTracker != nullptr) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700422 newTracker->setEventKey(newEventKey);
Yao Chen427d3722018-03-22 15:21:52 -0700423 newTracker->onSlicedConditionMayChange(overallCondition, eventTime);
Yangster13fb7e42018-03-07 17:30:49 -0800424 whatIt.second[conditionDimension] = std::move(newTracker);
425 }
Yangster-mac53928882018-02-25 23:02:56 -0800426 }
427 }
Yangster-mac93694462018-01-22 20:49:31 -0800428 }
429 }
Yao Chen729093d2017-10-16 10:33:26 -0700430}
431
Yangsterf2bee6f2017-11-29 12:01:05 -0800432void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
Yangster-macb142cc82018-03-30 15:22:08 -0700433 const int64_t eventTime) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800434 VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
Yao Chen729093d2017-10-16 10:33:26 -0700435 mCondition = conditionMet;
Yangsterf2bee6f2017-11-29 12:01:05 -0800436 flushIfNeededLocked(eventTime);
Yangster-mac53928882018-02-25 23:02:56 -0800437 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
438 for (auto& pair : whatIt.second) {
439 pair.second->onConditionChanged(conditionMet, eventTime);
440 }
Yao Chen729093d2017-10-16 10:33:26 -0700441 }
442}
443
Yangster-macb142cc82018-03-30 15:22:08 -0700444void DurationMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
Yao Chen06dba5d2018-01-26 13:38:16 -0800445 flushIfNeededLocked(dropTimeNs);
446 mPastBuckets.clear();
447}
448
Yangster-maca802d732018-04-24 07:50:38 -0700449void DurationMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) {
450 flushIfNeededLocked(dumpTimeNs);
451 mPastBuckets.clear();
452}
453
Yangster-macb142cc82018-03-30 15:22:08 -0700454void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
Yangster-mace68f3a52018-04-04 00:01:43 -0700455 const bool include_current_partial_bucket,
Bookatzff71cad2018-09-20 17:17:49 -0700456 const bool erase_data,
Yangster-mac9def8e32018-04-17 13:55:51 -0700457 std::set<string> *str_set,
Yao Chen288c6002017-12-12 13:43:18 -0800458 ProtoOutputStream* protoOutput) {
Yangster-mace68f3a52018-04-04 00:01:43 -0700459 if (include_current_partial_bucket) {
460 flushLocked(dumpTimeNs);
461 } else {
462 flushIfNeededLocked(dumpTimeNs);
463 }
Yangster-mac635b4b32018-01-23 20:17:35 -0800464 if (mPastBuckets.empty()) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800465 VLOG(" Duration metric, empty return");
Yangster-mac635b4b32018-01-23 20:17:35 -0800466 return;
467 }
Yao Chen6a8c7992017-11-29 20:02:07 +0000468
Yangster-mac94e197c2018-01-02 16:03:03 -0800469 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
Yangster-mac9def8e32018-04-17 13:55:51 -0700470 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TIME_BASE, (long long)mTimeBaseNs);
471 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_SIZE, (long long)mBucketSizeNs);
472
473 if (!mSliceByPositionALL) {
474 if (!mDimensionsInWhat.empty()) {
475 uint64_t dimenPathToken = protoOutput->start(
476 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT);
477 writeDimensionPathToProto(mDimensionsInWhat, protoOutput);
478 protoOutput->end(dimenPathToken);
479 }
480 if (!mDimensionsInCondition.empty()) {
481 uint64_t dimenPathToken = protoOutput->start(
482 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION);
483 writeDimensionPathToProto(mDimensionsInCondition, protoOutput);
484 protoOutput->end(dimenPathToken);
485 }
486 }
487
Yi Jin5ee07872018-03-05 18:18:27 -0800488 uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
Yao Chen288c6002017-12-12 13:43:18 -0800489
Yao Chen8a8d16c2018-02-08 14:50:40 -0800490 VLOG("Duration metric %lld dump report now...", (long long)mMetricId);
Yao Chen6a8c7992017-11-29 20:02:07 +0000491
Yao Chen729093d2017-10-16 10:33:26 -0700492 for (const auto& pair : mPastBuckets) {
Yangster-mac93694462018-01-22 20:49:31 -0800493 const MetricDimensionKey& dimensionKey = pair.first;
Yangster13fb7e42018-03-07 17:30:49 -0800494 VLOG(" dimension key %s", dimensionKey.toString().c_str());
Yao Chen1ff4f432017-11-16 17:01:40 -0800495
Yi Jin5ee07872018-03-05 18:18:27 -0800496 uint64_t wrapperToken =
Yao Chen288c6002017-12-12 13:43:18 -0800497 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
yro2b0f8862017-11-06 14:27:31 -0800498
Yangster-mac20877162017-12-22 17:19:39 -0800499 // First fill dimension.
Yangster-mac9def8e32018-04-17 13:55:51 -0700500 if (mSliceByPositionALL) {
501 uint64_t dimensionToken = protoOutput->start(
502 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
503 writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), str_set, protoOutput);
504 protoOutput->end(dimensionToken);
yro2b0f8862017-11-06 14:27:31 -0800505
Yangster-mac9def8e32018-04-17 13:55:51 -0700506 if (dimensionKey.hasDimensionKeyInCondition()) {
507 uint64_t dimensionInConditionToken = protoOutput->start(
508 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
509 writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(),
510 str_set, protoOutput);
511 protoOutput->end(dimensionInConditionToken);
512 }
513 } else {
514 writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInWhat(),
515 FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
516 if (dimensionKey.hasDimensionKeyInCondition()) {
517 writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInCondition(),
518 FIELD_ID_DIMENSION_LEAF_IN_CONDITION,
519 str_set, protoOutput);
520 }
Yangster-mac93694462018-01-22 20:49:31 -0800521 }
yro2b0f8862017-11-06 14:27:31 -0800522 // Then fill bucket_info (DurationBucketInfo).
523 for (const auto& bucket : pair.second) {
Yi Jin5ee07872018-03-05 18:18:27 -0800524 uint64_t bucketInfoToken = protoOutput->start(
Yao Chen288c6002017-12-12 13:43:18 -0800525 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
Yangster-mac9def8e32018-04-17 13:55:51 -0700526 if (bucket.mBucketEndNs - bucket.mBucketStartNs != mBucketSizeNs) {
527 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_MILLIS,
528 (long long)NanoToMillis(bucket.mBucketStartNs));
529 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_MILLIS,
530 (long long)NanoToMillis(bucket.mBucketEndNs));
531 } else {
532 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_NUM,
533 (long long)(getBucketNumFromEndTimeNs(bucket.mBucketEndNs)));
534 }
Yao Chen288c6002017-12-12 13:43:18 -0800535 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
536 protoOutput->end(bucketInfoToken);
yro2b0f8862017-11-06 14:27:31 -0800537 VLOG("\t bucket [%lld - %lld] duration: %lld", (long long)bucket.mBucketStartNs,
538 (long long)bucket.mBucketEndNs, (long long)bucket.mDuration);
539 }
540
Yao Chen288c6002017-12-12 13:43:18 -0800541 protoOutput->end(wrapperToken);
Yao Chen729093d2017-10-16 10:33:26 -0700542 }
yro2b0f8862017-11-06 14:27:31 -0800543
Yao Chen288c6002017-12-12 13:43:18 -0800544 protoOutput->end(protoToken);
Bookatzff71cad2018-09-20 17:17:49 -0700545 if (erase_data) {
546 mPastBuckets.clear();
547 }
yro2b0f8862017-11-06 14:27:31 -0800548}
Yao Chen729093d2017-10-16 10:33:26 -0700549
Yangster-macb142cc82018-03-30 15:22:08 -0700550void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
551 int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
David Chen27785a82018-01-19 17:06:45 -0800552
553 if (currentBucketEndTimeNs > eventTimeNs) {
Yao Chen729093d2017-10-16 10:33:26 -0700554 return;
555 }
Yao Chen5154a372017-10-30 22:57:06 -0700556 VLOG("flushing...........");
Yangster-mac53928882018-02-25 23:02:56 -0800557 for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
558 whatIt != mCurrentSlicedDurationTrackerMap.end();) {
559 for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
560 if (it->second->flushIfNeeded(eventTimeNs, &mPastBuckets)) {
Yangster13fb7e42018-03-07 17:30:49 -0800561 VLOG("erase bucket for key %s %s",
562 whatIt->first.toString().c_str(), it->first.toString().c_str());
Yangster-mac53928882018-02-25 23:02:56 -0800563 it = whatIt->second.erase(it);
564 } else {
565 ++it;
566 }
567 }
568 if (whatIt->second.empty()) {
569 whatIt = mCurrentSlicedDurationTrackerMap.erase(whatIt);
Yao Chend41c4222017-11-15 19:26:14 -0800570 } else {
Yangster-mac53928882018-02-25 23:02:56 -0800571 whatIt++;
Yao Chen729093d2017-10-16 10:33:26 -0700572 }
573 }
Yao Chen5154a372017-10-30 22:57:06 -0700574
David Chen27785a82018-01-19 17:06:45 -0800575 int numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
576 mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800577 mCurrentBucketNum += numBucketsForward;
Yao Chen5154a372017-10-30 22:57:06 -0700578}
579
Yangster-macb142cc82018-03-30 15:22:08 -0700580void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
Yangster-mac53928882018-02-25 23:02:56 -0800581 for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
582 whatIt != mCurrentSlicedDurationTrackerMap.end();) {
583 for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
584 if (it->second->flushCurrentBucket(eventTimeNs, &mPastBuckets)) {
Yangster13fb7e42018-03-07 17:30:49 -0800585 VLOG("erase bucket for key %s %s", whatIt->first.toString().c_str(),
586 it->first.toString().c_str());
Yangster-mac53928882018-02-25 23:02:56 -0800587 it = whatIt->second.erase(it);
588 } else {
589 ++it;
590 }
591 }
592 if (whatIt->second.empty()) {
593 whatIt = mCurrentSlicedDurationTrackerMap.erase(whatIt);
David Chen27785a82018-01-19 17:06:45 -0800594 } else {
Yangster-mac53928882018-02-25 23:02:56 -0800595 whatIt++;
David Chen27785a82018-01-19 17:06:45 -0800596 }
597 }
598}
599
Yao Chen884c8c12018-01-26 10:36:25 -0800600void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
Yangster-mac93694462018-01-22 20:49:31 -0800601 if (mCurrentSlicedDurationTrackerMap.size() == 0) {
Yao Chen884c8c12018-01-26 10:36:25 -0800602 return;
603 }
604
605 fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId,
Yangster-mac93694462018-01-22 20:49:31 -0800606 (unsigned long)mCurrentSlicedDurationTrackerMap.size());
Yao Chen884c8c12018-01-26 10:36:25 -0800607 if (verbose) {
Yangster-mac53928882018-02-25 23:02:56 -0800608 for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) {
609 for (const auto& slice : whatIt.second) {
Yangster13fb7e42018-03-07 17:30:49 -0800610 fprintf(out, "\t(what)%s\t(condition)%s\n", whatIt.first.toString().c_str(),
611 slice.first.toString().c_str());
Yangster-mac53928882018-02-25 23:02:56 -0800612 slice.second->dumpStates(out, verbose);
613 }
Yao Chen884c8c12018-01-26 10:36:25 -0800614 }
615 }
616}
617
Yangster-mac93694462018-01-22 20:49:31 -0800618bool DurationMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
Yangster-mac306ccc22018-03-24 15:03:40 -0700619 auto whatIt = mCurrentSlicedDurationTrackerMap.find(newKey.getDimensionKeyInWhat());
620 if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
621 auto condIt = whatIt->second.find(newKey.getDimensionKeyInCondition());
622 if (condIt != whatIt->second.end()) {
623 return false;
624 }
625 if (whatIt->second.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
626 size_t newTupleCount = whatIt->second.size() + 1;
627 StatsdStats::getInstance().noteMetricDimensionInConditionSize(
628 mConfigKey, mMetricId, newTupleCount);
629 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
630 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
631 ALOGE("DurationMetric %lld dropping data for condition dimension key %s",
632 (long long)mMetricId, newKey.getDimensionKeyInCondition().toString().c_str());
633 return true;
634 }
635 }
636 } else {
637 // 1. Report the tuple count if the tuple count > soft limit
638 if (mCurrentSlicedDurationTrackerMap.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
639 size_t newTupleCount = mCurrentSlicedDurationTrackerMap.size() + 1;
640 StatsdStats::getInstance().noteMetricDimensionSize(
641 mConfigKey, mMetricId, newTupleCount);
642 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
643 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
644 ALOGE("DurationMetric %lld dropping data for what dimension key %s",
645 (long long)mMetricId, newKey.getDimensionKeyInWhat().toString().c_str());
646 return true;
647 }
Yao Chenb3561512017-11-21 18:07:17 -0800648 }
649 }
650 return false;
651}
652
Yangster-mac53928882018-02-25 23:02:56 -0800653void DurationMetricProducer::handleStartEvent(const MetricDimensionKey& eventKey,
654 const ConditionKey& conditionKeys,
655 bool condition, const LogEvent& event) {
656 const auto& whatKey = eventKey.getDimensionKeyInWhat();
657 const auto& condKey = eventKey.getDimensionKeyInCondition();
Yao Chen5154a372017-10-30 22:57:06 -0700658
Yangster-mac53928882018-02-25 23:02:56 -0800659 auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatKey);
660 if (whatIt == mCurrentSlicedDurationTrackerMap.end()) {
Yangsterf2bee6f2017-11-29 12:01:05 -0800661 if (hitGuardRailLocked(eventKey)) {
Yao Chenb3561512017-11-21 18:07:17 -0800662 return;
663 }
Yangster-mac53928882018-02-25 23:02:56 -0800664 mCurrentSlicedDurationTrackerMap[whatKey][condKey] = createDurationTracker(eventKey);
665 } else {
666 if (whatIt->second.find(condKey) == whatIt->second.end()) {
667 if (hitGuardRailLocked(eventKey)) {
668 return;
669 }
670 mCurrentSlicedDurationTrackerMap[whatKey][condKey] = createDurationTracker(eventKey);
671 }
Yao Chen6a8c7992017-11-29 20:02:07 +0000672 }
Yao Chen5154a372017-10-30 22:57:06 -0700673
Yangster-mac53928882018-02-25 23:02:56 -0800674 auto it = mCurrentSlicedDurationTrackerMap.find(whatKey)->second.find(condKey);
675 if (mUseWhatDimensionAsInternalDimension) {
676 it->second->noteStart(whatKey, condition,
677 event.GetElapsedTimestampNs(), conditionKeys);
678 return;
679 }
Yao Chen5154a372017-10-30 22:57:06 -0700680
Yangster13fb7e42018-03-07 17:30:49 -0800681 if (mInternalDimensions.empty()) {
Yangster-mac53928882018-02-25 23:02:56 -0800682 it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
683 event.GetElapsedTimestampNs(), conditionKeys);
Yangster-mac20877162017-12-22 17:19:39 -0800684 } else {
Yangster-mace06cfd72018-03-10 23:22:59 -0800685 HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY;
686 filterValues(mInternalDimensions, event.getValues(), &dimensionKey);
687 it->second->noteStart(
688 dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
Yao Chen5154a372017-10-30 22:57:06 -0700689 }
Yangster-mac20877162017-12-22 17:19:39 -0800690
Yao Chen729093d2017-10-16 10:33:26 -0700691}
692
Yangster-mac53928882018-02-25 23:02:56 -0800693void DurationMetricProducer::onMatchedLogEventInternalLocked(
694 const size_t matcherIndex, const MetricDimensionKey& eventKey,
695 const ConditionKey& conditionKeys, bool condition,
696 const LogEvent& event) {
697 ALOGW("Not used in duration tracker.");
698}
699
Yangster-mace06cfd72018-03-10 23:22:59 -0800700void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
701 const LogEvent& event) {
Yangster-macb142cc82018-03-30 15:22:08 -0700702 int64_t eventTimeNs = event.GetElapsedTimestampNs();
Yangster-mac15f6bbc2018-04-08 11:52:26 -0700703 if (eventTimeNs < mTimeBaseNs) {
Yangster13fb7e42018-03-07 17:30:49 -0800704 return;
705 }
706
707 flushIfNeededLocked(event.GetElapsedTimestampNs());
708
709 // Handles Stopall events.
710 if (matcherIndex == mStopAllIndex) {
711 for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
712 for (auto& pair : whatIt.second) {
713 pair.second->noteStopAll(event.GetElapsedTimestampNs());
714 }
715 }
716 return;
717 }
718
719 HashableDimensionKey dimensionInWhat;
720 if (!mDimensionsInWhat.empty()) {
721 filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
722 } else {
723 dimensionInWhat = DEFAULT_DIMENSION_KEY;
724 }
725
726 // Handles Stop events.
727 if (matcherIndex == mStopIndex) {
728 if (mUseWhatDimensionAsInternalDimension) {
729 auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
730 if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
731 for (const auto& condIt : whatIt->second) {
732 condIt.second->noteStop(dimensionInWhat, event.GetElapsedTimestampNs(), false);
733 }
734 }
735 return;
736 }
737
738 HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY;
739 if (!mInternalDimensions.empty()) {
740 filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey);
741 }
742
743 auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
744 if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
745 for (const auto& condIt : whatIt->second) {
746 condIt.second->noteStop(
747 internalDimensionKey, event.GetElapsedTimestampNs(), false);
748 }
749 }
750 return;
751 }
752
753 bool condition;
754 ConditionKey conditionKey;
755 std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
756 if (mConditionSliced) {
757 for (const auto& link : mMetric2ConditionLinks) {
758 getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]);
759 }
760
761 auto conditionState =
762 mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
763 !mSameConditionDimensionsInTracker,
764 !mHasLinksToAllConditionDimensionsInTracker,
765 &dimensionKeysInCondition);
766 condition = (conditionState == ConditionState::kTrue);
767 if (mDimensionsInCondition.empty() && condition) {
768 dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
769 }
770 } else {
771 condition = mCondition;
772 if (condition) {
773 dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
774 }
775 }
776
777 if (dimensionKeysInCondition.empty()) {
778 handleStartEvent(MetricDimensionKey(dimensionInWhat, DEFAULT_DIMENSION_KEY),
779 conditionKey, condition, event);
780 } else {
781 auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
782 // If the what dimension is already there, we should update all the trackers even
783 // the condition is false.
784 if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
785 for (const auto& condIt : whatIt->second) {
786 const bool cond = dimensionKeysInCondition.find(condIt.first) !=
Yao Chen0aff9032018-07-03 10:51:05 -0700787 dimensionKeysInCondition.end() && condition;
Yangster13fb7e42018-03-07 17:30:49 -0800788 handleStartEvent(MetricDimensionKey(dimensionInWhat, condIt.first),
789 conditionKey, cond, event);
790 dimensionKeysInCondition.erase(condIt.first);
791 }
792 }
793 for (const auto& conditionDimension : dimensionKeysInCondition) {
794 handleStartEvent(MetricDimensionKey(dimensionInWhat, conditionDimension), conditionKey,
795 condition, event);
796 }
797 }
798}
799
Yangsterf2bee6f2017-11-29 12:01:05 -0800800size_t DurationMetricProducer::byteSizeLocked() const {
Yangster7c334a12017-11-22 14:24:24 -0800801 size_t totalSize = 0;
802 for (const auto& pair : mPastBuckets) {
803 totalSize += pair.second.size() * kBucketSize;
804 }
805 return totalSize;
yro69007c82017-10-26 20:42:57 -0700806}
807
Yao Chen729093d2017-10-16 10:33:26 -0700808} // namespace statsd
809} // namespace os
810} // namespace android