DurationMetricProducer.cpp revision 1ff4f4325882d812ded4f75ee6c2b6d352a85c9e
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
17729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#define DEBUG true
185154a379303ab90a2b2914676a4441917a329b5dYao Chen
19729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include "Log.h"
205154a379303ab90a2b2914676a4441917a329b5dYao Chen#include "DurationMetricProducer.h"
21729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include "stats_util.h"
22729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
23729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include <limits.h>
24729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen#include <stdlib.h>
25729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
26b0378b093d9b937fe9a731a601d670d50f263078yrousing android::util::FIELD_COUNT_REPEATED;
272b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_BOOL;
282b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_FLOAT;
292b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_INT32;
302b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_INT64;
312b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_MESSAGE;
32d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-macusing android::util::FIELD_TYPE_STRING;
332b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::ProtoOutputStream;
34729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::string;
35729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::unordered_map;
36729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::vector;
37729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
38729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace android {
39729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace os {
40729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace statsd {
41729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
422b0f88678b2877a8e9f83cea60f097322b078367yro// for StatsLogReport
43d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-macconst int FIELD_ID_NAME = 1;
442b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_START_REPORT_NANOS = 2;
452b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_END_REPORT_NANOS = 3;
462b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DURATION_METRICS = 6;
472b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationMetricDataWrapper
482b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DATA = 1;
492b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationMetricData
502b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DIMENSION = 1;
512b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_BUCKET_INFO = 2;
522b0f88678b2877a8e9f83cea60f097322b078367yro// for KeyValuePair
532b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_KEY = 1;
542b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_STR = 2;
552b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_INT = 3;
562b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_BOOL = 4;
572b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_FLOAT = 5;
582b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationBucketInfo
592b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_START_BUCKET_NANOS = 1;
602b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_END_BUCKET_NANOS = 2;
612b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DURATION = 3;
622b0f88678b2877a8e9f83cea60f097322b078367yro
63729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao ChenDurationMetricProducer::DurationMetricProducer(const DurationMetric& metric,
64729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                               const int conditionIndex, const size_t startIndex,
65729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                               const size_t stopIndex, const size_t stopAllIndex,
660ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen                                               const bool nesting,
675154a379303ab90a2b2914676a4441917a329b5dYao Chen                                               const sp<ConditionWizard>& wizard,
6893fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen                                               const vector<KeyMatcher>& internalDimension,
6993fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen                                               const uint64_t startTimeNs)
7093fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen    : MetricProducer(startTimeNs, conditionIndex, wizard),
71729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mMetric(metric),
72729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mStartIndex(startIndex),
73729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mStopIndex(stopIndex),
745154a379303ab90a2b2914676a4441917a329b5dYao Chen      mStopAllIndex(stopAllIndex),
750ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen      mNested(nesting),
765154a379303ab90a2b2914676a4441917a329b5dYao Chen      mInternalDimension(internalDimension) {
77729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: The following boiler plate code appears in all MetricProducers, but we can't abstract
78729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // them in the base class, because the proto generated CountMetric, and DurationMetric are
79729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // not related. Maybe we should add a template in the future??
80729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
81729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000000;
82729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    } else {
83729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mBucketSizeNs = LLONG_MAX;
84729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
85729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
86729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: use UidMap if uid->pkg_name is required
87729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    mDimension.insert(mDimension.begin(), metric.dimension().begin(), metric.dimension().end());
88729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
89729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    if (metric.links().size() > 0) {
90729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
91729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                               metric.links().end());
92729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mConditionSliced = true;
93729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
94729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
952b0f88678b2877a8e9f83cea60f097322b078367yro    startNewProtoOutputStream(mStartTimeNs);
962b0f88678b2877a8e9f83cea60f097322b078367yro
97d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    VLOG("metric %s created. bucket size %lld start_time: %lld", metric.name().c_str(),
98729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen         (long long)mBucketSizeNs, (long long)mStartTimeNs);
99729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
100729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
101729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao ChenDurationMetricProducer::~DurationMetricProducer() {
102729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    VLOG("~DurationMetric() called");
103729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
104729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1052b0f88678b2877a8e9f83cea60f097322b078367yrovoid DurationMetricProducer::startNewProtoOutputStream(long long startTime) {
1062b0f88678b2877a8e9f83cea60f097322b078367yro    mProto = std::make_unique<ProtoOutputStream>();
107d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    mProto->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mMetric.name());
1082b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, startTime);
1092b0f88678b2877a8e9f83cea60f097322b078367yro    mProtoToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
1102b0f88678b2877a8e9f83cea60f097322b078367yro}
1112b0f88678b2877a8e9f83cea60f097322b078367yro
1125154a379303ab90a2b2914676a4441917a329b5dYao Chenunique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
113e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac        const HashableDimensionKey& eventKey, vector<DurationBucket>& bucket) {
114cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon    switch (mMetric.aggregation_type()) {
115cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon        case DurationMetric_AggregationType_SUM:
116e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac            return make_unique<OringDurationTracker>(eventKey, mWizard, mConditionTrackerIndex,
117e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac                                                     mNested, mCurrentBucketStartTimeNs,
118e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac                                                     mBucketSizeNs, mAnomalyTrackers, bucket);
119cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon        case DurationMetric_AggregationType_MAX_SPARSE:
120e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac            return make_unique<MaxDurationTracker>(eventKey, mWizard, mConditionTrackerIndex,
121e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac                                                   mNested, mCurrentBucketStartTimeNs,
122e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac                                                   mBucketSizeNs, mAnomalyTrackers, bucket);
1235154a379303ab90a2b2914676a4441917a329b5dYao Chen    }
1245154a379303ab90a2b2914676a4441917a329b5dYao Chen}
1255154a379303ab90a2b2914676a4441917a329b5dYao Chen
126729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenvoid DurationMetricProducer::finish() {
127729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: write the StatsLogReport to dropbox using
128729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // DropboxWriter.
129729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
130729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1315154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
132d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    VLOG("Metric %s onSlicedConditionMayChange", mMetric.name().c_str());
133729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // Now for each of the on-going event, check if the condition has changed for them.
134729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1355154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onSlicedConditionMayChange(eventTime);
136729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
137729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
138729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1395154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onConditionChanged(const bool conditionMet, const uint64_t eventTime) {
140d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    VLOG("Metric %s onConditionChanged", mMetric.name().c_str());
141729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    mCondition = conditionMet;
142729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: need to populate the condition change time from the event which triggers the condition
143729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // change, instead of using current time.
144729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1455154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onConditionChanged(conditionMet, eventTime);
146729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
147729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
148729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
14917adac9cf3e03ad95372eb8657b26909d0414ac0yrostd::unique_ptr<std::vector<uint8_t>> DurationMetricProducer::onDumpReport() {
1502b0f88678b2877a8e9f83cea60f097322b078367yro    long long endTime = time(nullptr) * NS_PER_SEC;
1512b0f88678b2877a8e9f83cea60f097322b078367yro
152729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // Dump current bucket if it's stale.
153729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // If current bucket is still on-going, don't force dump current bucket.
154729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // In finish(), We can force dump current bucket.
1552b0f88678b2877a8e9f83cea60f097322b078367yro    flushIfNeeded(endTime);
156d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    VLOG("metric %s dump report now...", mMetric.name().c_str());
157729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
158729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& pair : mPastBuckets) {
159729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        const HashableDimensionKey& hashableKey = pair.first;
1602b0f88678b2877a8e9f83cea60f097322b078367yro        VLOG("  dimension key %s", hashableKey.c_str());
161729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        auto it = mDimensionKeyMap.find(hashableKey);
162729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        if (it == mDimensionKeyMap.end()) {
163729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen            ALOGW("Dimension key %s not found?!?! skip...", hashableKey.c_str());
164729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen            continue;
165729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
1661ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen
1671ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen        // If there is no duration bucket info for this key, don't include it in the report.
1681ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen        // For example, duration started, but condition is never turned to true.
1691ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen        // TODO: Only add the key to the map when we add duration buckets info for it.
1701ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen        if (pair.second.size() == 0) {
1711ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen            continue;
1721ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen        }
1731ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen
174b0378b093d9b937fe9a731a601d670d50f263078yro        long long wrapperToken =
175b0378b093d9b937fe9a731a601d670d50f263078yro                mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
1762b0f88678b2877a8e9f83cea60f097322b078367yro
1772b0f88678b2877a8e9f83cea60f097322b078367yro        // First fill dimension (KeyValuePairs).
1782b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& kv : it->second) {
179b0378b093d9b937fe9a731a601d670d50f263078yro            long long dimensionToken =
180b0378b093d9b937fe9a731a601d670d50f263078yro                    mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
1812b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT32 | FIELD_ID_KEY, kv.key());
1822b0f88678b2877a8e9f83cea60f097322b078367yro            if (kv.has_value_str()) {
1831ff4f4325882d812ded4f75ee6c2b6d352a85c9eYao Chen                mProto->write(FIELD_TYPE_STRING | FIELD_ID_VALUE_STR, kv.value_str());
1842b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_int()) {
1852b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_INT, kv.value_int());
1862b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_bool()) {
1872b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_BOOL | FIELD_ID_VALUE_BOOL, kv.value_bool());
1882b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_float()) {
1892b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_FLOAT | FIELD_ID_VALUE_FLOAT, kv.value_float());
1902b0f88678b2877a8e9f83cea60f097322b078367yro            }
1912b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->end(dimensionToken);
1922b0f88678b2877a8e9f83cea60f097322b078367yro        }
1932b0f88678b2877a8e9f83cea60f097322b078367yro
1942b0f88678b2877a8e9f83cea60f097322b078367yro        // Then fill bucket_info (DurationBucketInfo).
1952b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& bucket : pair.second) {
196b0378b093d9b937fe9a731a601d670d50f263078yro            long long bucketInfoToken =
197b0378b093d9b937fe9a731a601d670d50f263078yro                    mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
1982b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
1992b0f88678b2877a8e9f83cea60f097322b078367yro                          (long long)bucket.mBucketStartNs);
2002b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
2012b0f88678b2877a8e9f83cea60f097322b078367yro                          (long long)bucket.mBucketEndNs);
2022b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
2032b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->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
2082b0f88678b2877a8e9f83cea60f097322b078367yro        mProto->end(wrapperToken);
209729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
2102b0f88678b2877a8e9f83cea60f097322b078367yro
2112b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->end(mProtoToken);
2122b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS,
2132b0f88678b2877a8e9f83cea60f097322b078367yro                  (long long)mCurrentBucketStartTimeNs);
21417adac9cf3e03ad95372eb8657b26909d0414ac0yro    std::unique_ptr<std::vector<uint8_t>> buffer = serializeProto();
2152b0f88678b2877a8e9f83cea60f097322b078367yro    startNewProtoOutputStream(endTime);
21630b6a20c99d043e36d41851d80250bfdf2810556Yao Chen    // TODO: Properly clear the old buckets.
21717adac9cf3e03ad95372eb8657b26909d0414ac0yro    return buffer;
2182b0f88678b2877a8e9f83cea60f097322b078367yro}
219729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2205154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::flushIfNeeded(uint64_t eventTime) {
2215154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
222729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
223729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
2245154a379303ab90a2b2914676a4441917a329b5dYao Chen    VLOG("flushing...........");
225d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen    for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end();) {
2265154a379303ab90a2b2914676a4441917a329b5dYao Chen        if (it->second->flushIfNeeded(eventTime)) {
2275154a379303ab90a2b2914676a4441917a329b5dYao Chen            VLOG("erase bucket for key %s", it->first.c_str());
228d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen            it = mCurrentSlicedDuration.erase(it);
229d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen        } else {
230d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen            ++it;
231729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
232729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
233729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2345154a379303ab90a2b2914676a4441917a329b5dYao Chen    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
2355154a379303ab90a2b2914676a4441917a329b5dYao Chen    mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
236e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac    mCurrentBucketNum += numBucketsForward;
237729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
238729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2395154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onMatchedLogEventInternal(
2405154a379303ab90a2b2914676a4441917a329b5dYao Chen        const size_t matcherIndex, const HashableDimensionKey& eventKey,
2415154a379303ab90a2b2914676a4441917a329b5dYao Chen        const map<string, HashableDimensionKey>& conditionKeys, bool condition,
242b3dda41a5a48ddfa44dc8fa939ab495926a0195dChenjie Yu        const LogEvent& event, bool scheduledPull) {
2435154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(event.GetTimestampNs());
244729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2455154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (matcherIndex == mStopAllIndex) {
2465154a379303ab90a2b2914676a4441917a329b5dYao Chen        for (auto& pair : mCurrentSlicedDuration) {
2475154a379303ab90a2b2914676a4441917a329b5dYao Chen            pair.second->noteStopAll(event.GetTimestampNs());
2485154a379303ab90a2b2914676a4441917a329b5dYao Chen        }
249729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
250729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
251729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2525154a379303ab90a2b2914676a4441917a329b5dYao Chen    HashableDimensionKey atomKey = getHashableKey(getDimensionKey(event, mInternalDimension));
253729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2545154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end()) {
255e2cd6d509b17894b95d14523ae3e7c4c7a9a74e3Yangster-mac        mCurrentSlicedDuration[eventKey] = createDurationTracker(eventKey, mPastBuckets[eventKey]);
2565154a379303ab90a2b2914676a4441917a329b5dYao Chen    }
257729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2585154a379303ab90a2b2914676a4441917a329b5dYao Chen    auto it = mCurrentSlicedDuration.find(eventKey);
259729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2605154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (matcherIndex == mStartIndex) {
2615154a379303ab90a2b2914676a4441917a329b5dYao Chen        it->second->noteStart(atomKey, condition, event.GetTimestampNs(), conditionKeys);
2625154a379303ab90a2b2914676a4441917a329b5dYao Chen    } else if (matcherIndex == mStopIndex) {
2630ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen        it->second->noteStop(atomKey, event.GetTimestampNs(), false);
264729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
265729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
266729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
26769007c82625dd8b19bd68d1031191e2ff83b5f49yrosize_t DurationMetricProducer::byteSize() {
2682b0f88678b2877a8e9f83cea60f097322b078367yro  size_t totalSize = 0;
2692b0f88678b2877a8e9f83cea60f097322b078367yro  for (const auto& pair : mPastBuckets) {
2702b0f88678b2877a8e9f83cea60f097322b078367yro      totalSize += pair.second.size() * kBucketSize;
2712b0f88678b2877a8e9f83cea60f097322b078367yro  }
2722b0f88678b2877a8e9f83cea60f097322b078367yro  return totalSize;
27369007c82625dd8b19bd68d1031191e2ff83b5f49yro}
27469007c82625dd8b19bd68d1031191e2ff83b5f49yro
275729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace statsd
276729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace os
277729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace android
278