blob: c9cc7bb9c1d4528bdc86f70987227ed89cfe40b0 [file] [log] [blame]
Chenjie Yub3dda412017-10-24 13:41:59 -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 // STOPSHIP if true
Chenjie Yub3dda412017-10-24 13:41:59 -070018#include "Log.h"
19
Yangster-maca7fb12d2018-01-03 17:17:20 -080020#include "dimension.h"
Chenjie Yub3dda412017-10-24 13:41:59 -070021#include "ValueMetricProducer.h"
Yao Chenb3561512017-11-21 18:07:17 -080022#include "guardrail/StatsdStats.h"
Yangster-mac20877162017-12-22 17:19:39 -080023#include "stats_log_util.h"
Chenjie Yub3dda412017-10-24 13:41:59 -070024
25#include <cutils/log.h>
26#include <limits.h>
27#include <stdlib.h>
28
yrob0378b02017-11-09 20:36:25 -080029using android::util::FIELD_COUNT_REPEATED;
yro2b0f8862017-11-06 14:27:31 -080030using android::util::FIELD_TYPE_BOOL;
31using android::util::FIELD_TYPE_FLOAT;
32using android::util::FIELD_TYPE_INT32;
33using android::util::FIELD_TYPE_INT64;
34using android::util::FIELD_TYPE_MESSAGE;
Yangster-macd1815dc2017-11-13 21:43:15 -080035using android::util::FIELD_TYPE_STRING;
yro2b0f8862017-11-06 14:27:31 -080036using android::util::ProtoOutputStream;
Chenjie Yub3dda412017-10-24 13:41:59 -070037using std::list;
Chenjie Yu6736c892017-11-09 10:50:09 -080038using std::make_pair;
Chenjie Yub3dda412017-10-24 13:41:59 -070039using std::make_shared;
Yao Chen93fe3a32017-11-02 13:52:59 -070040using std::map;
Chenjie Yub3dda412017-10-24 13:41:59 -070041using std::shared_ptr;
42using std::unique_ptr;
Yao Chen93fe3a32017-11-02 13:52:59 -070043using std::unordered_map;
Chenjie Yub3dda412017-10-24 13:41:59 -070044
45namespace android {
46namespace os {
47namespace statsd {
48
yro2b0f8862017-11-06 14:27:31 -080049// for StatsLogReport
Yangster-mac94e197c2018-01-02 16:03:03 -080050const int FIELD_ID_ID = 1;
yro2b0f8862017-11-06 14:27:31 -080051const int FIELD_ID_START_REPORT_NANOS = 2;
52const int FIELD_ID_END_REPORT_NANOS = 3;
53const int FIELD_ID_VALUE_METRICS = 7;
54// for ValueMetricDataWrapper
55const int FIELD_ID_DATA = 1;
56// for ValueMetricData
Yangster-mac468ff042018-01-17 12:26:34 -080057const int FIELD_ID_DIMENSION_IN_WHAT = 1;
58const int FIELD_ID_DIMENSION_IN_CONDITION = 2;
59const int FIELD_ID_BUCKET_INFO = 3;
yro2b0f8862017-11-06 14:27:31 -080060// for ValueBucketInfo
61const int FIELD_ID_START_BUCKET_NANOS = 1;
62const int FIELD_ID_END_BUCKET_NANOS = 2;
63const int FIELD_ID_VALUE = 3;
64
Chenjie Yub3dda412017-10-24 13:41:59 -070065// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
Yao Chenb3561512017-11-21 18:07:17 -080066ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
67 const int conditionIndex,
Yao Chen93fe3a32017-11-02 13:52:59 -070068 const sp<ConditionWizard>& wizard, const int pullTagId,
Chenjie Yu6736c892017-11-09 10:50:09 -080069 const uint64_t startTimeNs,
70 shared_ptr<StatsPullerManager> statsPullerManager)
Yangster-mac94e197c2018-01-02 16:03:03 -080071 : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
Yao Chenf09569f2017-12-13 17:00:51 -080072 mValueField(metric.value_field()),
Chenjie Yu6736c892017-11-09 10:50:09 -080073 mStatsPullerManager(statsPullerManager),
74 mPullTagId(pullTagId) {
Yao Chen93fe3a32017-11-02 13:52:59 -070075 // TODO: valuemetric for pushed events may need unlimited bucket length
Yangster-macb8144812018-01-04 10:56:23 -080076 int64_t bucketSizeMills = 0;
77 if (metric.has_bucket()) {
78 bucketSizeMills = TimeUnitToBucketSizeInMillis(metric.bucket());
Chenjie Yu6736c892017-11-09 10:50:09 -080079 } else {
Yangster-macb8144812018-01-04 10:56:23 -080080 bucketSizeMills = TimeUnitToBucketSizeInMillis(ONE_HOUR);
Chenjie Yu6736c892017-11-09 10:50:09 -080081 }
Chenjie Yub3dda412017-10-24 13:41:59 -070082
Yangster-macb8144812018-01-04 10:56:23 -080083 mBucketSizeNs = bucketSizeMills * 1000000;
Yangster-mac93694462018-01-22 20:49:31 -080084 mDimensionsInWhat = metric.dimensions_in_what();
85 mDimensionsInCondition = metric.dimensions_in_condition();
Chenjie Yub3dda412017-10-24 13:41:59 -070086
Yao Chen93fe3a32017-11-02 13:52:59 -070087 if (metric.links().size() > 0) {
88 mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
89 metric.links().end());
Yao Chen93fe3a32017-11-02 13:52:59 -070090 }
Yangster-mac93694462018-01-22 20:49:31 -080091 mConditionSliced = (metric.links().size() > 0)||
92 (mDimensionsInCondition.has_field() && mDimensionsInCondition.child_size() > 0);
Chenjie Yub3dda412017-10-24 13:41:59 -070093
Yao Chen93fe3a32017-11-02 13:52:59 -070094 if (!metric.has_condition() && mPullTagId != -1) {
Chenjie Yu6736c892017-11-09 10:50:09 -080095 VLOG("Setting up periodic pulling for %d", mPullTagId);
Yangster-macb8144812018-01-04 10:56:23 -080096 mStatsPullerManager->RegisterReceiver(mPullTagId, this, bucketSizeMills);
Yao Chen93fe3a32017-11-02 13:52:59 -070097 }
Yangster-mac94e197c2018-01-02 16:03:03 -080098 VLOG("value metric %lld created. bucket size %lld start_time: %lld",
99 (long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs);
Chenjie Yub3dda412017-10-24 13:41:59 -0700100}
101
Chenjie Yu6736c892017-11-09 10:50:09 -0800102// for testing
Yao Chenb3561512017-11-21 18:07:17 -0800103ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
104 const int conditionIndex,
Chenjie Yu6736c892017-11-09 10:50:09 -0800105 const sp<ConditionWizard>& wizard, const int pullTagId,
106 const uint64_t startTimeNs)
Yao Chenb3561512017-11-21 18:07:17 -0800107 : ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId, startTimeNs,
Chenjie Yu6736c892017-11-09 10:50:09 -0800108 make_shared<StatsPullerManager>()) {
109}
110
Chenjie Yub3dda412017-10-24 13:41:59 -0700111ValueMetricProducer::~ValueMetricProducer() {
Yao Chen93fe3a32017-11-02 13:52:59 -0700112 VLOG("~ValueMetricProducer() called");
Chenjie Yu6736c892017-11-09 10:50:09 -0800113 if (mPullTagId != -1) {
114 mStatsPullerManager->UnRegisterReceiver(mPullTagId, this);
115 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700116}
117
Yangsterf2bee6f2017-11-29 12:01:05 -0800118void ValueMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800119 VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
Chenjie Yub3dda412017-10-24 13:41:59 -0700120}
121
Yangster-mac20877162017-12-22 17:19:39 -0800122void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
123 flushIfNeededLocked(dumpTimeNs);
Yangster-mac94e197c2018-01-02 16:03:03 -0800124 report->set_metric_id(mMetricId);
Yangster-mac20877162017-12-22 17:19:39 -0800125 report->set_start_report_nanos(mStartTimeNs);
126 auto value_metrics = report->mutable_value_metrics();
127 for (const auto& pair : mPastBuckets) {
128 ValueMetricData* metricData = value_metrics->add_data();
Yangster-mac93694462018-01-22 20:49:31 -0800129 *metricData->mutable_dimensions_in_what() =
130 pair.first.getDimensionKeyInWhat().getDimensionsValue();
131 *metricData->mutable_dimensions_in_condition() =
132 pair.first.getDimensionKeyInCondition().getDimensionsValue();
Yangster-mac20877162017-12-22 17:19:39 -0800133 for (const auto& bucket : pair.second) {
134 ValueBucketInfo* bucketInfo = metricData->add_bucket_info();
135 bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
136 bucketInfo->set_end_bucket_nanos(bucket.mBucketEndNs);
137 bucketInfo->set_value(bucket.mValue);
138 }
139 }
140}
141
Yao Chen288c6002017-12-12 13:43:18 -0800142void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
143 ProtoOutputStream* protoOutput) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800144 VLOG("metric %lld dump report now...", (long long)mMetricId);
Yao Chen288c6002017-12-12 13:43:18 -0800145 flushIfNeededLocked(dumpTimeNs);
Yangster-mac635b4b32018-01-23 20:17:35 -0800146 if (mPastBuckets.empty()) {
147 return;
148 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800149 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
Yao Chen288c6002017-12-12 13:43:18 -0800150 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
151 long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS);
Yao Chen6a8c7992017-11-29 20:02:07 +0000152
Yao Chen93fe3a32017-11-02 13:52:59 -0700153 for (const auto& pair : mPastBuckets) {
Yangster-mac93694462018-01-22 20:49:31 -0800154 const MetricDimensionKey& dimensionKey = pair.first;
155 VLOG(" dimension key %s", dimensionKey.c_str());
yrob0378b02017-11-09 20:36:25 -0800156 long long wrapperToken =
Yao Chen288c6002017-12-12 13:43:18 -0800157 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
Chenjie Yub3dda412017-10-24 13:41:59 -0700158
Yangster-mac20877162017-12-22 17:19:39 -0800159 // First fill dimension.
160 long long dimensionToken = protoOutput->start(
Yangster-mac468ff042018-01-17 12:26:34 -0800161 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
Yangster-mac93694462018-01-22 20:49:31 -0800162 writeDimensionsValueProtoToStream(
163 dimensionKey.getDimensionKeyInWhat().getDimensionsValue(), protoOutput);
Yangster-mac20877162017-12-22 17:19:39 -0800164 protoOutput->end(dimensionToken);
Yangster-mac93694462018-01-22 20:49:31 -0800165 if (dimensionKey.hasDimensionKeyInCondition()) {
166 long long dimensionInConditionToken = protoOutput->start(
167 FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
168 writeDimensionsValueProtoToStream(
169 dimensionKey.getDimensionKeyInCondition().getDimensionsValue(), protoOutput);
170 protoOutput->end(dimensionInConditionToken);
171 }
yro2b0f8862017-11-06 14:27:31 -0800172
173 // Then fill bucket_info (ValueBucketInfo).
174 for (const auto& bucket : pair.second) {
Yao Chen288c6002017-12-12 13:43:18 -0800175 long long bucketInfoToken = protoOutput->start(
176 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
177 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
178 (long long)bucket.mBucketStartNs);
179 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
180 (long long)bucket.mBucketEndNs);
181 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE, (long long)bucket.mValue);
182 protoOutput->end(bucketInfoToken);
yro2b0f8862017-11-06 14:27:31 -0800183 VLOG("\t bucket [%lld - %lld] count: %lld", (long long)bucket.mBucketStartNs,
184 (long long)bucket.mBucketEndNs, (long long)bucket.mValue);
185 }
Yao Chen288c6002017-12-12 13:43:18 -0800186 protoOutput->end(wrapperToken);
Chenjie Yub3dda412017-10-24 13:41:59 -0700187 }
Yao Chen288c6002017-12-12 13:43:18 -0800188 protoOutput->end(protoToken);
189 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
yro2b0f8862017-11-06 14:27:31 -0800190
Yangster-mac94e197c2018-01-02 16:03:03 -0800191 VLOG("metric %lld dump report now...", (long long)mMetricId);
Yao Chen6a8c7992017-11-29 20:02:07 +0000192 mPastBuckets.clear();
Yao Chen288c6002017-12-12 13:43:18 -0800193 mStartTimeNs = mCurrentBucketStartTimeNs;
yro2b0f8862017-11-06 14:27:31 -0800194 // TODO: Clear mDimensionKeyMap once the report is dumped.
Chenjie Yub3dda412017-10-24 13:41:59 -0700195}
196
Yangsterf2bee6f2017-11-29 12:01:05 -0800197void ValueMetricProducer::onConditionChangedLocked(const bool condition, const uint64_t eventTime) {
Yao Chen6a8c7992017-11-29 20:02:07 +0000198 mCondition = condition;
Chenjie Yub3dda412017-10-24 13:41:59 -0700199
Yao Chen2794da22017-12-13 16:01:55 -0800200 if (eventTime < mCurrentBucketStartTimeNs) {
Chenjie Yua7259ab2017-12-10 08:31:05 -0800201 VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTime,
202 (long long)mCurrentBucketStartTimeNs);
Yao Chen2794da22017-12-13 16:01:55 -0800203 return;
204 }
205
Chenjie Yua7259ab2017-12-10 08:31:05 -0800206 flushIfNeededLocked(eventTime);
207
Yao Chen6a8c7992017-11-29 20:02:07 +0000208 if (mPullTagId != -1) {
Chenjie Yub3dda412017-10-24 13:41:59 -0700209 if (mCondition == true) {
Yao Chenf09569f2017-12-13 17:00:51 -0800210 mStatsPullerManager->RegisterReceiver(mPullTagId, this, mBucketSizeNs / 1000 / 1000);
Chenjie Yu6736c892017-11-09 10:50:09 -0800211 } else if (mCondition == false) {
212 mStatsPullerManager->UnRegisterReceiver(mPullTagId, this);
Chenjie Yub3dda412017-10-24 13:41:59 -0700213 }
Yangster8de69392017-11-27 13:48:29 -0800214
Yao Chen6a8c7992017-11-29 20:02:07 +0000215 vector<shared_ptr<LogEvent>> allData;
216 if (mStatsPullerManager->Pull(mPullTagId, &allData)) {
217 if (allData.size() == 0) {
218 return;
219 }
220 for (const auto& data : allData) {
Chenjie Yua7259ab2017-12-10 08:31:05 -0800221 onMatchedLogEventLocked(0, *data);
Yao Chen6a8c7992017-11-29 20:02:07 +0000222 }
Yao Chen6a8c7992017-11-29 20:02:07 +0000223 }
Chenjie Yu5305e1d2017-10-31 13:49:36 -0700224 return;
Chenjie Yub3dda412017-10-24 13:41:59 -0700225 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700226}
227
228void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
Yangsterf2bee6f2017-11-29 12:01:05 -0800229 std::lock_guard<std::mutex> lock(mMutex);
230
Yao Chenf09569f2017-12-13 17:00:51 -0800231 if (mCondition == true || mConditionTrackerIndex < 0) {
Chenjie Yub3dda412017-10-24 13:41:59 -0700232 if (allData.size() == 0) {
233 return;
234 }
Chenjie Yua7259ab2017-12-10 08:31:05 -0800235 // For scheduled pulled data, the effective event time is snap to the nearest
236 // bucket boundary to make bucket finalize.
237 uint64_t realEventTime = allData.at(0)->GetTimestampNs();
Yangster-maca7fb12d2018-01-03 17:17:20 -0800238 uint64_t eventTime = mStartTimeNs +
239 ((realEventTime - mStartTimeNs)/mBucketSizeNs) * mBucketSizeNs;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800240
241 mCondition = false;
Chenjie Yub3dda412017-10-24 13:41:59 -0700242 for (const auto& data : allData) {
Chenjie Yua7259ab2017-12-10 08:31:05 -0800243 data->setTimestampNs(eventTime-1);
244 onMatchedLogEventLocked(0, *data);
Chenjie Yub3dda412017-10-24 13:41:59 -0700245 }
Chenjie Yua7259ab2017-12-10 08:31:05 -0800246
247 mCondition = true;
248 for (const auto& data : allData) {
249 data->setTimestampNs(eventTime);
250 onMatchedLogEventLocked(0, *data);
251 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700252 }
253}
254
Yangster-mac93694462018-01-22 20:49:31 -0800255bool ValueMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
Yao Chenb3561512017-11-21 18:07:17 -0800256 // ===========GuardRail==============
257 // 1. Report the tuple count if the tuple count > soft limit
258 if (mCurrentSlicedBucket.find(newKey) != mCurrentSlicedBucket.end()) {
259 return false;
260 }
261 if (mCurrentSlicedBucket.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
262 size_t newTupleCount = mCurrentSlicedBucket.size() + 1;
Yangster-mac94e197c2018-01-02 16:03:03 -0800263 StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
Yao Chenb3561512017-11-21 18:07:17 -0800264 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
265 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
Yangster-mac94e197c2018-01-02 16:03:03 -0800266 ALOGE("ValueMetric %lld dropping data for dimension key %s",
267 (long long)mMetricId, newKey.c_str());
Yao Chenb3561512017-11-21 18:07:17 -0800268 return true;
269 }
270 }
271
272 return false;
273}
274
Yangsterf2bee6f2017-11-29 12:01:05 -0800275void ValueMetricProducer::onMatchedLogEventInternalLocked(
Yangster-mac93694462018-01-22 20:49:31 -0800276 const size_t matcherIndex, const MetricDimensionKey& eventKey,
Yangster-mac20877162017-12-22 17:19:39 -0800277 const ConditionKey& conditionKey, bool condition,
Chenjie Yua7259ab2017-12-10 08:31:05 -0800278 const LogEvent& event) {
Yangster8de69392017-11-27 13:48:29 -0800279 uint64_t eventTimeNs = event.GetTimestampNs();
Yao Chen6a8c7992017-11-29 20:02:07 +0000280 if (eventTimeNs < mCurrentBucketStartTimeNs) {
281 VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
282 (long long)mCurrentBucketStartTimeNs);
283 return;
284 }
285
Chenjie Yua7259ab2017-12-10 08:31:05 -0800286 flushIfNeededLocked(eventTimeNs);
287
Yangsterf2bee6f2017-11-29 12:01:05 -0800288 if (hitGuardRailLocked(eventKey)) {
Yangster8de69392017-11-27 13:48:29 -0800289 return;
290 }
Yao Chen6a8c7992017-11-29 20:02:07 +0000291 Interval& interval = mCurrentSlicedBucket[eventKey];
292
Yangster-maca7fb12d2018-01-03 17:17:20 -0800293 std::shared_ptr<FieldValueMap> valueFieldMap = getValueFields(event);
294 if (valueFieldMap->empty() || valueFieldMap->size() > 1) {
295 return;
296 }
297 const long value = getLongFromDimenValue(valueFieldMap->begin()->second);
Yao Chen6a8c7992017-11-29 20:02:07 +0000298
Chenjie Yua7259ab2017-12-10 08:31:05 -0800299 if (mPullTagId != -1) { // for pulled events
300 if (mCondition == true) {
301 interval.start = value;
302 interval.startUpdated = true;
Yao Chen6a8c7992017-11-29 20:02:07 +0000303 } else {
Chenjie Yu0ed268b2018-01-10 09:37:10 -0800304 // Generally we expect value to be monotonically increasing.
305 // If not, there was a reset event. We take the absolute value as
306 // diff in this case.
Chenjie Yua7259ab2017-12-10 08:31:05 -0800307 if (interval.startUpdated) {
Chenjie Yu0ed268b2018-01-10 09:37:10 -0800308 if (value > interval.start) {
309 interval.sum += (value - interval.start);
310 } else {
311 interval.sum += value;
312 }
Chenjie Yua7259ab2017-12-10 08:31:05 -0800313 interval.startUpdated = false;
Yao Chen6a8c7992017-11-29 20:02:07 +0000314 } else {
Chenjie Yua7259ab2017-12-10 08:31:05 -0800315 VLOG("No start for matching end %ld", value);
316 interval.tainted += 1;
Yao Chen6a8c7992017-11-29 20:02:07 +0000317 }
318 }
Chenjie Yua7259ab2017-12-10 08:31:05 -0800319 } else { // for pushed events
320 interval.sum += value;
Yangster8de69392017-11-27 13:48:29 -0800321 }
Bookatzde1b55622017-12-14 18:38:27 -0800322
323 for (auto& tracker : mAnomalyTrackers) {
324 tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey, interval.sum);
325 }
Yangster8de69392017-11-27 13:48:29 -0800326}
327
Yangster-maca7fb12d2018-01-03 17:17:20 -0800328std::shared_ptr<FieldValueMap> ValueMetricProducer::getValueFields(const LogEvent& event) {
329 std::shared_ptr<FieldValueMap> valueFields =
330 std::make_shared<FieldValueMap>(event.getFieldValueMap());
331 filterFields(mValueField, valueFields.get());
332 return valueFields;
Chenjie Yub3dda412017-10-24 13:41:59 -0700333}
334
Yangsterf2bee6f2017-11-29 12:01:05 -0800335void ValueMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
Chenjie Yub3dda412017-10-24 13:41:59 -0700336 if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTimeNs) {
337 VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
338 (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
339 return;
340 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700341 VLOG("finalizing bucket for %ld, dumping %d slices", (long)mCurrentBucketStartTimeNs,
342 (int)mCurrentSlicedBucket.size());
yro2b0f8862017-11-06 14:27:31 -0800343 ValueBucket info;
344 info.mBucketStartNs = mCurrentBucketStartTimeNs;
345 info.mBucketEndNs = mCurrentBucketStartTimeNs + mBucketSizeNs;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800346 info.mBucketNum = mCurrentBucketNum;
Chenjie Yub3dda412017-10-24 13:41:59 -0700347
Chenjie Yu6736c892017-11-09 10:50:09 -0800348 int tainted = 0;
Chenjie Yub3dda412017-10-24 13:41:59 -0700349 for (const auto& slice : mCurrentSlicedBucket) {
Chenjie Yu6736c892017-11-09 10:50:09 -0800350 tainted += slice.second.tainted;
Chenjie Yua7259ab2017-12-10 08:31:05 -0800351 info.mValue = slice.second.sum;
Yao Chen93fe3a32017-11-02 13:52:59 -0700352 // it will auto create new vector of ValuebucketInfo if the key is not found.
353 auto& bucketList = mPastBuckets[slice.first];
354 bucketList.push_back(info);
Bookatzde1b55622017-12-14 18:38:27 -0800355
356 for (auto& tracker : mAnomalyTrackers) {
357 if (tracker != nullptr) {
358 tracker->addPastBucket(slice.first, info.mValue, info.mBucketNum);
359 }
360 }
Chenjie Yub3dda412017-10-24 13:41:59 -0700361 }
Chenjie Yua7259ab2017-12-10 08:31:05 -0800362 VLOG("%d tainted pairs in the bucket", tainted);
Chenjie Yub3dda412017-10-24 13:41:59 -0700363
364 // Reset counters
Chenjie Yua7259ab2017-12-10 08:31:05 -0800365 mCurrentSlicedBucket.clear();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800366
Chenjie Yub3dda412017-10-24 13:41:59 -0700367 int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800368 mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
369 mCurrentBucketNum += numBucketsForward;
370
Yao Chen93fe3a32017-11-02 13:52:59 -0700371 if (numBucketsForward > 1) {
Chenjie Yub3dda412017-10-24 13:41:59 -0700372 VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
373 }
Yangster-mac94e197c2018-01-02 16:03:03 -0800374 VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
Chenjie Yub3dda412017-10-24 13:41:59 -0700375 (long long)mCurrentBucketStartTimeNs);
376}
377
Yangsterf2bee6f2017-11-29 12:01:05 -0800378size_t ValueMetricProducer::byteSizeLocked() const {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800379 size_t totalSize = 0;
380 for (const auto& pair : mPastBuckets) {
381 totalSize += pair.second.size() * kBucketSize;
382 }
383 return totalSize;
yro2b0f8862017-11-06 14:27:31 -0800384}
385
Chenjie Yub3dda412017-10-24 13:41:59 -0700386} // namespace statsd
387} // namespace os
Yao Chen93fe3a32017-11-02 13:52:59 -0700388} // namespace android