| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2017 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
| Yao Chen | 3c0b95c | 2017-12-16 14:34:20 -0800 | [diff] [blame] | 17 | #define DEBUG false | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 18 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 19 | #include "Log.h" | 
| Tej Singh | cfa32e1 | 2020-10-15 03:14:19 -0700 | [diff] [blame] | 20 |  | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 21 | #include "DurationMetricProducer.h" | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 22 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 23 | #include <limits.h> | 
 | 24 | #include <stdlib.h> | 
 | 25 |  | 
| Tej Singh | cfa32e1 | 2020-10-15 03:14:19 -0700 | [diff] [blame] | 26 | #include "guardrail/StatsdStats.h" | 
 | 27 | #include "metrics/parsing_utils/metrics_manager_util.h" | 
 | 28 | #include "stats_log_util.h" | 
 | 29 | #include "stats_util.h" | 
 | 30 |  | 
| yro | b0378b0 | 2017-11-09 20:36:25 -0800 | [diff] [blame] | 31 | using android::util::FIELD_COUNT_REPEATED; | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 32 | using android::util::FIELD_TYPE_BOOL; | 
 | 33 | using android::util::FIELD_TYPE_FLOAT; | 
 | 34 | using android::util::FIELD_TYPE_INT32; | 
 | 35 | using android::util::FIELD_TYPE_INT64; | 
 | 36 | using android::util::FIELD_TYPE_MESSAGE; | 
| Yangster-mac | d1815dc | 2017-11-13 21:43:15 -0800 | [diff] [blame] | 37 | using android::util::FIELD_TYPE_STRING; | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 38 | using android::util::ProtoOutputStream; | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 39 | using std::string; | 
 | 40 | using std::unordered_map; | 
 | 41 | using std::vector; | 
| Ruchir Rastogi | 21a287b | 2019-10-02 12:04:33 -0700 | [diff] [blame] | 42 | using std::shared_ptr; | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 43 |  | 
 | 44 | namespace android { | 
 | 45 | namespace os { | 
 | 46 | namespace statsd { | 
 | 47 |  | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 48 | // for StatsLogReport | 
| Yangster-mac | 94e197c | 2018-01-02 16:03:03 -0800 | [diff] [blame] | 49 | const int FIELD_ID_ID = 1; | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 50 | const int FIELD_ID_DURATION_METRICS = 6; | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 51 | const int FIELD_ID_TIME_BASE = 9; | 
 | 52 | const int FIELD_ID_BUCKET_SIZE = 10; | 
 | 53 | const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11; | 
| Howard Ro | 9440e09 | 2018-12-16 19:15:21 -0800 | [diff] [blame] | 54 | const int FIELD_ID_IS_ACTIVE = 14; | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 55 | // for DurationMetricDataWrapper | 
 | 56 | const int FIELD_ID_DATA = 1; | 
 | 57 | // for DurationMetricData | 
| Yangster-mac | 468ff04 | 2018-01-17 12:26:34 -0800 | [diff] [blame] | 58 | const int FIELD_ID_DIMENSION_IN_WHAT = 1; | 
| Yangster-mac | 468ff04 | 2018-01-17 12:26:34 -0800 | [diff] [blame] | 59 | const int FIELD_ID_BUCKET_INFO = 3; | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 60 | const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4; | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 61 | const int FIELD_ID_SLICE_BY_STATE = 6; | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 62 | // for DurationBucketInfo | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 63 | const int FIELD_ID_DURATION = 3; | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 64 | const int FIELD_ID_BUCKET_NUM = 4; | 
 | 65 | const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5; | 
 | 66 | const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6; | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 67 |  | 
| Ruchir Rastogi | 21a287b | 2019-10-02 12:04:33 -0700 | [diff] [blame] | 68 | DurationMetricProducer::DurationMetricProducer( | 
 | 69 |         const ConfigKey& key, const DurationMetric& metric, const int conditionIndex, | 
| Tej Singh | cfa32e1 | 2020-10-15 03:14:19 -0700 | [diff] [blame] | 70 |         const vector<ConditionState>& initialConditionCache, const int startIndex, | 
 | 71 |         const int stopIndex, const int stopAllIndex, const bool nesting, | 
| Tej Singh | 052d11c | 2020-08-28 02:48:40 -0700 | [diff] [blame] | 72 |         const sp<ConditionWizard>& wizard, const uint64_t protoHash, | 
 | 73 |         const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs, | 
| Ruchir Rastogi | 21a287b | 2019-10-02 12:04:33 -0700 | [diff] [blame] | 74 |         const unordered_map<int, shared_ptr<Activation>>& eventActivationMap, | 
| tsaichristine | d21aacf | 2019-10-07 14:47:38 -0700 | [diff] [blame] | 75 |         const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap, | 
 | 76 |         const vector<int>& slicedStateAtoms, | 
 | 77 |         const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) | 
| tsaichristine | 6e2e92d | 2020-05-18 14:39:45 -0700 | [diff] [blame] | 78 |     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard, | 
| Tej Singh | 052d11c | 2020-08-28 02:48:40 -0700 | [diff] [blame] | 79 |                      protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms, | 
 | 80 |                      stateGroupMap), | 
| Yao Chen | f09569f | 2017-12-13 17:00:51 -0800 | [diff] [blame] | 81 |       mAggregationType(metric.aggregation_type()), | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 82 |       mStartIndex(startIndex), | 
 | 83 |       mStopIndex(stopIndex), | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 84 |       mStopAllIndex(stopAllIndex), | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 85 |       mNested(nesting), | 
 | 86 |       mContainANYPositionInInternalDimensions(false) { | 
| Yangster-mac | b814481 | 2018-01-04 10:56:23 -0800 | [diff] [blame] | 87 |     if (metric.has_bucket()) { | 
| yro | 59cc24d | 2018-02-13 20:17:32 -0800 | [diff] [blame] | 88 |         mBucketSizeNs = | 
 | 89 |                 TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000; | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 90 |     } else { | 
 | 91 |         mBucketSizeNs = LLONG_MAX; | 
 | 92 |     } | 
 | 93 |  | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 94 |     if (metric.has_dimensions_in_what()) { | 
 | 95 |         translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 96 |         mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what()); | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 97 |     } | 
 | 98 |  | 
 | 99 |     if (internalDimensions.has_field()) { | 
 | 100 |         translateFieldMatcher(internalDimensions, &mInternalDimensions); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 101 |         mContainANYPositionInInternalDimensions = HasPositionANY(internalDimensions); | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 102 |     } | 
| Yangster-mac | e06cfd7 | 2018-03-10 23:22:59 -0800 | [diff] [blame] | 103 |     if (mContainANYPositionInInternalDimensions) { | 
 | 104 |         ALOGE("Position ANY in internal dimension not supported."); | 
 | 105 |     } | 
 | 106 |     if (mContainANYPositionInDimensionsInWhat) { | 
 | 107 |         ALOGE("Position ANY in dimension_in_what not supported."); | 
 | 108 |     } | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 109 |  | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 110 |     mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()); | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 111 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 112 |     if (metric.links().size() > 0) { | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 113 |         for (const auto& link : metric.links()) { | 
 | 114 |             Metric2Condition mc; | 
 | 115 |             mc.conditionId = link.condition(); | 
 | 116 |             translateFieldMatcher(link.fields_in_what(), &mc.metricFields); | 
 | 117 |             translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields); | 
 | 118 |             mMetric2ConditionLinks.push_back(mc); | 
 | 119 |         } | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 120 |         mConditionSliced = true; | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 121 |     } | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 122 |     mUnSlicedPartCondition = ConditionState::kUnknown; | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 123 |  | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 124 |     for (const auto& stateLink : metric.state_link()) { | 
 | 125 |         Metric2State ms; | 
 | 126 |         ms.stateAtomId = stateLink.state_atom_id(); | 
 | 127 |         translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields); | 
 | 128 |         translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields); | 
 | 129 |         mMetric2StateLinks.push_back(ms); | 
 | 130 |     } | 
 | 131 |  | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 132 |     mUseWhatDimensionAsInternalDimension = equalDimensions(mDimensionsInWhat, mInternalDimensions); | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 133 |     if (mWizard != nullptr && mConditionTrackerIndex >= 0 && | 
 | 134 |             mMetric2ConditionLinks.size() == 1) { | 
| tsaichristine | 69000e6 | 2019-10-18 17:34:52 -0700 | [diff] [blame] | 135 |         mHasLinksToAllConditionDimensionsInTracker = mWizard->equalOutputDimensions( | 
 | 136 |                 mConditionTrackerIndex, mMetric2ConditionLinks.begin()->conditionFields); | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 137 |     } | 
| Chenjie Yu | e1361ed | 2018-07-23 17:33:09 -0700 | [diff] [blame] | 138 |     flushIfNeededLocked(startTimeNs); | 
 | 139 |     // Adjust start for partial bucket | 
 | 140 |     mCurrentBucketStartTimeNs = startTimeNs; | 
| Yangster-mac | 94e197c | 2018-01-02 16:03:03 -0800 | [diff] [blame] | 141 |     VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(), | 
| Yangster-mac | 15f6bbc | 2018-04-08 11:52:26 -0700 | [diff] [blame] | 142 |          (long long)mBucketSizeNs, (long long)mTimeBaseNs); | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 143 | } | 
 | 144 |  | 
 | 145 | DurationMetricProducer::~DurationMetricProducer() { | 
 | 146 |     VLOG("~DurationMetric() called"); | 
 | 147 | } | 
 | 148 |  | 
| Tej Singh | cfa32e1 | 2020-10-15 03:14:19 -0700 | [diff] [blame] | 149 | bool DurationMetricProducer::onConfigUpdatedLocked( | 
 | 150 |         const StatsdConfig& config, const int configIndex, const int metricIndex, | 
 | 151 |         const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers, | 
 | 152 |         const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap, | 
 | 153 |         const unordered_map<int64_t, int>& newAtomMatchingTrackerMap, | 
 | 154 |         const sp<EventMatcherWizard>& matcherWizard, | 
 | 155 |         const vector<sp<ConditionTracker>>& allConditionTrackers, | 
 | 156 |         const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard, | 
 | 157 |         const unordered_map<int64_t, int>& metricToActivationMap, | 
 | 158 |         unordered_map<int, vector<int>>& trackerToMetricMap, | 
 | 159 |         unordered_map<int, vector<int>>& conditionToMetricMap, | 
 | 160 |         unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap, | 
 | 161 |         unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap, | 
 | 162 |         vector<int>& metricsWithActivation) { | 
 | 163 |     if (!MetricProducer::onConfigUpdatedLocked( | 
 | 164 |                 config, configIndex, metricIndex, allAtomMatchingTrackers, | 
 | 165 |                 oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard, | 
 | 166 |                 allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap, | 
 | 167 |                 trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap, | 
 | 168 |                 deactivationAtomTrackerToMetricMap, metricsWithActivation)) { | 
 | 169 |         return false; | 
 | 170 |     } | 
 | 171 |  | 
 | 172 |     const DurationMetric& metric = config.duration_metric(configIndex); | 
 | 173 |     const auto& what_it = conditionTrackerMap.find(metric.what()); | 
 | 174 |     if (what_it == conditionTrackerMap.end()) { | 
 | 175 |         ALOGE("DurationMetric's \"what\" is not present in the config"); | 
 | 176 |         return false; | 
 | 177 |     } | 
 | 178 |  | 
 | 179 |     const Predicate& durationWhat = config.predicate(what_it->second); | 
 | 180 |     if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) { | 
 | 181 |         ALOGE("DurationMetric's \"what\" must be a simple condition"); | 
 | 182 |         return false; | 
 | 183 |     } | 
 | 184 |  | 
 | 185 |     const SimplePredicate& simplePredicate = durationWhat.simple_predicate(); | 
 | 186 |  | 
 | 187 |     // Update indices: mStartIndex, mStopIndex, mStopAllIndex, mConditionIndex and MetricsManager | 
 | 188 |     // maps. | 
 | 189 |     if (!handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex, | 
 | 190 |                                               metric.has_dimensions_in_what(), | 
 | 191 |                                               allAtomMatchingTrackers, newAtomMatchingTrackerMap, | 
 | 192 |                                               trackerToMetricMap, mStartIndex)) { | 
 | 193 |         ALOGE("Duration metrics must specify a valid start event matcher"); | 
 | 194 |         return false; | 
 | 195 |     } | 
 | 196 |  | 
 | 197 |     if (simplePredicate.has_stop() && | 
 | 198 |         !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex, | 
 | 199 |                                               metric.has_dimensions_in_what(), | 
 | 200 |                                               allAtomMatchingTrackers, newAtomMatchingTrackerMap, | 
 | 201 |                                               trackerToMetricMap, mStopIndex)) { | 
 | 202 |         return false; | 
 | 203 |     } | 
 | 204 |  | 
 | 205 |     if (simplePredicate.has_stop_all() && | 
 | 206 |         !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex, | 
 | 207 |                                               metric.has_dimensions_in_what(), | 
 | 208 |                                               allAtomMatchingTrackers, newAtomMatchingTrackerMap, | 
 | 209 |                                               trackerToMetricMap, mStopAllIndex)) { | 
 | 210 |         return false; | 
 | 211 |     } | 
 | 212 |  | 
 | 213 |     if (metric.has_condition() && | 
 | 214 |         !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap, | 
 | 215 |                                     metric.links(), allConditionTrackers, mConditionTrackerIndex, | 
 | 216 |                                     conditionToMetricMap)) { | 
 | 217 |         return false; | 
 | 218 |     } | 
 | 219 |  | 
 | 220 |     for (const auto& it : mCurrentSlicedDurationTrackerMap) { | 
 | 221 |         it.second->onConfigUpdated(wizard, mConditionTrackerIndex); | 
 | 222 |     } | 
 | 223 |  | 
 | 224 |     return true; | 
 | 225 | } | 
 | 226 |  | 
| Yangster-mac | 932ecec | 2018-02-01 10:23:52 -0800 | [diff] [blame] | 227 | sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker( | 
 | 228 |         const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) { | 
| Bookatz | 857aaa5 | 2017-12-19 15:29:06 -0800 | [diff] [blame] | 229 |     std::lock_guard<std::mutex> lock(mMutex); | 
| Bookatz | 423f753 | 2018-03-08 15:45:14 -0800 | [diff] [blame] | 230 |     if (mAggregationType == DurationMetric_AggregationType_SUM) { | 
 | 231 |         if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) { | 
 | 232 |             ALOGW("invalid alert for SUM: threshold (%f) > possible recordable value (%d x %lld)", | 
 | 233 |                   alert.trigger_if_sum_gt(), alert.num_buckets(), (long long)mBucketSizeNs); | 
 | 234 |             return nullptr; | 
 | 235 |         } | 
 | 236 |     } | 
| Tej Singh | d07d0ff | 2020-10-27 20:56:11 -0700 | [diff] [blame] | 237 |     sp<AnomalyTracker> anomalyTracker = | 
 | 238 |             new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor); | 
 | 239 |     addAnomalyTrackerLocked(anomalyTracker); | 
| Bookatz | 857aaa5 | 2017-12-19 15:29:06 -0800 | [diff] [blame] | 240 |     return anomalyTracker; | 
| Bookatz | 450099d | 2017-11-30 17:09:30 -0800 | [diff] [blame] | 241 | } | 
 | 242 |  | 
| Tej Singh | d07d0ff | 2020-10-27 20:56:11 -0700 | [diff] [blame] | 243 | // Adds an AnomalyTracker that has already been created. | 
 | 244 | // Note: this gets called on config updates, and will only get called if the metric and the | 
 | 245 | // associated alert are preserved, which means the AnomalyTracker must be a DurationAnomalyTracker. | 
 | 246 | void DurationMetricProducer::addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) { | 
 | 247 |     std::lock_guard<std::mutex> lock(mMutex); | 
 | 248 |     addAnomalyTrackerLocked(anomalyTracker); | 
 | 249 | } | 
 | 250 |  | 
 | 251 | void DurationMetricProducer::addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker) { | 
 | 252 |     mAnomalyTrackers.push_back(anomalyTracker); | 
 | 253 |     for (const auto& [_, durationTracker] : mCurrentSlicedDurationTrackerMap) { | 
 | 254 |         durationTracker->addAnomalyTracker(anomalyTracker); | 
 | 255 |     } | 
 | 256 | } | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 257 | void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId, | 
 | 258 |                                             const HashableDimensionKey& primaryKey, | 
| tsaichristine | 9f95105 | 2020-05-13 14:32:37 -0700 | [diff] [blame] | 259 |                                             const FieldValue& oldState, | 
 | 260 |                                             const FieldValue& newState) { | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 261 |     // Check if this metric has a StateMap. If so, map the new state value to | 
 | 262 |     // the correct state group id. | 
| tsaichristine | 9f95105 | 2020-05-13 14:32:37 -0700 | [diff] [blame] | 263 |     FieldValue newStateCopy = newState; | 
 | 264 |     mapStateValue(atomId, &newStateCopy); | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 265 |  | 
 | 266 |     flushIfNeededLocked(eventTimeNs); | 
 | 267 |  | 
 | 268 |     // Each duration tracker is mapped to a different whatKey (a set of values from the | 
 | 269 |     // dimensionsInWhat fields). We notify all trackers iff the primaryKey field values from the | 
 | 270 |     // state change event are a subset of the tracker's whatKey field values. | 
 | 271 |     // | 
 | 272 |     // Ex. For a duration metric dimensioned on uid and tag: | 
 | 273 |     // DurationTracker1 whatKey = uid: 1001, tag: 1 | 
 | 274 |     // DurationTracker2 whatKey = uid: 1002, tag 1 | 
 | 275 |     // | 
 | 276 |     // If the state change primaryKey = uid: 1001, we only notify DurationTracker1 of a state | 
 | 277 |     // change. | 
 | 278 |     for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
 | 279 |         if (!containsLinkedStateValues(whatIt.first, primaryKey, mMetric2StateLinks, atomId)) { | 
 | 280 |             continue; | 
 | 281 |         } | 
| tsaichristine | 9f95105 | 2020-05-13 14:32:37 -0700 | [diff] [blame] | 282 |         whatIt.second->onStateChanged(eventTimeNs, atomId, newStateCopy); | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 283 |     } | 
 | 284 | } | 
 | 285 |  | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 286 | unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker( | 
| Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 287 |         const MetricDimensionKey& eventKey) const { | 
| Yao Chen | f09569f | 2017-12-13 17:00:51 -0800 | [diff] [blame] | 288 |     switch (mAggregationType) { | 
| Stefan Lafon | cfed20b | 2017-11-18 09:26:53 -0800 | [diff] [blame] | 289 |         case DurationMetric_AggregationType_SUM: | 
| Yao Chen | b356151 | 2017-11-21 18:07:17 -0800 | [diff] [blame] | 290 |             return make_unique<OringDurationTracker>( | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 291 |                     mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested, | 
 | 292 |                     mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs, | 
 | 293 |                     mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers); | 
| Stefan Lafon | cfed20b | 2017-11-18 09:26:53 -0800 | [diff] [blame] | 294 |         case DurationMetric_AggregationType_MAX_SPARSE: | 
| Yao Chen | b356151 | 2017-11-21 18:07:17 -0800 | [diff] [blame] | 295 |             return make_unique<MaxDurationTracker>( | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 296 |                     mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested, | 
 | 297 |                     mCurrentBucketStartTimeNs, mCurrentBucketNum, mTimeBaseNs, mBucketSizeNs, | 
 | 298 |                     mConditionSliced, mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 299 |     } | 
 | 300 | } | 
 | 301 |  | 
 | 302 | // SlicedConditionChange optimization case 1: | 
 | 303 | // 1. If combination condition, logical operation is AND, only one sliced child predicate. | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 304 | // 2. The links covers all dimension fields in the sliced child condition predicate. | 
| Yao Chen | 427d372 | 2018-03-22 15:21:52 -0700 | [diff] [blame] | 305 | void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition, | 
| Yangster-mac | b142cc8 | 2018-03-30 15:22:08 -0700 | [diff] [blame] | 306 |                                                                    const int64_t eventTime) { | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 307 |     if (mMetric2ConditionLinks.size() != 1 || | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 308 |         !mHasLinksToAllConditionDimensionsInTracker) { | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 309 |         return; | 
 | 310 |     } | 
 | 311 |  | 
 | 312 |     bool  currentUnSlicedPartCondition = true; | 
 | 313 |     if (!mWizard->IsSimpleCondition(mConditionTrackerIndex)) { | 
 | 314 |         ConditionState unslicedPartState = | 
 | 315 |             mWizard->getUnSlicedPartConditionState(mConditionTrackerIndex); | 
 | 316 |         // When the unsliced part is still false, return directly. | 
 | 317 |         if (mUnSlicedPartCondition == ConditionState::kFalse && | 
 | 318 |             unslicedPartState == ConditionState::kFalse) { | 
 | 319 |             return; | 
 | 320 |         } | 
 | 321 |         mUnSlicedPartCondition = unslicedPartState; | 
 | 322 |         currentUnSlicedPartCondition = mUnSlicedPartCondition > 0; | 
 | 323 |     } | 
 | 324 |  | 
 | 325 |     auto dimensionsChangedToTrue = mWizard->getChangedToTrueDimensions(mConditionTrackerIndex); | 
 | 326 |     auto dimensionsChangedToFalse = mWizard->getChangedToFalseDimensions(mConditionTrackerIndex); | 
 | 327 |  | 
 | 328 |     // The condition change is from the unsliced predicates. | 
 | 329 |     // We need to find out the true dimensions from the sliced predicate and flip their condition | 
 | 330 |     // state based on the new unsliced condition state. | 
 | 331 |     if (dimensionsChangedToTrue == nullptr || dimensionsChangedToFalse == nullptr || | 
 | 332 |         (dimensionsChangedToTrue->empty() && dimensionsChangedToFalse->empty())) { | 
 | 333 |         std::set<HashableDimensionKey> trueConditionDimensions; | 
 | 334 |         mWizard->getTrueSlicedDimensions(mConditionTrackerIndex, &trueConditionDimensions); | 
 | 335 |         for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
 | 336 |             HashableDimensionKey linkedConditionDimensionKey; | 
| tsaichristine | 69000e6 | 2019-10-18 17:34:52 -0700 | [diff] [blame] | 337 |             getDimensionForCondition(whatIt.first.getValues(), mMetric2ConditionLinks[0], | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 338 |                                      &linkedConditionDimensionKey); | 
 | 339 |             if (trueConditionDimensions.find(linkedConditionDimensionKey) != | 
 | 340 |                     trueConditionDimensions.end()) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 341 |                 whatIt.second->onConditionChanged(currentUnSlicedPartCondition, eventTime); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 342 |             } | 
 | 343 |         } | 
 | 344 |     } else { | 
 | 345 |         // Handle the condition change from the sliced predicate. | 
 | 346 |         if (currentUnSlicedPartCondition) { | 
 | 347 |             for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
 | 348 |                 HashableDimensionKey linkedConditionDimensionKey; | 
| tsaichristine | 69000e6 | 2019-10-18 17:34:52 -0700 | [diff] [blame] | 349 |                 getDimensionForCondition(whatIt.first.getValues(), mMetric2ConditionLinks[0], | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 350 |                                          &linkedConditionDimensionKey); | 
 | 351 |                 if (dimensionsChangedToTrue->find(linkedConditionDimensionKey) != | 
 | 352 |                         dimensionsChangedToTrue->end()) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 353 |                     whatIt.second->onConditionChanged(true, eventTime); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 354 |                 } | 
 | 355 |                 if (dimensionsChangedToFalse->find(linkedConditionDimensionKey) != | 
 | 356 |                         dimensionsChangedToFalse->end()) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 357 |                     whatIt.second->onConditionChanged(false, eventTime); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 358 |                 } | 
 | 359 |             } | 
 | 360 |         } | 
 | 361 |     } | 
 | 362 | } | 
 | 363 |  | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 364 | void DurationMetricProducer::onSlicedConditionMayChangeInternalLocked(bool overallCondition, | 
 | 365 |         const int64_t eventTimeNs) { | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 366 |     bool changeDimTrackable = mWizard->IsChangedDimensionTrackable(mConditionTrackerIndex); | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 367 |     if (changeDimTrackable && mHasLinksToAllConditionDimensionsInTracker) { | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 368 |         onSlicedConditionMayChangeLocked_opt1(overallCondition, eventTimeNs); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 369 |         return; | 
 | 370 |     } | 
 | 371 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 372 |     // Now for each of the on-going event, check if the condition has changed for them. | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 373 |     for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 374 |         whatIt.second->onSlicedConditionMayChange(overallCondition, eventTimeNs); | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 375 |     } | 
 | 376 | } | 
 | 377 |  | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 378 | void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition, | 
 | 379 |                                                               const int64_t eventTime) { | 
 | 380 |     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId); | 
 | 381 |  | 
 | 382 |     if (!mIsActive) { | 
 | 383 |         return; | 
 | 384 |     } | 
 | 385 |  | 
 | 386 |     flushIfNeededLocked(eventTime); | 
 | 387 |  | 
 | 388 |     if (!mConditionSliced) { | 
 | 389 |         return; | 
 | 390 |     } | 
 | 391 |  | 
 | 392 |     onSlicedConditionMayChangeInternalLocked(overallCondition, eventTime); | 
 | 393 | } | 
 | 394 |  | 
 | 395 | void DurationMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs) { | 
 | 396 |     MetricProducer::onActiveStateChangedLocked(eventTimeNs); | 
 | 397 |  | 
 | 398 |     if (!mConditionSliced) { | 
 | 399 |         if (ConditionState::kTrue != mCondition) { | 
 | 400 |             return; | 
 | 401 |         } | 
 | 402 |  | 
 | 403 |         if (mIsActive) { | 
 | 404 |             flushIfNeededLocked(eventTimeNs); | 
 | 405 |         } | 
 | 406 |  | 
 | 407 |         for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 408 |             whatIt.second->onConditionChanged(mIsActive, eventTimeNs); | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 409 |         } | 
 | 410 |     } else if (mIsActive) { | 
 | 411 |         flushIfNeededLocked(eventTimeNs); | 
 | 412 |         onSlicedConditionMayChangeInternalLocked(mIsActive, eventTimeNs); | 
 | 413 |     } else { // mConditionSliced == true && !mIsActive | 
 | 414 |         for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 415 |             whatIt.second->onConditionChanged(mIsActive, eventTimeNs); | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 416 |         } | 
 | 417 |     } | 
 | 418 | } | 
 | 419 |  | 
| Yangster | f2bee6f | 2017-11-29 12:01:05 -0800 | [diff] [blame] | 420 | void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet, | 
| Yangster-mac | b142cc8 | 2018-03-30 15:22:08 -0700 | [diff] [blame] | 421 |                                                       const int64_t eventTime) { | 
| Yangster-mac | 94e197c | 2018-01-02 16:03:03 -0800 | [diff] [blame] | 422 |     VLOG("Metric %lld onConditionChanged", (long long)mMetricId); | 
| Olivier Gaillard | e63d9e0 | 2019-02-12 14:43:59 +0000 | [diff] [blame] | 423 |     mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse; | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 424 |  | 
 | 425 |     if (!mIsActive) { | 
 | 426 |         return; | 
 | 427 |     } | 
 | 428 |  | 
| Yangster | f2bee6f | 2017-11-29 12:01:05 -0800 | [diff] [blame] | 429 |     flushIfNeededLocked(eventTime); | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 430 |     for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 431 |         whatIt.second->onConditionChanged(conditionMet, eventTime); | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 432 |     } | 
 | 433 | } | 
 | 434 |  | 
| Yangster-mac | b142cc8 | 2018-03-30 15:22:08 -0700 | [diff] [blame] | 435 | void DurationMetricProducer::dropDataLocked(const int64_t dropTimeNs) { | 
| Yao Chen | 06dba5d | 2018-01-26 13:38:16 -0800 | [diff] [blame] | 436 |     flushIfNeededLocked(dropTimeNs); | 
| Olivier Gaillard | 320952b | 2019-02-06 13:57:24 +0000 | [diff] [blame] | 437 |     StatsdStats::getInstance().noteBucketDropped(mMetricId); | 
| Yao Chen | 06dba5d | 2018-01-26 13:38:16 -0800 | [diff] [blame] | 438 |     mPastBuckets.clear(); | 
 | 439 | } | 
 | 440 |  | 
| Yangster-mac | a802d73 | 2018-04-24 07:50:38 -0700 | [diff] [blame] | 441 | void DurationMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) { | 
 | 442 |     flushIfNeededLocked(dumpTimeNs); | 
 | 443 |     mPastBuckets.clear(); | 
 | 444 | } | 
 | 445 |  | 
| Yangster-mac | b142cc8 | 2018-03-30 15:22:08 -0700 | [diff] [blame] | 446 | void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, | 
| Yangster-mac | e68f3a5 | 2018-04-04 00:01:43 -0700 | [diff] [blame] | 447 |                                                 const bool include_current_partial_bucket, | 
| Bookatz | ff71cad | 2018-09-20 17:17:49 -0700 | [diff] [blame] | 448 |                                                 const bool erase_data, | 
| Olivier Gaillard | 6c75ecd | 2019-02-20 09:57:33 +0000 | [diff] [blame] | 449 |                                                 const DumpLatency dumpLatency, | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 450 |                                                 std::set<string> *str_set, | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 451 |                                                 ProtoOutputStream* protoOutput) { | 
| Yangster-mac | e68f3a5 | 2018-04-04 00:01:43 -0700 | [diff] [blame] | 452 |     if (include_current_partial_bucket) { | 
 | 453 |         flushLocked(dumpTimeNs); | 
 | 454 |     } else { | 
 | 455 |         flushIfNeededLocked(dumpTimeNs); | 
 | 456 |     } | 
| Yang Lu | b472291 | 2018-11-15 11:02:03 -0800 | [diff] [blame] | 457 |     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); | 
| Howard Ro | 07e23ff | 2018-12-17 17:28:07 -0800 | [diff] [blame] | 458 |     protoOutput->write(FIELD_TYPE_BOOL | FIELD_ID_IS_ACTIVE, isActiveLocked()); | 
| Yang Lu | b472291 | 2018-11-15 11:02:03 -0800 | [diff] [blame] | 459 |  | 
| Yangster-mac | 635b4b3 | 2018-01-23 20:17:35 -0800 | [diff] [blame] | 460 |     if (mPastBuckets.empty()) { | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 461 |         VLOG(" Duration metric, empty return"); | 
| Yangster-mac | 635b4b3 | 2018-01-23 20:17:35 -0800 | [diff] [blame] | 462 |         return; | 
 | 463 |     } | 
| Yao Chen | 6a8c799 | 2017-11-29 20:02:07 +0000 | [diff] [blame] | 464 |  | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 465 |     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_TIME_BASE, (long long)mTimeBaseNs); | 
 | 466 |     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_SIZE, (long long)mBucketSizeNs); | 
 | 467 |  | 
 | 468 |     if (!mSliceByPositionALL) { | 
 | 469 |         if (!mDimensionsInWhat.empty()) { | 
 | 470 |             uint64_t dimenPathToken = protoOutput->start( | 
 | 471 |                     FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT); | 
 | 472 |             writeDimensionPathToProto(mDimensionsInWhat, protoOutput); | 
 | 473 |             protoOutput->end(dimenPathToken); | 
 | 474 |         } | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 475 |     } | 
 | 476 |  | 
| Yi Jin | 5ee0787 | 2018-03-05 18:18:27 -0800 | [diff] [blame] | 477 |     uint64_t protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS); | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 478 |  | 
| Yao Chen | 8a8d16c | 2018-02-08 14:50:40 -0800 | [diff] [blame] | 479 |     VLOG("Duration metric %lld dump report now...", (long long)mMetricId); | 
| Yao Chen | 6a8c799 | 2017-11-29 20:02:07 +0000 | [diff] [blame] | 480 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 481 |     for (const auto& pair : mPastBuckets) { | 
| Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 482 |         const MetricDimensionKey& dimensionKey = pair.first; | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 483 |         VLOG("  dimension key %s", dimensionKey.toString().c_str()); | 
| Yao Chen | 1ff4f43 | 2017-11-16 17:01:40 -0800 | [diff] [blame] | 484 |  | 
| Yi Jin | 5ee0787 | 2018-03-05 18:18:27 -0800 | [diff] [blame] | 485 |         uint64_t wrapperToken = | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 486 |                 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 487 |  | 
| Yangster-mac | 2087716 | 2017-12-22 17:19:39 -0800 | [diff] [blame] | 488 |         // First fill dimension. | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 489 |         if (mSliceByPositionALL) { | 
 | 490 |             uint64_t dimensionToken = protoOutput->start( | 
 | 491 |                     FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT); | 
 | 492 |             writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), str_set, protoOutput); | 
 | 493 |             protoOutput->end(dimensionToken); | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 494 |         } else { | 
 | 495 |             writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInWhat(), | 
 | 496 |                                            FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput); | 
| Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 497 |         } | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 498 |         // Then fill slice_by_state. | 
 | 499 |         for (auto state : dimensionKey.getStateValuesKey().getValues()) { | 
 | 500 |             uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | | 
 | 501 |                                                      FIELD_ID_SLICE_BY_STATE); | 
 | 502 |             writeStateToProto(state, protoOutput); | 
 | 503 |             protoOutput->end(stateToken); | 
 | 504 |         } | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 505 |         // Then fill bucket_info (DurationBucketInfo). | 
 | 506 |         for (const auto& bucket : pair.second) { | 
| Yi Jin | 5ee0787 | 2018-03-05 18:18:27 -0800 | [diff] [blame] | 507 |             uint64_t bucketInfoToken = protoOutput->start( | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 508 |                     FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO); | 
| Yangster-mac | 9def8e3 | 2018-04-17 13:55:51 -0700 | [diff] [blame] | 509 |             if (bucket.mBucketEndNs - bucket.mBucketStartNs != mBucketSizeNs) { | 
 | 510 |                 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_ELAPSED_MILLIS, | 
 | 511 |                                    (long long)NanoToMillis(bucket.mBucketStartNs)); | 
 | 512 |                 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_ELAPSED_MILLIS, | 
 | 513 |                                    (long long)NanoToMillis(bucket.mBucketEndNs)); | 
 | 514 |             } else { | 
 | 515 |                 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_NUM, | 
 | 516 |                                    (long long)(getBucketNumFromEndTimeNs(bucket.mBucketEndNs))); | 
 | 517 |             } | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 518 |             protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration); | 
 | 519 |             protoOutput->end(bucketInfoToken); | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 520 |             VLOG("\t bucket [%lld - %lld] duration: %lld", (long long)bucket.mBucketStartNs, | 
 | 521 |                  (long long)bucket.mBucketEndNs, (long long)bucket.mDuration); | 
 | 522 |         } | 
 | 523 |  | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 524 |         protoOutput->end(wrapperToken); | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 525 |     } | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 526 |  | 
| Yao Chen | 288c600 | 2017-12-12 13:43:18 -0800 | [diff] [blame] | 527 |     protoOutput->end(protoToken); | 
| Bookatz | ff71cad | 2018-09-20 17:17:49 -0700 | [diff] [blame] | 528 |     if (erase_data) { | 
 | 529 |         mPastBuckets.clear(); | 
 | 530 |     } | 
| yro | 2b0f886 | 2017-11-06 14:27:31 -0800 | [diff] [blame] | 531 | } | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 532 |  | 
| Yangster-mac | b142cc8 | 2018-03-30 15:22:08 -0700 | [diff] [blame] | 533 | void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) { | 
 | 534 |     int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs(); | 
| David Chen | 27785a8 | 2018-01-19 17:06:45 -0800 | [diff] [blame] | 535 |  | 
 | 536 |     if (currentBucketEndTimeNs > eventTimeNs) { | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 537 |         return; | 
 | 538 |     } | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 539 |     VLOG("flushing..........."); | 
| David Chen | 27785a8 | 2018-01-19 17:06:45 -0800 | [diff] [blame] | 540 |     int numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs; | 
| Muhammad Qureshi | 902529a | 2019-03-14 16:03:21 -0700 | [diff] [blame] | 541 |     int64_t nextBucketNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs; | 
 | 542 |     flushCurrentBucketLocked(eventTimeNs, nextBucketNs); | 
 | 543 |  | 
| Yangster-mac | e2cd6d5 | 2017-11-09 20:38:30 -0800 | [diff] [blame] | 544 |     mCurrentBucketNum += numBucketsForward; | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 545 | } | 
 | 546 |  | 
| Olivier Gaillard | 6c75ecd | 2019-02-20 09:57:33 +0000 | [diff] [blame] | 547 | void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs, | 
 | 548 |                                                       const int64_t& nextBucketStartTimeNs) { | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 549 |     for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin(); | 
 | 550 |             whatIt != mCurrentSlicedDurationTrackerMap.end();) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 551 |         if (whatIt->second->flushCurrentBucket(eventTimeNs, &mPastBuckets)) { | 
 | 552 |             VLOG("erase bucket for key %s", whatIt->first.toString().c_str()); | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 553 |             whatIt = mCurrentSlicedDurationTrackerMap.erase(whatIt); | 
| David Chen | 27785a8 | 2018-01-19 17:06:45 -0800 | [diff] [blame] | 554 |         } else { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 555 |             ++whatIt; | 
| David Chen | 27785a8 | 2018-01-19 17:06:45 -0800 | [diff] [blame] | 556 |         } | 
 | 557 |     } | 
| Olivier Gaillard | f248c0d | 2019-02-21 15:56:58 +0000 | [diff] [blame] | 558 |     StatsdStats::getInstance().noteBucketCount(mMetricId); | 
| Muhammad Qureshi | 902529a | 2019-03-14 16:03:21 -0700 | [diff] [blame] | 559 |     mCurrentBucketStartTimeNs = nextBucketStartTimeNs; | 
| David Chen | 27785a8 | 2018-01-19 17:06:45 -0800 | [diff] [blame] | 560 | } | 
 | 561 |  | 
| Yao Chen | 884c8c1 | 2018-01-26 10:36:25 -0800 | [diff] [blame] | 562 | void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { | 
| Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 563 |     if (mCurrentSlicedDurationTrackerMap.size() == 0) { | 
| Yao Chen | 884c8c1 | 2018-01-26 10:36:25 -0800 | [diff] [blame] | 564 |         return; | 
 | 565 |     } | 
 | 566 |  | 
 | 567 |     fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId, | 
| Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 568 |             (unsigned long)mCurrentSlicedDurationTrackerMap.size()); | 
| Yao Chen | 884c8c1 | 2018-01-26 10:36:25 -0800 | [diff] [blame] | 569 |     if (verbose) { | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 570 |         for (const auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 571 |             fprintf(out, "\t(what)%s\n", whatIt.first.toString().c_str()); | 
 | 572 |             whatIt.second->dumpStates(out, verbose); | 
| Yao Chen | 884c8c1 | 2018-01-26 10:36:25 -0800 | [diff] [blame] | 573 |         } | 
 | 574 |     } | 
 | 575 | } | 
 | 576 |  | 
| Yangster-mac | 9369446 | 2018-01-22 20:49:31 -0800 | [diff] [blame] | 577 | bool DurationMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) { | 
| Yangster-mac | 306ccc2 | 2018-03-24 15:03:40 -0700 | [diff] [blame] | 578 |     auto whatIt = mCurrentSlicedDurationTrackerMap.find(newKey.getDimensionKeyInWhat()); | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 579 |     if (whatIt == mCurrentSlicedDurationTrackerMap.end()) { | 
| Yangster-mac | 306ccc2 | 2018-03-24 15:03:40 -0700 | [diff] [blame] | 580 |         // 1. Report the tuple count if the tuple count > soft limit | 
 | 581 |         if (mCurrentSlicedDurationTrackerMap.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) { | 
 | 582 |             size_t newTupleCount = mCurrentSlicedDurationTrackerMap.size() + 1; | 
 | 583 |             StatsdStats::getInstance().noteMetricDimensionSize( | 
 | 584 |                     mConfigKey, mMetricId, newTupleCount); | 
 | 585 |             // 2. Don't add more tuples, we are above the allowed threshold. Drop the data. | 
 | 586 |             if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) { | 
 | 587 |                 ALOGE("DurationMetric %lld dropping data for what dimension key %s", | 
 | 588 |                     (long long)mMetricId, newKey.getDimensionKeyInWhat().toString().c_str()); | 
| Muhammad Qureshi | 87348a6 | 2019-02-14 16:17:52 -0800 | [diff] [blame] | 589 |                 StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId); | 
| Yangster-mac | 306ccc2 | 2018-03-24 15:03:40 -0700 | [diff] [blame] | 590 |                 return true; | 
 | 591 |             } | 
| Yao Chen | b356151 | 2017-11-21 18:07:17 -0800 | [diff] [blame] | 592 |         } | 
 | 593 |     } | 
 | 594 |     return false; | 
 | 595 | } | 
 | 596 |  | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 597 | void DurationMetricProducer::handleStartEvent(const MetricDimensionKey& eventKey, | 
 | 598 |                                               const ConditionKey& conditionKeys, | 
 | 599 |                                               bool condition, const LogEvent& event) { | 
 | 600 |     const auto& whatKey = eventKey.getDimensionKeyInWhat(); | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 601 |     auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatKey); | 
 | 602 |     if (whatIt == mCurrentSlicedDurationTrackerMap.end()) { | 
| Yangster | f2bee6f | 2017-11-29 12:01:05 -0800 | [diff] [blame] | 603 |         if (hitGuardRailLocked(eventKey)) { | 
| Yao Chen | b356151 | 2017-11-21 18:07:17 -0800 | [diff] [blame] | 604 |             return; | 
 | 605 |         } | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 606 |         mCurrentSlicedDurationTrackerMap[whatKey] = createDurationTracker(eventKey); | 
| Yao Chen | 6a8c799 | 2017-11-29 20:02:07 +0000 | [diff] [blame] | 607 |     } | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 608 |  | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 609 |     auto it = mCurrentSlicedDurationTrackerMap.find(whatKey); | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 610 |     if (mUseWhatDimensionAsInternalDimension) { | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 611 |         it->second->noteStart(whatKey, condition, event.GetElapsedTimestampNs(), conditionKeys); | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 612 |         return; | 
 | 613 |     } | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 614 |  | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 615 |     if (mInternalDimensions.empty()) { | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 616 |         it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, event.GetElapsedTimestampNs(), | 
 | 617 |                               conditionKeys); | 
| Yangster-mac | 2087716 | 2017-12-22 17:19:39 -0800 | [diff] [blame] | 618 |     } else { | 
| Yangster-mac | e06cfd7 | 2018-03-10 23:22:59 -0800 | [diff] [blame] | 619 |         HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY; | 
 | 620 |         filterValues(mInternalDimensions, event.getValues(), &dimensionKey); | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 621 |         it->second->noteStart(dimensionKey, condition, event.GetElapsedTimestampNs(), | 
 | 622 |                               conditionKeys); | 
| Yao Chen | 5154a379 | 2017-10-30 22:57:06 -0700 | [diff] [blame] | 623 |     } | 
| Yangster-mac | 2087716 | 2017-12-22 17:19:39 -0800 | [diff] [blame] | 624 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 625 | } | 
 | 626 |  | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 627 | void DurationMetricProducer::onMatchedLogEventInternalLocked( | 
 | 628 |         const size_t matcherIndex, const MetricDimensionKey& eventKey, | 
| tsaichristine | c876b49 | 2019-12-10 13:47:05 -0800 | [diff] [blame] | 629 |         const ConditionKey& conditionKeys, bool condition, const LogEvent& event, | 
 | 630 |         const map<int, HashableDimensionKey>& statePrimaryKeys) { | 
| Yangster-mac | 5392888 | 2018-02-25 23:02:56 -0800 | [diff] [blame] | 631 |     ALOGW("Not used in duration tracker."); | 
 | 632 | } | 
 | 633 |  | 
| Yangster-mac | e06cfd7 | 2018-03-10 23:22:59 -0800 | [diff] [blame] | 634 | void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, | 
 | 635 |                                                      const LogEvent& event) { | 
| Yangster-mac | b142cc8 | 2018-03-30 15:22:08 -0700 | [diff] [blame] | 636 |     int64_t eventTimeNs = event.GetElapsedTimestampNs(); | 
| Yangster-mac | 15f6bbc | 2018-04-08 11:52:26 -0700 | [diff] [blame] | 637 |     if (eventTimeNs < mTimeBaseNs) { | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 638 |         return; | 
 | 639 |     } | 
 | 640 |  | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 641 |     if (mIsActive) { | 
 | 642 |         flushIfNeededLocked(event.GetElapsedTimestampNs()); | 
 | 643 |     } | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 644 |  | 
 | 645 |     // Handles Stopall events. | 
| Tej Singh | cfa32e1 | 2020-10-15 03:14:19 -0700 | [diff] [blame] | 646 |     if ((int)matcherIndex == mStopAllIndex) { | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 647 |         for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 648 |             whatIt.second->noteStopAll(event.GetElapsedTimestampNs()); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 649 |         } | 
 | 650 |         return; | 
 | 651 |     } | 
 | 652 |  | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 653 |     HashableDimensionKey dimensionInWhat = DEFAULT_DIMENSION_KEY; | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 654 |     if (!mDimensionsInWhat.empty()) { | 
 | 655 |         filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 656 |     } | 
 | 657 |  | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 658 |     // Stores atom id to primary key pairs for each state atom that the metric is | 
 | 659 |     // sliced by. | 
 | 660 |     std::map<int, HashableDimensionKey> statePrimaryKeys; | 
 | 661 |  | 
 | 662 |     // For states with primary fields, use MetricStateLinks to get the primary | 
 | 663 |     // field values from the log event. These values will form a primary key | 
 | 664 |     // that will be used to query StateTracker for the correct state value. | 
 | 665 |     for (const auto& stateLink : mMetric2StateLinks) { | 
 | 666 |         getDimensionForState(event.getValues(), stateLink, | 
 | 667 |                              &statePrimaryKeys[stateLink.stateAtomId]); | 
 | 668 |     } | 
 | 669 |  | 
 | 670 |     // For each sliced state, query StateTracker for the state value using | 
 | 671 |     // either the primary key from the previous step or the DEFAULT_DIMENSION_KEY. | 
 | 672 |     // | 
 | 673 |     // Expected functionality: for any case where the MetricStateLinks are | 
 | 674 |     // initialized incorrectly (ex. # of state links != # of primary fields, no | 
 | 675 |     // links are provided for a state with primary fields, links are provided | 
 | 676 |     // in the wrong order, etc.), StateTracker will simply return kStateUnknown | 
 | 677 |     // when queried using an incorrect key. | 
 | 678 |     HashableDimensionKey stateValuesKey = DEFAULT_DIMENSION_KEY; | 
 | 679 |     for (auto atomId : mSlicedStateAtoms) { | 
 | 680 |         FieldValue value; | 
 | 681 |         if (statePrimaryKeys.find(atomId) != statePrimaryKeys.end()) { | 
 | 682 |             // found a primary key for this state, query using the key | 
 | 683 |             queryStateValue(atomId, statePrimaryKeys[atomId], &value); | 
 | 684 |         } else { | 
 | 685 |             // if no MetricStateLinks exist for this state atom, | 
 | 686 |             // query using the default dimension key (empty HashableDimensionKey) | 
 | 687 |             queryStateValue(atomId, DEFAULT_DIMENSION_KEY, &value); | 
 | 688 |         } | 
 | 689 |         mapStateValue(atomId, &value); | 
 | 690 |         stateValuesKey.addValue(value); | 
 | 691 |     } | 
 | 692 |  | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 693 |     // Handles Stop events. | 
| Tej Singh | cfa32e1 | 2020-10-15 03:14:19 -0700 | [diff] [blame] | 694 |     if ((int)matcherIndex == mStopIndex) { | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 695 |         if (mUseWhatDimensionAsInternalDimension) { | 
 | 696 |             auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat); | 
 | 697 |             if (whatIt != mCurrentSlicedDurationTrackerMap.end()) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 698 |                 whatIt->second->noteStop(dimensionInWhat, event.GetElapsedTimestampNs(), false); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 699 |             } | 
 | 700 |             return; | 
 | 701 |         } | 
 | 702 |  | 
 | 703 |         HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY; | 
 | 704 |         if (!mInternalDimensions.empty()) { | 
 | 705 |             filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey); | 
 | 706 |         } | 
 | 707 |  | 
 | 708 |         auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat); | 
 | 709 |         if (whatIt != mCurrentSlicedDurationTrackerMap.end()) { | 
| tsaichristine | 81899f1 | 2020-01-08 12:42:12 -0800 | [diff] [blame] | 710 |             whatIt->second->noteStop(internalDimensionKey, event.GetElapsedTimestampNs(), false); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 711 |         } | 
 | 712 |         return; | 
 | 713 |     } | 
 | 714 |  | 
 | 715 |     bool condition; | 
 | 716 |     ConditionKey conditionKey; | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 717 |     if (mConditionSliced) { | 
 | 718 |         for (const auto& link : mMetric2ConditionLinks) { | 
 | 719 |             getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]); | 
 | 720 |         } | 
 | 721 |  | 
 | 722 |         auto conditionState = | 
| tsaichristine | 7685337 | 2019-08-06 17:17:03 -0700 | [diff] [blame] | 723 |             mWizard->query(mConditionTrackerIndex, conditionKey, | 
 | 724 |                            !mHasLinksToAllConditionDimensionsInTracker); | 
| Olivier Gaillard | e63d9e0 | 2019-02-12 14:43:59 +0000 | [diff] [blame] | 725 |         condition = conditionState == ConditionState::kTrue; | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 726 |     } else { | 
| Olivier Gaillard | e63d9e0 | 2019-02-12 14:43:59 +0000 | [diff] [blame] | 727 |         // TODO: The unknown condition state is not handled here, we should fix it. | 
 | 728 |         condition = mCondition == ConditionState::kTrue; | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 729 |     } | 
 | 730 |  | 
| Muhammad Qureshi | 18e4692 | 2019-05-24 16:38:49 -0700 | [diff] [blame] | 731 |     condition = condition && mIsActive; | 
 | 732 |  | 
| tsaichristine | 1449fa4 | 2020-01-02 12:12:05 -0800 | [diff] [blame] | 733 |     handleStartEvent(MetricDimensionKey(dimensionInWhat, stateValuesKey), conditionKey, condition, | 
 | 734 |                      event); | 
| Yangster | 13fb7e4 | 2018-03-07 17:30:49 -0800 | [diff] [blame] | 735 | } | 
 | 736 |  | 
| Yangster | f2bee6f | 2017-11-29 12:01:05 -0800 | [diff] [blame] | 737 | size_t DurationMetricProducer::byteSizeLocked() const { | 
| Yangster | 7c334a1 | 2017-11-22 14:24:24 -0800 | [diff] [blame] | 738 |     size_t totalSize = 0; | 
 | 739 |     for (const auto& pair : mPastBuckets) { | 
 | 740 |         totalSize += pair.second.size() * kBucketSize; | 
 | 741 |     } | 
 | 742 |     return totalSize; | 
| yro | 69007c8 | 2017-10-26 20:42:57 -0700 | [diff] [blame] | 743 | } | 
 | 744 |  | 
| Yao Chen | 729093d | 2017-10-16 10:33:26 -0700 | [diff] [blame] | 745 | }  // namespace statsd | 
 | 746 | }  // namespace os | 
 | 747 | }  // namespace android |