DurationMetricProducer.cpp revision cfed20bce8a66bde6ad0d74a44fc0a2764b2886d
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(
1132b0f88678b2877a8e9f83cea60f097322b078367yro        vector<DurationBucket>& bucket) {
114cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon    switch (mMetric.aggregation_type()) {
115cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon        case DurationMetric_AggregationType_SUM:
1160ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen            return make_unique<OringDurationTracker>(mWizard, mConditionTrackerIndex, mNested,
1175154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                     mCurrentBucketStartTimeNs, mBucketSizeNs,
1185154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                     bucket);
119cfed20bce8a66bde6ad0d74a44fc0a2764b2886dStefan Lafon        case DurationMetric_AggregationType_MAX_SPARSE:
1200ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen            return make_unique<MaxDurationTracker>(mWizard, mConditionTrackerIndex, mNested,
1215154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                   mCurrentBucketStartTimeNs, mBucketSizeNs,
1225154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                   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.
1345154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(eventTime);
135729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1365154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onSlicedConditionMayChange(eventTime);
137729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
138729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
139729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1405154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onConditionChanged(const bool conditionMet, const uint64_t eventTime) {
141d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    VLOG("Metric %s onConditionChanged", mMetric.name().c_str());
142729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    mCondition = conditionMet;
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.
1455154a379303ab90a2b2914676a4441917a329b5dYao Chen
1465154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(eventTime);
147729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1485154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onConditionChanged(conditionMet, eventTime);
149729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
150729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
151729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
152729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenstatic void addDurationBucketsToReport(StatsLogReport_DurationMetricDataWrapper& wrapper,
153729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                       const vector<KeyValuePair>& key,
154729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                       const vector<DurationBucketInfo>& buckets) {
155729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    DurationMetricData* data = wrapper.add_data();
156729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& kv : key) {
157729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        data->add_dimension()->CopyFrom(kv);
158729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
159729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& bucket : buckets) {
160729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        data->add_bucket_info()->CopyFrom(bucket);
1615154a379303ab90a2b2914676a4441917a329b5dYao Chen        VLOG("\t bucket [%lld - %lld] duration(ns): %lld", bucket.start_bucket_nanos(),
162729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen             bucket.end_bucket_nanos(), bucket.duration_nanos());
163729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
164729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
165729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
16617adac9cf3e03ad95372eb8657b26909d0414ac0yrostd::unique_ptr<std::vector<uint8_t>> DurationMetricProducer::onDumpReport() {
1672b0f88678b2877a8e9f83cea60f097322b078367yro    long long endTime = time(nullptr) * NS_PER_SEC;
1682b0f88678b2877a8e9f83cea60f097322b078367yro
169729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // Dump current bucket if it's stale.
170729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // If current bucket is still on-going, don't force dump current bucket.
171729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // In finish(), We can force dump current bucket.
1722b0f88678b2877a8e9f83cea60f097322b078367yro    flushIfNeeded(endTime);
173d1815dc7b82f99259f6c41cfacc44972b867ef2dYangster-mac    VLOG("metric %s dump report now...", mMetric.name().c_str());
174729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
175729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& pair : mPastBuckets) {
176729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        const HashableDimensionKey& hashableKey = pair.first;
1772b0f88678b2877a8e9f83cea60f097322b078367yro        VLOG("  dimension key %s", hashableKey.c_str());
178729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        auto it = mDimensionKeyMap.find(hashableKey);
179729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        if (it == mDimensionKeyMap.end()) {
180729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen            ALOGW("Dimension key %s not found?!?! skip...", hashableKey.c_str());
181729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen            continue;
182729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
183b0378b093d9b937fe9a731a601d670d50f263078yro        long long wrapperToken =
184b0378b093d9b937fe9a731a601d670d50f263078yro                mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
1852b0f88678b2877a8e9f83cea60f097322b078367yro
1862b0f88678b2877a8e9f83cea60f097322b078367yro        // First fill dimension (KeyValuePairs).
1872b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& kv : it->second) {
188b0378b093d9b937fe9a731a601d670d50f263078yro            long long dimensionToken =
189b0378b093d9b937fe9a731a601d670d50f263078yro                    mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DIMENSION);
1902b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT32 | FIELD_ID_KEY, kv.key());
1912b0f88678b2877a8e9f83cea60f097322b078367yro            if (kv.has_value_str()) {
1922b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_INT32 | FIELD_ID_VALUE_STR, kv.value_str());
1932b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_int()) {
1942b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_INT, kv.value_int());
1952b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_bool()) {
1962b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_BOOL | FIELD_ID_VALUE_BOOL, kv.value_bool());
1972b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_float()) {
1982b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_FLOAT | FIELD_ID_VALUE_FLOAT, kv.value_float());
1992b0f88678b2877a8e9f83cea60f097322b078367yro            }
2002b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->end(dimensionToken);
2012b0f88678b2877a8e9f83cea60f097322b078367yro        }
2022b0f88678b2877a8e9f83cea60f097322b078367yro
2032b0f88678b2877a8e9f83cea60f097322b078367yro        // Then fill bucket_info (DurationBucketInfo).
2042b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& bucket : pair.second) {
205b0378b093d9b937fe9a731a601d670d50f263078yro            long long bucketInfoToken =
206b0378b093d9b937fe9a731a601d670d50f263078yro                    mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_BUCKET_INFO);
2072b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
2082b0f88678b2877a8e9f83cea60f097322b078367yro                          (long long)bucket.mBucketStartNs);
2092b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
2102b0f88678b2877a8e9f83cea60f097322b078367yro                          (long long)bucket.mBucketEndNs);
2112b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
2122b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->end(bucketInfoToken);
2132b0f88678b2877a8e9f83cea60f097322b078367yro            VLOG("\t bucket [%lld - %lld] duration: %lld", (long long)bucket.mBucketStartNs,
2142b0f88678b2877a8e9f83cea60f097322b078367yro                 (long long)bucket.mBucketEndNs, (long long)bucket.mDuration);
2152b0f88678b2877a8e9f83cea60f097322b078367yro        }
2162b0f88678b2877a8e9f83cea60f097322b078367yro
2172b0f88678b2877a8e9f83cea60f097322b078367yro        mProto->end(wrapperToken);
218729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
2192b0f88678b2877a8e9f83cea60f097322b078367yro
2202b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->end(mProtoToken);
2212b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS,
2222b0f88678b2877a8e9f83cea60f097322b078367yro                  (long long)mCurrentBucketStartTimeNs);
2232b0f88678b2877a8e9f83cea60f097322b078367yro
22417adac9cf3e03ad95372eb8657b26909d0414ac0yro    std::unique_ptr<std::vector<uint8_t>> buffer = serializeProto();
2252b0f88678b2877a8e9f83cea60f097322b078367yro
2262b0f88678b2877a8e9f83cea60f097322b078367yro    startNewProtoOutputStream(endTime);
2272b0f88678b2877a8e9f83cea60f097322b078367yro    mPastBuckets.clear();
2282b0f88678b2877a8e9f83cea60f097322b078367yro
22917adac9cf3e03ad95372eb8657b26909d0414ac0yro    return buffer;
2302b0f88678b2877a8e9f83cea60f097322b078367yro}
231729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2325154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::flushIfNeeded(uint64_t eventTime) {
2335154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
234729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
235729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
236729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2375154a379303ab90a2b2914676a4441917a329b5dYao Chen    VLOG("flushing...........");
238d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen    for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end();) {
2395154a379303ab90a2b2914676a4441917a329b5dYao Chen        if (it->second->flushIfNeeded(eventTime)) {
2405154a379303ab90a2b2914676a4441917a329b5dYao Chen            VLOG("erase bucket for key %s", it->first.c_str());
241d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen            it = mCurrentSlicedDuration.erase(it);
242d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen        } else {
243d41c4220d06875cea2d19a7991c3227bd56ea611Yao Chen            ++it;
244729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
245729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
246729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2475154a379303ab90a2b2914676a4441917a329b5dYao Chen    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
2485154a379303ab90a2b2914676a4441917a329b5dYao Chen    mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
249729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
250729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2515154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onMatchedLogEventInternal(
2525154a379303ab90a2b2914676a4441917a329b5dYao Chen        const size_t matcherIndex, const HashableDimensionKey& eventKey,
2535154a379303ab90a2b2914676a4441917a329b5dYao Chen        const map<string, HashableDimensionKey>& conditionKeys, bool condition,
254b3dda41a5a48ddfa44dc8fa939ab495926a0195dChenjie Yu        const LogEvent& event, bool scheduledPull) {
2555154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(event.GetTimestampNs());
256729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2575154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (matcherIndex == mStopAllIndex) {
2585154a379303ab90a2b2914676a4441917a329b5dYao Chen        for (auto& pair : mCurrentSlicedDuration) {
2595154a379303ab90a2b2914676a4441917a329b5dYao Chen            pair.second->noteStopAll(event.GetTimestampNs());
2605154a379303ab90a2b2914676a4441917a329b5dYao Chen        }
261729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
262729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
263729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2645154a379303ab90a2b2914676a4441917a329b5dYao Chen    HashableDimensionKey atomKey = getHashableKey(getDimensionKey(event, mInternalDimension));
265729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2665154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end()) {
2675154a379303ab90a2b2914676a4441917a329b5dYao Chen        mCurrentSlicedDuration[eventKey] = createDurationTracker(mPastBuckets[eventKey]);
2685154a379303ab90a2b2914676a4441917a329b5dYao Chen    }
269729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2705154a379303ab90a2b2914676a4441917a329b5dYao Chen    auto it = mCurrentSlicedDuration.find(eventKey);
271729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2725154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (matcherIndex == mStartIndex) {
2735154a379303ab90a2b2914676a4441917a329b5dYao Chen        it->second->noteStart(atomKey, condition, event.GetTimestampNs(), conditionKeys);
2745154a379303ab90a2b2914676a4441917a329b5dYao Chen    } else if (matcherIndex == mStopIndex) {
2750ea19901ef78de19437c08bbcbb7af6663ad6f4bYao Chen        it->second->noteStop(atomKey, event.GetTimestampNs(), false);
276729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
277729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
278729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
27969007c82625dd8b19bd68d1031191e2ff83b5f49yrosize_t DurationMetricProducer::byteSize() {
2802b0f88678b2877a8e9f83cea60f097322b078367yro  size_t totalSize = 0;
2812b0f88678b2877a8e9f83cea60f097322b078367yro  for (const auto& pair : mPastBuckets) {
2822b0f88678b2877a8e9f83cea60f097322b078367yro      totalSize += pair.second.size() * kBucketSize;
2832b0f88678b2877a8e9f83cea60f097322b078367yro  }
2842b0f88678b2877a8e9f83cea60f097322b078367yro  return totalSize;
28569007c82625dd8b19bd68d1031191e2ff83b5f49yro}
28669007c82625dd8b19bd68d1031191e2ff83b5f49yro
287729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace statsd
288729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace os
289729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace android
290