blob: 51fd9fcb335b07449fe1eda83f0969a2a694b82e [file] [log] [blame]
Yangster1d4d6862017-10-31 12:58:51 -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
Yangster1d4d6862017-10-31 12:58:51 -070018#include "Log.h"
19
20#include "GaugeMetricProducer.h"
Yao Chenb3561512017-11-21 18:07:17 -080021#include "guardrail/StatsdStats.h"
Yangster-mac20877162017-12-22 17:19:39 -080022#include "dimension.h"
23#include "stats_log_util.h"
Yangster1d4d6862017-10-31 12:58:51 -070024
25#include <cutils/log.h>
Yangster1d4d6862017-10-31 12:58:51 -070026
yrob0378b02017-11-09 20:36:25 -080027using android::util::FIELD_COUNT_REPEATED;
yro2b0f8862017-11-06 14:27:31 -080028using android::util::FIELD_TYPE_BOOL;
29using android::util::FIELD_TYPE_FLOAT;
30using android::util::FIELD_TYPE_INT32;
31using android::util::FIELD_TYPE_INT64;
32using android::util::FIELD_TYPE_MESSAGE;
Yangster-macd1815dc2017-11-13 21:43:15 -080033using android::util::FIELD_TYPE_STRING;
yro2b0f8862017-11-06 14:27:31 -080034using android::util::ProtoOutputStream;
Yangster1d4d6862017-10-31 12:58:51 -070035using std::map;
36using std::string;
37using std::unordered_map;
38using std::vector;
Chenjie Yud9dfda72017-12-11 17:41:20 -080039using std::make_shared;
40using std::shared_ptr;
Yangster1d4d6862017-10-31 12:58:51 -070041
42namespace android {
43namespace os {
44namespace statsd {
45
yro2b0f8862017-11-06 14:27:31 -080046// for StatsLogReport
Yangster-macd1815dc2017-11-13 21:43:15 -080047const int FIELD_ID_NAME = 1;
yro2b0f8862017-11-06 14:27:31 -080048const int FIELD_ID_START_REPORT_NANOS = 2;
49const int FIELD_ID_END_REPORT_NANOS = 3;
50const int FIELD_ID_GAUGE_METRICS = 8;
51// for GaugeMetricDataWrapper
52const int FIELD_ID_DATA = 1;
53// for GaugeMetricData
54const int FIELD_ID_DIMENSION = 1;
55const int FIELD_ID_BUCKET_INFO = 2;
yro2b0f8862017-11-06 14:27:31 -080056// for GaugeBucketInfo
57const int FIELD_ID_START_BUCKET_NANOS = 1;
58const int FIELD_ID_END_BUCKET_NANOS = 2;
Chenjie Yud9dfda72017-12-11 17:41:20 -080059const int FIELD_ID_ATOM = 3;
yro2b0f8862017-11-06 14:27:31 -080060
Yao Chenb3561512017-11-21 18:07:17 -080061GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
62 const int conditionIndex,
Chenjie Yud9dfda72017-12-11 17:41:20 -080063 const sp<ConditionWizard>& wizard, const int atomTagId,
64 const int pullTagId, const uint64_t startTimeNs,
65 shared_ptr<StatsPullerManager> statsPullerManager)
Yao Chenf09569f2017-12-13 17:00:51 -080066 : MetricProducer(metric.name(), key, startTimeNs, conditionIndex, wizard),
Chenjie Yud9dfda72017-12-11 17:41:20 -080067 mStatsPullerManager(statsPullerManager),
68 mPullTagId(pullTagId),
69 mAtomTagId(atomTagId) {
Yangster-mac20877162017-12-22 17:19:39 -080070 mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>();
71 mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
Yangster1d4d6862017-10-31 12:58:51 -070072 if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
73 mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000 * 1000;
74 } else {
75 mBucketSizeNs = kDefaultGaugemBucketSizeNs;
76 }
77
Yangster-mac20877162017-12-22 17:19:39 -080078 mFieldFilter = metric.gauge_fields_filter();
Chenjie Yud9dfda72017-12-11 17:41:20 -080079
Yangster1d4d6862017-10-31 12:58:51 -070080 // TODO: use UidMap if uid->pkg_name is required
Yangster-mac20877162017-12-22 17:19:39 -080081 mDimensions = metric.dimensions();
Yangster1d4d6862017-10-31 12:58:51 -070082
83 if (metric.links().size() > 0) {
84 mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
85 metric.links().end());
86 mConditionSliced = true;
87 }
88
89 // Kicks off the puller immediately.
90 if (mPullTagId != -1) {
Chenjie Yud9dfda72017-12-11 17:41:20 -080091 mStatsPullerManager->RegisterReceiver(mPullTagId, this,
Yangster-mac20877162017-12-22 17:19:39 -080092 metric.bucket().bucket_size_millis());
Yangster1d4d6862017-10-31 12:58:51 -070093 }
94
Yangster-macd1815dc2017-11-13 21:43:15 -080095 VLOG("metric %s created. bucket size %lld start_time: %lld", metric.name().c_str(),
Yangster1d4d6862017-10-31 12:58:51 -070096 (long long)mBucketSizeNs, (long long)mStartTimeNs);
97}
98
Chenjie Yud9dfda72017-12-11 17:41:20 -080099// for testing
100GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
101 const int conditionIndex,
102 const sp<ConditionWizard>& wizard, const int pullTagId,
103 const int atomTagId, const int64_t startTimeNs)
104 : GaugeMetricProducer(key, metric, conditionIndex, wizard, pullTagId, atomTagId, startTimeNs,
105 make_shared<StatsPullerManager>()) {
106}
107
Yangster1d4d6862017-10-31 12:58:51 -0700108GaugeMetricProducer::~GaugeMetricProducer() {
109 VLOG("~GaugeMetricProducer() called");
Chenjie Yu032fefc2017-12-01 23:30:59 -0800110 if (mPullTagId != -1) {
Chenjie Yud9dfda72017-12-11 17:41:20 -0800111 mStatsPullerManager->UnRegisterReceiver(mPullTagId, this);
Chenjie Yu032fefc2017-12-01 23:30:59 -0800112 }
Yangster1d4d6862017-10-31 12:58:51 -0700113}
114
Yangster-mac20877162017-12-22 17:19:39 -0800115void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
116 flushIfNeededLocked(dumpTimeNs);
117}
118
Yao Chen288c6002017-12-12 13:43:18 -0800119void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
120 ProtoOutputStream* protoOutput) {
Yao Chenf09569f2017-12-13 17:00:51 -0800121 VLOG("gauge metric %s dump report now...", mName.c_str());
Yao Chen6a8c7992017-11-29 20:02:07 +0000122
Yao Chen288c6002017-12-12 13:43:18 -0800123 flushIfNeededLocked(dumpTimeNs);
124
Yao Chenf09569f2017-12-13 17:00:51 -0800125 protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mName);
Yao Chen288c6002017-12-12 13:43:18 -0800126 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
127 long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS);
Yao Chen6a8c7992017-11-29 20:02:07 +0000128
Yangster1d4d6862017-10-31 12:58:51 -0700129 for (const auto& pair : mPastBuckets) {
130 const HashableDimensionKey& hashableKey = pair.first;
Yangster1d4d6862017-10-31 12:58:51 -0700131
132 VLOG(" dimension key %s", hashableKey.c_str());
yrob0378b02017-11-09 20:36:25 -0800133 long long wrapperToken =
Yao Chen288c6002017-12-12 13:43:18 -0800134 protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
yro2b0f8862017-11-06 14:27:31 -0800135
Yangster-mac20877162017-12-22 17:19:39 -0800136 // First fill dimension.
137 long long dimensionToken = protoOutput->start(
138 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
139 writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput);
140 protoOutput->end(dimensionToken);
yro2b0f8862017-11-06 14:27:31 -0800141
142 // Then fill bucket_info (GaugeBucketInfo).
143 for (const auto& bucket : pair.second) {
Yao Chen288c6002017-12-12 13:43:18 -0800144 long long bucketInfoToken = protoOutput->start(
145 FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
146 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
147 (long long)bucket.mBucketStartNs);
148 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
149 (long long)bucket.mBucketEndNs);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800150 long long atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM);
Yangster-mac20877162017-12-22 17:19:39 -0800151 writeFieldValueTreeToStream(*bucket.mGaugeFields, protoOutput);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800152 protoOutput->end(atomToken);
Yao Chen288c6002017-12-12 13:43:18 -0800153 protoOutput->end(bucketInfoToken);
Yangster-mac20877162017-12-22 17:19:39 -0800154 VLOG("\t bucket [%lld - %lld] includes %d gauge fields.", (long long)bucket.mBucketStartNs,
155 (long long)bucket.mBucketEndNs, (int)bucket.mGaugeFields->size());
yro2b0f8862017-11-06 14:27:31 -0800156 }
Yao Chen288c6002017-12-12 13:43:18 -0800157 protoOutput->end(wrapperToken);
Yangster1d4d6862017-10-31 12:58:51 -0700158 }
Yao Chen288c6002017-12-12 13:43:18 -0800159 protoOutput->end(protoToken);
160 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
yro2b0f8862017-11-06 14:27:31 -0800161
Yao Chen6a8c7992017-11-29 20:02:07 +0000162 mPastBuckets.clear();
Yao Chen288c6002017-12-12 13:43:18 -0800163 mStartTimeNs = mCurrentBucketStartTimeNs;
yro2b0f8862017-11-06 14:27:31 -0800164 // TODO: Clear mDimensionKeyMap once the report is dumped.
Yangster1d4d6862017-10-31 12:58:51 -0700165}
166
Yangsterf2bee6f2017-11-29 12:01:05 -0800167void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
168 const uint64_t eventTime) {
Yao Chenf09569f2017-12-13 17:00:51 -0800169 VLOG("Metric %s onConditionChanged", mName.c_str());
Yangsterf2bee6f2017-11-29 12:01:05 -0800170 flushIfNeededLocked(eventTime);
Yao Chen6a8c7992017-11-29 20:02:07 +0000171 mCondition = conditionMet;
Yangster8de69392017-11-27 13:48:29 -0800172
Yao Chen6a8c7992017-11-29 20:02:07 +0000173 // Push mode. No need to proactively pull the gauge data.
174 if (mPullTagId == -1) {
175 return;
Yangster1d4d6862017-10-31 12:58:51 -0700176 }
Chenjie Yud9dfda72017-12-11 17:41:20 -0800177 // No need to pull again. Either scheduled pull or condition on true happened
Yao Chen6a8c7992017-11-29 20:02:07 +0000178 if (!mCondition) {
179 return;
180 }
181 // Already have gauge metric for the current bucket, do not do it again.
182 if (mCurrentSlicedBucket->size() > 0) {
183 return;
184 }
185 vector<std::shared_ptr<LogEvent>> allData;
Chenjie Yud9dfda72017-12-11 17:41:20 -0800186 if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
Yao Chen6a8c7992017-11-29 20:02:07 +0000187 ALOGE("Stats puller failed for tag: %d", mPullTagId);
188 return;
189 }
Yangster1d4d6862017-10-31 12:58:51 -0700190 for (const auto& data : allData) {
Chenjie Yua7259ab2017-12-10 08:31:05 -0800191 onMatchedLogEventLocked(0, *data);
Yangster1d4d6862017-10-31 12:58:51 -0700192 }
Yangsterf2bee6f2017-11-29 12:01:05 -0800193 flushIfNeededLocked(eventTime);
Yangster1d4d6862017-10-31 12:58:51 -0700194}
195
Yangsterf2bee6f2017-11-29 12:01:05 -0800196void GaugeMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
Yao Chenf09569f2017-12-13 17:00:51 -0800197 VLOG("Metric %s onSlicedConditionMayChange", mName.c_str());
Yangster1d4d6862017-10-31 12:58:51 -0700198}
199
Yangster-mac20877162017-12-22 17:19:39 -0800200std::shared_ptr<FieldValueMap> GaugeMetricProducer::getGaugeFields(const LogEvent& event) {
201 std::shared_ptr<FieldValueMap> gaugeFields =
202 std::make_shared<FieldValueMap>(event.getFieldValueMap());
203 if (!mFieldFilter.include_all()) {
204 filterFields(mFieldFilter.fields(), gaugeFields.get());
Yangster1d4d6862017-10-31 12:58:51 -0700205 }
Yangster-mac20877162017-12-22 17:19:39 -0800206 return gaugeFields;
Yangster1d4d6862017-10-31 12:58:51 -0700207}
208
209void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
Yangsterf2bee6f2017-11-29 12:01:05 -0800210 std::lock_guard<std::mutex> lock(mMutex);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800211 if (allData.size() == 0) {
212 return;
213 }
Yangster1d4d6862017-10-31 12:58:51 -0700214 for (const auto& data : allData) {
Chenjie Yua7259ab2017-12-10 08:31:05 -0800215 onMatchedLogEventLocked(0, *data);
Yangster1d4d6862017-10-31 12:58:51 -0700216 }
Yangster1d4d6862017-10-31 12:58:51 -0700217}
218
Yangsterf2bee6f2017-11-29 12:01:05 -0800219bool GaugeMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) {
Yao Chenb3561512017-11-21 18:07:17 -0800220 if (mCurrentSlicedBucket->find(newKey) != mCurrentSlicedBucket->end()) {
221 return false;
222 }
223 // 1. Report the tuple count if the tuple count > soft limit
224 if (mCurrentSlicedBucket->size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
225 size_t newTupleCount = mCurrentSlicedBucket->size() + 1;
Yao Chenf09569f2017-12-13 17:00:51 -0800226 StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mName, newTupleCount);
Yao Chenb3561512017-11-21 18:07:17 -0800227 // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
228 if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
Yao Chenf09569f2017-12-13 17:00:51 -0800229 ALOGE("GaugeMetric %s dropping data for dimension key %s", mName.c_str(),
Yao Chenb3561512017-11-21 18:07:17 -0800230 newKey.c_str());
231 return true;
232 }
233 }
234
235 return false;
236}
237
Yangsterf2bee6f2017-11-29 12:01:05 -0800238void GaugeMetricProducer::onMatchedLogEventInternalLocked(
Yangster1d4d6862017-10-31 12:58:51 -0700239 const size_t matcherIndex, const HashableDimensionKey& eventKey,
Yangster-mac20877162017-12-22 17:19:39 -0800240 const ConditionKey& conditionKey, bool condition,
Chenjie Yua7259ab2017-12-10 08:31:05 -0800241 const LogEvent& event) {
Yangster1d4d6862017-10-31 12:58:51 -0700242 if (condition == false) {
243 return;
244 }
Yao Chen6a8c7992017-11-29 20:02:07 +0000245 uint64_t eventTimeNs = event.GetTimestampNs();
Yangster1d4d6862017-10-31 12:58:51 -0700246 if (eventTimeNs < mCurrentBucketStartTimeNs) {
247 VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
248 (long long)mCurrentBucketStartTimeNs);
249 return;
250 }
Chenjie Yud9dfda72017-12-11 17:41:20 -0800251 flushIfNeededLocked(eventTimeNs);
Yao Chen6a8c7992017-11-29 20:02:07 +0000252
Yao Chenb3561512017-11-21 18:07:17 -0800253 // For gauge metric, we just simply use the first gauge in the given bucket.
Chenjie Yud9dfda72017-12-11 17:41:20 -0800254 if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end()) {
Yangster1d4d6862017-10-31 12:58:51 -0700255 return;
256 }
Yangster-mac20877162017-12-22 17:19:39 -0800257 std::shared_ptr<FieldValueMap> gaugeFields = getGaugeFields(event);
Chenjie Yud9dfda72017-12-11 17:41:20 -0800258 if (hitGuardRailLocked(eventKey)) {
259 return;
Yao Chen6a8c7992017-11-29 20:02:07 +0000260 }
Yangster-mac20877162017-12-22 17:19:39 -0800261 (*mCurrentSlicedBucket)[eventKey] = gaugeFields;
Chenjie Yud9dfda72017-12-11 17:41:20 -0800262 // Anomaly detection on gauge metric only works when there is one numeric
263 // field specified.
264 if (mAnomalyTrackers.size() > 0) {
Yangster-mac20877162017-12-22 17:19:39 -0800265 if (gaugeFields->size() == 1) {
266 const DimensionsValue& dimensionsValue = gaugeFields->begin()->second;
Chenjie Yud9dfda72017-12-11 17:41:20 -0800267 long gaugeVal = 0;
Yangster-mac20877162017-12-22 17:19:39 -0800268 if (dimensionsValue.has_value_int()) {
269 gaugeVal = (long)dimensionsValue.value_int();
270 } else if (dimensionsValue.has_value_long()) {
271 gaugeVal = dimensionsValue.value_long();
Chenjie Yud9dfda72017-12-11 17:41:20 -0800272 }
273 for (auto& tracker : mAnomalyTrackers) {
274 tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
275 gaugeVal);
276 }
277 }
278 }
279}
280
281void GaugeMetricProducer::updateCurrentSlicedBucketForAnomaly() {
282 mCurrentSlicedBucketForAnomaly->clear();
283 status_t err = NO_ERROR;
284 for (const auto& slice : *mCurrentSlicedBucket) {
Yangster-mac20877162017-12-22 17:19:39 -0800285 const DimensionsValue& dimensionsValue = slice.second->begin()->second;
Chenjie Yud9dfda72017-12-11 17:41:20 -0800286 long gaugeVal = 0;
Yangster-mac20877162017-12-22 17:19:39 -0800287 if (dimensionsValue.has_value_int()) {
288 gaugeVal = (long)dimensionsValue.value_int();
289 } else if (dimensionsValue.has_value_long()) {
290 gaugeVal = dimensionsValue.value_long();
Chenjie Yud9dfda72017-12-11 17:41:20 -0800291 }
292 (*mCurrentSlicedBucketForAnomaly)[slice.first] = gaugeVal;
Yangster1d4d6862017-10-31 12:58:51 -0700293 }
294}
295
296// When a new matched event comes in, we check if event falls into the current
297// bucket. If not, flush the old counter to past buckets and initialize the new
298// bucket.
299// if data is pushed, onMatchedLogEvent will only be called through onConditionChanged() inside
300// the GaugeMetricProducer while holding the lock.
Yangsterf2bee6f2017-11-29 12:01:05 -0800301void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800302 if (eventTimeNs < mCurrentBucketStartTimeNs + mBucketSizeNs) {
Chenjie Yud9dfda72017-12-11 17:41:20 -0800303 VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
304 (long long)(mCurrentBucketStartTimeNs + mBucketSizeNs));
Yangster1d4d6862017-10-31 12:58:51 -0700305 return;
306 }
307
yro2b0f8862017-11-06 14:27:31 -0800308 GaugeBucket info;
309 info.mBucketStartNs = mCurrentBucketStartTimeNs;
310 info.mBucketEndNs = mCurrentBucketStartTimeNs + mBucketSizeNs;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800311 info.mBucketNum = mCurrentBucketNum;
Yangster1d4d6862017-10-31 12:58:51 -0700312
Yangster-mace2cd6d52017-11-09 20:38:30 -0800313 for (const auto& slice : *mCurrentSlicedBucket) {
Yangster-mac20877162017-12-22 17:19:39 -0800314 info.mGaugeFields = slice.second;
Yangster1d4d6862017-10-31 12:58:51 -0700315 auto& bucketList = mPastBuckets[slice.first];
316 bucketList.push_back(info);
Yangster-mac20877162017-12-22 17:19:39 -0800317 VLOG("gauge metric %s, dump key value: %s", mName.c_str(), slice.first.c_str());
Yangster1d4d6862017-10-31 12:58:51 -0700318 }
Yangster1d4d6862017-10-31 12:58:51 -0700319
Yangster-mace2cd6d52017-11-09 20:38:30 -0800320 // Reset counters
Chenjie Yud9dfda72017-12-11 17:41:20 -0800321 if (mAnomalyTrackers.size() > 0) {
322 updateCurrentSlicedBucketForAnomaly();
323 for (auto& tracker : mAnomalyTrackers) {
324 tracker->addPastBucket(mCurrentSlicedBucketForAnomaly, mCurrentBucketNum);
325 }
Yangster-mace2cd6d52017-11-09 20:38:30 -0800326 }
327
Yangster-mac20877162017-12-22 17:19:39 -0800328 mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>();
Yangster-mace2cd6d52017-11-09 20:38:30 -0800329
330 // Adjusts the bucket start time
331 int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
Yangster1d4d6862017-10-31 12:58:51 -0700332 mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
Yangster-mace2cd6d52017-11-09 20:38:30 -0800333 mCurrentBucketNum += numBucketsForward;
Yao Chenf09569f2017-12-13 17:00:51 -0800334 VLOG("metric %s: new bucket start time: %lld", mName.c_str(),
Yangster1d4d6862017-10-31 12:58:51 -0700335 (long long)mCurrentBucketStartTimeNs);
336}
337
Yangsterf2bee6f2017-11-29 12:01:05 -0800338size_t GaugeMetricProducer::byteSizeLocked() const {
Yangster-mace2cd6d52017-11-09 20:38:30 -0800339 size_t totalSize = 0;
340 for (const auto& pair : mPastBuckets) {
341 totalSize += pair.second.size() * kBucketSize;
342 }
343 return totalSize;
yro2b0f8862017-11-06 14:27:31 -0800344}
345
Yangster1d4d6862017-10-31 12:58:51 -0700346} // namespace statsd
347} // namespace os
348} // namespace android