DurationMetricProducer.cpp revision 884c8c130fde0d02ada1316f7c27f0f55e7e48b9
1729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen/*
2729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * Copyright (C) 2017 The Android Open Source Project
3729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen *
4729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * Licensed under the Apache License, Version 2.0 (the "License");
5729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * you may not use this file except in compliance with the License.
6729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * You may obtain a copy of the License at
7729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen *
8729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen *      http://www.apache.org/licenses/LICENSE-2.0
9729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen *
10729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * Unless required by applicable law or agreed to in writing, software
11729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * distributed under the License is distributed on an "AS IS" BASIS,
12729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * See the License for the specific language governing permissions and
14729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen * limitations under the License.
15729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen */
16729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
173c0b95ceb520c6b23871da90c23f89c55b76b560Yao Chen#define DEBUG false
185154a379303ab90a2b2914676a4441917a329b5dYao Chen
19729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include "Log.h"
205154a379303ab90a2b2914676a4441917a329b5dYao Chen#include "DurationMetricProducer.h"
21b356151e63140085cb96fa16804ee18b3862a4fcYao Chen#include "guardrail/StatsdStats.h"
22729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include "stats_util.h"
232087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac#include "stats_log_util.h"
24729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
25729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include <limits.h>
26729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include <stdlib.h>
27729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
28b0378b093d9b937fe9a731a601d670d50f263078yrousing android::util::FIELD_COUNT_REPEATED;
292b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_BOOL;
302b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_FLOAT;
312b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_INT32;
322b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_INT64;
332b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_MESSAGE;
34d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-macusing android::util::FIELD_TYPE_STRING;
352b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::ProtoOutputStream;
36729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::string;
37729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::unordered_map;
38729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::vector;
39729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
40729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace android {
41729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace os {
42729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace statsd {
43729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
442b0f88678b2877a8e9f83cea60f097322b078367yro// for StatsLogReport
4594e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-macconst int FIELD_ID_ID = 1;
462b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_START_REPORT_NANOS = 2;
472b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_END_REPORT_NANOS = 3;
482b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DURATION_METRICS = 6;
492b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationMetricDataWrapper
502b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DATA = 1;
512b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationMetricData
52468ff04fd4cb43a384a3d4948cccd4438be7202aYangster-macconst int FIELD_ID_DIMENSION_IN_WHAT = 1;
53468ff04fd4cb43a384a3d4948cccd4438be7202aYangster-macconst int FIELD_ID_DIMENSION_IN_CONDITION = 2;
54468ff04fd4cb43a384a3d4948cccd4438be7202aYangster-macconst int FIELD_ID_BUCKET_INFO = 3;
552b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationBucketInfo
562b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_START_BUCKET_NANOS = 1;
572b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_END_BUCKET_NANOS = 2;
582b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DURATION = 3;
592b0f88678b2877a8e9f83cea60f097322b078367yro
60b356151e63140085cb96fa16804ee18b3862a4fcYao ChenDurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const DurationMetric& metric,
61729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                               const int conditionIndex, const size_t startIndex,
62729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                               const size_t stopIndex, const size_t stopAllIndex,
630ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen                                               const bool nesting,
645154a379303ab90a2b2914676a4441917a329b5dYao Chen                                               const sp<ConditionWizard>& wizard,
652087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac                                               const FieldMatcher& internalDimensions,
6693fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen                                               const uint64_t startTimeNs)
6794e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
68f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chen      mAggregationType(metric.aggregation_type()),
69729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mStartIndex(startIndex),
70729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mStopIndex(stopIndex),
715154a379303ab90a2b2914676a4441917a329b5dYao Chen      mStopAllIndex(stopAllIndex),
720ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen      mNested(nesting),
732087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac      mInternalDimensions(internalDimensions) {
74729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: The following boiler plate code appears in all MetricProducers, but we can't abstract
75729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // them in the base class, because the proto generated CountMetric, and DurationMetric are
76729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // not related. Maybe we should add a template in the future??
77b814481ad1f8d0e429d799b1571a6272e1a7f6c5Yangster-mac    if (metric.has_bucket()) {
78b814481ad1f8d0e429d799b1571a6272e1a7f6c5Yangster-mac        mBucketSizeNs = TimeUnitToBucketSizeInMillis(metric.bucket()) * 1000000;
79729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    } else {
80729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mBucketSizeNs = LLONG_MAX;
81729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
82729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
83729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: use UidMap if uid->pkg_name is required
84468ff04fd4cb43a384a3d4948cccd4438be7202aYangster-mac    mDimensions = metric.dimensions_in_what();
85729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
86729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    if (metric.links().size() > 0) {
87729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
88729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                               metric.links().end());
89729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mConditionSliced = true;
90729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
91729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
9294e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
93729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen         (long long)mBucketSizeNs, (long long)mStartTimeNs);
94729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
95729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
96729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao ChenDurationMetricProducer::~DurationMetricProducer() {
97729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    VLOG("~DurationMetric() called");
98729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
99729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
100857aaa520804d846a050e1eeb85d82977c983666Bookatzsp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(const Alert &alert) {
101857aaa520804d846a050e1eeb85d82977c983666Bookatz    std::lock_guard<std::mutex> lock(mMutex);
102a7fb12d2d285a3a62f5e8956d1bacfa0e15e9d0fYangster-mac    if (alert.trigger_if_sum_gt() > alert.num_buckets() * mBucketSizeNs) {
103a7fb12d2d285a3a62f5e8956d1bacfa0e15e9d0fYangster-mac        ALOGW("invalid alert: threshold (%f) > possible recordable value (%d x %lld)",
104a7fb12d2d285a3a62f5e8956d1bacfa0e15e9d0fYangster-mac              alert.trigger_if_sum_gt(), alert.num_buckets(),
105450099db169d386077584d93486908c3bae1244eBookatz              (long long)mBucketSizeNs);
106450099db169d386077584d93486908c3bae1244eBookatz        return nullptr;
107450099db169d386077584d93486908c3bae1244eBookatz    }
108857aaa520804d846a050e1eeb85d82977c983666Bookatz    sp<DurationAnomalyTracker> anomalyTracker = new DurationAnomalyTracker(alert, mConfigKey);
109857aaa520804d846a050e1eeb85d82977c983666Bookatz    if (anomalyTracker != nullptr) {
110857aaa520804d846a050e1eeb85d82977c983666Bookatz        mAnomalyTrackers.push_back(anomalyTracker);
111857aaa520804d846a050e1eeb85d82977c983666Bookatz    }
112857aaa520804d846a050e1eeb85d82977c983666Bookatz    return anomalyTracker;
113450099db169d386077584d93486908c3bae1244eBookatz}
114450099db169d386077584d93486908c3bae1244eBookatz
1155154a379303ab90a2b2914676a4441917a329b5dYao Chenunique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
116f60e0bad5908c51c954ca8dc763c8efd394c56dcYao Chen        const HashableDimensionKey& eventKey) const {
117f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chen    switch (mAggregationType) {
118cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon        case DurationMetric_AggregationType_SUM:
119b356151e63140085cb96fa16804ee18b3862a4fcYao Chen            return make_unique<OringDurationTracker>(
12094e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac                    mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
121d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen                    mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
122cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon        case DurationMetric_AggregationType_MAX_SPARSE:
123b356151e63140085cb96fa16804ee18b3862a4fcYao Chen            return make_unique<MaxDurationTracker>(
12494e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac                    mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex, mNested,
125d59a6589faeb8a1b7b3c23e5ac95671bda736cddYao Chen                    mCurrentBucketStartTimeNs, mBucketSizeNs, mConditionSliced, mAnomalyTrackers);
1265154a379303ab90a2b2914676a4441917a329b5dYao Chen    }
1275154a379303ab90a2b2914676a4441917a329b5dYao Chen}
1285154a379303ab90a2b2914676a4441917a329b5dYao Chen
129f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangstervoid DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
13094e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
131f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangster    flushIfNeededLocked(eventTime);
132729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // Now for each of the on-going event, check if the condition has changed for them.
133729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1345154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onSlicedConditionMayChange(eventTime);
135729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
136729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
137729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
138f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangstervoid DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
139f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangster                                                      const uint64_t eventTime) {
14094e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
141729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    mCondition = conditionMet;
142f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangster    flushIfNeededLocked(eventTime);
143729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: need to populate the condition change time from the event which triggers the condition
144729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // change, instead of using current time.
145729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1465154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onConditionChanged(conditionMet, eventTime);
147729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
148729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
149729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1502087716f2bdca90c7c3034d556ac12911bd8018eYangster-macvoid DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) {
1512087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    flushIfNeededLocked(dumpTimeNs);
15294e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    report->set_metric_id(mMetricId);
1532087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    report->set_start_report_nanos(mStartTimeNs);
1542087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac
1552087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    auto duration_metrics = report->mutable_duration_metrics();
1562087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    for (const auto& pair : mPastBuckets) {
1572087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        DurationMetricData* metricData = duration_metrics->add_data();
158468ff04fd4cb43a384a3d4948cccd4438be7202aYangster-mac        *metricData->mutable_dimensions_in_what() = pair.first.getDimensionsValue();
1592087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        for (const auto& bucket : pair.second) {
1602087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            auto bucketInfo = metricData->add_bucket_info();
1612087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            bucketInfo->set_start_bucket_nanos(bucket.mBucketStartNs);
1622087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            bucketInfo->set_end_bucket_nanos(bucket.mBucketEndNs);
1632087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            bucketInfo->set_duration_nanos(bucket.mDuration);
1642087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        }
1652087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    }
1662087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac}
1672087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac
168288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chenvoid DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
169288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen                                                ProtoOutputStream* protoOutput) {
170288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen    flushIfNeededLocked(dumpTimeNs);
171635b4b37210bd61b73aebf19298e38b8fb382e85Yangster-mac    if (mPastBuckets.empty()) {
172635b4b37210bd61b73aebf19298e38b8fb382e85Yangster-mac        return;
173635b4b37210bd61b73aebf19298e38b8fb382e85Yangster-mac    }
174288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen
17594e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
176288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
177288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen    long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
1786a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen
17994e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac    VLOG("metric %lld dump report now...", (long long)mMetricId);
1806a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen
181729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& pair : mPastBuckets) {
182729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        const HashableDimensionKey& hashableKey = pair.first;
1832b0f88678b2877a8e9f83cea60f097322b078367yro        VLOG("  dimension key %s", hashableKey.c_str());
1841ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen
185b0378b093d9b937fe9a731a601d670d50f263078yro        long long wrapperToken =
186288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen                protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
1872b0f88678b2877a8e9f83cea60f097322b078367yro
1882087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        // First fill dimension.
1892087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        long long dimensionToken = protoOutput->start(
190468ff04fd4cb43a384a3d4948cccd4438be7202aYangster-mac                FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
1912087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        writeDimensionsValueProtoToStream(hashableKey.getDimensionsValue(), protoOutput);
1922087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        protoOutput->end(dimensionToken);
1932b0f88678b2877a8e9f83cea60f097322b078367yro
1942b0f88678b2877a8e9f83cea60f097322b078367yro        // Then fill bucket_info (DurationBucketInfo).
1952b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& bucket : pair.second) {
196288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen            long long bucketInfoToken = protoOutput->start(
197288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen                    FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
198288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
199288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen                               (long long)bucket.mBucketStartNs);
200288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
201288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen                               (long long)bucket.mBucketEndNs);
202288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen            protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
203288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen            protoOutput->end(bucketInfoToken);
2042b0f88678b2877a8e9f83cea60f097322b078367yro            VLOG("\t bucket [%lld - %lld] duration: %lld", (long long)bucket.mBucketStartNs,
2052b0f88678b2877a8e9f83cea60f097322b078367yro                 (long long)bucket.mBucketEndNs, (long long)bucket.mDuration);
2062b0f88678b2877a8e9f83cea60f097322b078367yro        }
2072b0f88678b2877a8e9f83cea60f097322b078367yro
208288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen        protoOutput->end(wrapperToken);
209729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
2102b0f88678b2877a8e9f83cea60f097322b078367yro
211288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen    protoOutput->end(protoToken);
212288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
213f60e0bad5908c51c954ca8dc763c8efd394c56dcYao Chen    mPastBuckets.clear();
214288c60001330a5a924a47c0eebd6097ae3ee5d67Yao Chen    mStartTimeNs = mCurrentBucketStartTimeNs;
2152b0f88678b2877a8e9f83cea60f097322b078367yro}
216729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
217f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangstervoid DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTime) {
2185154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
219729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
220729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
2215154a379303ab90a2b2914676a4441917a329b5dYao Chen    VLOG("flushing...........");
222d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen    for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end();) {
223f60e0bad5908c51c954ca8dc763c8efd394c56dcYao Chen        if (it->second->flushIfNeeded(eventTime, &mPastBuckets)) {
2245154a379303ab90a2b2914676a4441917a329b5dYao Chen            VLOG("erase bucket for key %s", it->first.c_str());
225d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen            it = mCurrentSlicedDuration.erase(it);
226d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen        } else {
227d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen            ++it;
228729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
229729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
230729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2315154a379303ab90a2b2914676a4441917a329b5dYao Chen    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
2325154a379303ab90a2b2914676a4441917a329b5dYao Chen    mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
233e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac    mCurrentBucketNum += numBucketsForward;
234729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
235729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
236884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chenvoid DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
237884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen    if (mCurrentSlicedDuration.size() == 0) {
238884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen        return;
239884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen    }
240884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen
241884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen    fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId,
242884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen            (unsigned long)mCurrentSlicedDuration.size());
243884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen    if (verbose) {
244884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen        for (const auto& slice : mCurrentSlicedDuration) {
245884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen            fprintf(out, "\t%s\n", slice.first.c_str());
246884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen            slice.second->dumpStates(out, verbose);
247884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen        }
248884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen    }
249884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen}
250884c8c130fde0d02ada1316f7c27f0f55e7e48b9Yao Chen
251f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangsterbool DurationMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) {
252b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    // the key is not new, we are good.
253b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    if (mCurrentSlicedDuration.find(newKey) != mCurrentSlicedDuration.end()) {
254b356151e63140085cb96fa16804ee18b3862a4fcYao Chen        return false;
255b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    }
256b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    // 1. Report the tuple count if the tuple count > soft limit
257b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    if (mCurrentSlicedDuration.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
258b356151e63140085cb96fa16804ee18b3862a4fcYao Chen        size_t newTupleCount = mCurrentSlicedDuration.size() + 1;
25994e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac        StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
260b356151e63140085cb96fa16804ee18b3862a4fcYao Chen        // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
261b356151e63140085cb96fa16804ee18b3862a4fcYao Chen        if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
26294e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac            ALOGE("DurationMetric %lld dropping data for dimension key %s",
26394e197cceb2ba7df13ff8de04f60bfeec64015d9Yangster-mac                (long long)mMetricId, newKey.c_str());
264b356151e63140085cb96fa16804ee18b3862a4fcYao Chen            return true;
265b356151e63140085cb96fa16804ee18b3862a4fcYao Chen        }
266b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    }
267b356151e63140085cb96fa16804ee18b3862a4fcYao Chen    return false;
268b356151e63140085cb96fa16804ee18b3862a4fcYao Chen}
269b356151e63140085cb96fa16804ee18b3862a4fcYao Chen
270f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangstervoid DurationMetricProducer::onMatchedLogEventInternalLocked(
2715154a379303ab90a2b2914676a4441917a329b5dYao Chen        const size_t matcherIndex, const HashableDimensionKey& eventKey,
2722087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        const ConditionKey& conditionKeys, bool condition,
273a7259abde4e89fd91404b14b4845113cd313d1ecChenjie Yu        const LogEvent& event) {
274f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangster    flushIfNeededLocked(event.GetTimestampNs());
275729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2766a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen    if (matcherIndex == mStopAllIndex) {
2776a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen        for (auto& pair : mCurrentSlicedDuration) {
2786a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen            pair.second->noteStopAll(event.GetTimestampNs());
2795154a379303ab90a2b2914676a4441917a329b5dYao Chen        }
2806a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen        return;
2816a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen    }
282729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
283729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2846a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen    if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end()) {
285f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangster        if (hitGuardRailLocked(eventKey)) {
2866a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen            return;
287b356151e63140085cb96fa16804ee18b3862a4fcYao Chen        }
288f60e0bad5908c51c954ca8dc763c8efd394c56dcYao Chen        mCurrentSlicedDuration[eventKey] = createDurationTracker(eventKey);
2896a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen    }
290729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2916a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen    auto it = mCurrentSlicedDuration.find(eventKey);
2926a8c799d901cbd166aa6463d7dea231bcf594a1eYao Chen
2932087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    std::vector<DimensionsValue> values = getDimensionKeys(event, mInternalDimensions);
2942087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    if (values.empty()) {
2952087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        if (matcherIndex == mStartIndex) {
2962087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
2972087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac                                  event.GetTimestampNs(), conditionKeys);
2982087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        } else if (matcherIndex == mStopIndex) {
2992087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            it->second->noteStop(DEFAULT_DIMENSION_KEY, event.GetTimestampNs(), false);
3002087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        }
3012087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac    } else {
3022087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        for (const DimensionsValue& value : values) {
3032087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            if (matcherIndex == mStartIndex) {
3042087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac                it->second->noteStart(HashableDimensionKey(value), condition,
3052087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac                                      event.GetTimestampNs(), conditionKeys);
3062087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            } else if (matcherIndex == mStopIndex) {
3072087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac                it->second->noteStop(HashableDimensionKey(value), event.GetTimestampNs(), false);
3082087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac            }
3092087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac        }
310729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
3112087716f2bdca90c7c3034d556ac12911bd8018eYangster-mac
312729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
313729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
314f2bee6fec965fd42ab223f1a3aa705f07ba79aeaYangstersize_t DurationMetricProducer::byteSizeLocked() const {
3157c334a129e93e405a72e8299a1cd928af079d14fYangster    size_t totalSize = 0;
3167c334a129e93e405a72e8299a1cd928af079d14fYangster    for (const auto& pair : mPastBuckets) {
3177c334a129e93e405a72e8299a1cd928af079d14fYangster        totalSize += pair.second.size() * kBucketSize;
3187c334a129e93e405a72e8299a1cd928af079d14fYangster    }
3197c334a129e93e405a72e8299a1cd928af079d14fYangster    return totalSize;
32069007c82625dd8b19bd68d1031191e2ff83b5f49yro}
32169007c82625dd8b19bd68d1031191e2ff83b5f49yro
322729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace statsd
323729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace os
324729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace android
325