DurationMetricProducer.cpp revision 2b0f88678b2877a8e9f83cea60f097322b078367
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
262b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_BOOL;
272b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_FLOAT;
282b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_INT32;
292b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_INT64;
302b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::FIELD_TYPE_MESSAGE;
312b0f88678b2877a8e9f83cea60f097322b078367yrousing android::util::ProtoOutputStream;
32729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::string;
33729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::unordered_map;
34729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenusing std::vector;
35729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
36729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace android {
37729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace os {
38729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chennamespace statsd {
39729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
402b0f88678b2877a8e9f83cea60f097322b078367yro// for StatsLogReport
412b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_METRIC_ID = 1;
422b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_START_REPORT_NANOS = 2;
432b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_END_REPORT_NANOS = 3;
442b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DURATION_METRICS = 6;
452b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationMetricDataWrapper
462b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DATA = 1;
472b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationMetricData
482b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DIMENSION = 1;
492b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_BUCKET_INFO = 2;
502b0f88678b2877a8e9f83cea60f097322b078367yro// for KeyValuePair
512b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_KEY = 1;
522b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_STR = 2;
532b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_INT = 3;
542b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_BOOL = 4;
552b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_VALUE_FLOAT = 5;
562b0f88678b2877a8e9f83cea60f097322b078367yro// for DurationBucketInfo
572b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_START_BUCKET_NANOS = 1;
582b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_END_BUCKET_NANOS = 2;
592b0f88678b2877a8e9f83cea60f097322b078367yroconst int FIELD_ID_DURATION = 3;
602b0f88678b2877a8e9f83cea60f097322b078367yro
61729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao ChenDurationMetricProducer::DurationMetricProducer(const DurationMetric& metric,
62729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                               const int conditionIndex, const size_t startIndex,
63729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                               const size_t stopIndex, const size_t stopAllIndex,
645154a379303ab90a2b2914676a4441917a329b5dYao Chen                                               const sp<ConditionWizard>& wizard,
6593fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen                                               const vector<KeyMatcher>& internalDimension,
6693fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen                                               const uint64_t startTimeNs)
6793fe3a34a02c673eaee4a2d18565ba8df20685cbYao Chen    : MetricProducer(startTimeNs, conditionIndex, wizard),
68729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mMetric(metric),
69729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mStartIndex(startIndex),
70729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen      mStopIndex(stopIndex),
715154a379303ab90a2b2914676a4441917a329b5dYao Chen      mStopAllIndex(stopAllIndex),
725154a379303ab90a2b2914676a4441917a329b5dYao Chen      mInternalDimension(internalDimension) {
73729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: The following boiler plate code appears in all MetricProducers, but we can't abstract
74729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // them in the base class, because the proto generated CountMetric, and DurationMetric are
75729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // not related. Maybe we should add a template in the future??
76729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
77729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000000;
78729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    } else {
79729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mBucketSizeNs = LLONG_MAX;
80729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
81729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
82729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: use UidMap if uid->pkg_name is required
83729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    mDimension.insert(mDimension.begin(), metric.dimension().begin(), metric.dimension().end());
84729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
85729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    if (metric.links().size() > 0) {
86729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
87729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                               metric.links().end());
88729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        mConditionSliced = true;
89729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
90729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
912b0f88678b2877a8e9f83cea60f097322b078367yro    startNewProtoOutputStream(mStartTimeNs);
922b0f88678b2877a8e9f83cea60f097322b078367yro
93729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    VLOG("metric %lld created. bucket size %lld start_time: %lld", metric.metric_id(),
94729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen         (long long)mBucketSizeNs, (long long)mStartTimeNs);
95729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
96729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
97729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao ChenDurationMetricProducer::~DurationMetricProducer() {
98729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    VLOG("~DurationMetric() called");
99729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
100729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1012b0f88678b2877a8e9f83cea60f097322b078367yrovoid DurationMetricProducer::startNewProtoOutputStream(long long startTime) {
1022b0f88678b2877a8e9f83cea60f097322b078367yro    mProto = std::make_unique<ProtoOutputStream>();
1032b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_ID, mMetric.metric_id());
1042b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, startTime);
1052b0f88678b2877a8e9f83cea60f097322b078367yro    mProtoToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
1062b0f88678b2877a8e9f83cea60f097322b078367yro}
1072b0f88678b2877a8e9f83cea60f097322b078367yro
1085154a379303ab90a2b2914676a4441917a329b5dYao Chenunique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
1092b0f88678b2877a8e9f83cea60f097322b078367yro        vector<DurationBucket>& bucket) {
1105154a379303ab90a2b2914676a4441917a329b5dYao Chen    switch (mMetric.type()) {
1115154a379303ab90a2b2914676a4441917a329b5dYao Chen        case DurationMetric_AggregationType_DURATION_SUM:
1125154a379303ab90a2b2914676a4441917a329b5dYao Chen            return make_unique<OringDurationTracker>(mWizard, mConditionTrackerIndex,
1135154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                     mCurrentBucketStartTimeNs, mBucketSizeNs,
1145154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                     bucket);
1155154a379303ab90a2b2914676a4441917a329b5dYao Chen        case DurationMetric_AggregationType_DURATION_MAX_SPARSE:
1165154a379303ab90a2b2914676a4441917a329b5dYao Chen            return make_unique<MaxDurationTracker>(mWizard, mConditionTrackerIndex,
1175154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                   mCurrentBucketStartTimeNs, mBucketSizeNs,
1185154a379303ab90a2b2914676a4441917a329b5dYao Chen                                                   bucket);
1195154a379303ab90a2b2914676a4441917a329b5dYao Chen    }
1205154a379303ab90a2b2914676a4441917a329b5dYao Chen}
1215154a379303ab90a2b2914676a4441917a329b5dYao Chen
122729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenvoid DurationMetricProducer::finish() {
123729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: write the StatsLogReport to dropbox using
124729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // DropboxWriter.
125729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
126729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1275154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onSlicedConditionMayChange(const uint64_t eventTime) {
128729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    VLOG("Metric %lld onSlicedConditionMayChange", mMetric.metric_id());
129729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // Now for each of the on-going event, check if the condition has changed for them.
1305154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(eventTime);
131729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1325154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onSlicedConditionMayChange(eventTime);
133729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
134729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
135729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
1365154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onConditionChanged(const bool conditionMet, const uint64_t eventTime) {
137729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    VLOG("Metric %lld onConditionChanged", mMetric.metric_id());
138729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    mCondition = conditionMet;
139729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // TODO: need to populate the condition change time from the event which triggers the condition
140729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // change, instead of using current time.
1415154a379303ab90a2b2914676a4441917a329b5dYao Chen
1425154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(eventTime);
143729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (auto& pair : mCurrentSlicedDuration) {
1445154a379303ab90a2b2914676a4441917a329b5dYao Chen        pair.second->onConditionChanged(conditionMet, eventTime);
145729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
146729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
147729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
148729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chenstatic void addDurationBucketsToReport(StatsLogReport_DurationMetricDataWrapper& wrapper,
149729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                       const vector<KeyValuePair>& key,
150729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen                                       const vector<DurationBucketInfo>& buckets) {
151729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    DurationMetricData* data = wrapper.add_data();
152729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& kv : key) {
153729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        data->add_dimension()->CopyFrom(kv);
154729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
155729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& bucket : buckets) {
156729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        data->add_bucket_info()->CopyFrom(bucket);
1575154a379303ab90a2b2914676a4441917a329b5dYao Chen        VLOG("\t bucket [%lld - %lld] duration(ns): %lld", bucket.start_bucket_nanos(),
158729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen             bucket.end_bucket_nanos(), bucket.duration_nanos());
159729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
160729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
161729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
162729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao ChenStatsLogReport DurationMetricProducer::onDumpReport() {
1632b0f88678b2877a8e9f83cea60f097322b078367yro    long long endTime = time(nullptr) * NS_PER_SEC;
1642b0f88678b2877a8e9f83cea60f097322b078367yro
165729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // Dump current bucket if it's stale.
166729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // If current bucket is still on-going, don't force dump current bucket.
167729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    // In finish(), We can force dump current bucket.
1682b0f88678b2877a8e9f83cea60f097322b078367yro    flushIfNeeded(endTime);
1692b0f88678b2877a8e9f83cea60f097322b078367yro    VLOG("metric %lld dump report now...", mMetric.metric_id());
170729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
171729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    for (const auto& pair : mPastBuckets) {
172729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        const HashableDimensionKey& hashableKey = pair.first;
1732b0f88678b2877a8e9f83cea60f097322b078367yro        VLOG("  dimension key %s", hashableKey.c_str());
174729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        auto it = mDimensionKeyMap.find(hashableKey);
175729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        if (it == mDimensionKeyMap.end()) {
176729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen            ALOGW("Dimension key %s not found?!?! skip...", hashableKey.c_str());
177729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen            continue;
178729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
1792b0f88678b2877a8e9f83cea60f097322b078367yro        long long wrapperToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_DATA);
1802b0f88678b2877a8e9f83cea60f097322b078367yro
1812b0f88678b2877a8e9f83cea60f097322b078367yro        // First fill dimension (KeyValuePairs).
1822b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& kv : it->second) {
1832b0f88678b2877a8e9f83cea60f097322b078367yro            long long dimensionToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION);
1842b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT32 | FIELD_ID_KEY, kv.key());
1852b0f88678b2877a8e9f83cea60f097322b078367yro            if (kv.has_value_str()) {
1862b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_INT32 | FIELD_ID_VALUE_STR, kv.value_str());
1872b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_int()) {
1882b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_INT, kv.value_int());
1892b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_bool()) {
1902b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_BOOL | FIELD_ID_VALUE_BOOL, kv.value_bool());
1912b0f88678b2877a8e9f83cea60f097322b078367yro            } else if (kv.has_value_float()) {
1922b0f88678b2877a8e9f83cea60f097322b078367yro                mProto->write(FIELD_TYPE_FLOAT | FIELD_ID_VALUE_FLOAT, kv.value_float());
1932b0f88678b2877a8e9f83cea60f097322b078367yro            }
1942b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->end(dimensionToken);
1952b0f88678b2877a8e9f83cea60f097322b078367yro        }
1962b0f88678b2877a8e9f83cea60f097322b078367yro
1972b0f88678b2877a8e9f83cea60f097322b078367yro        // Then fill bucket_info (DurationBucketInfo).
1982b0f88678b2877a8e9f83cea60f097322b078367yro        for (const auto& bucket : pair.second) {
1992b0f88678b2877a8e9f83cea60f097322b078367yro            long long bucketInfoToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_BUCKET_INFO);
2002b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_START_BUCKET_NANOS,
2012b0f88678b2877a8e9f83cea60f097322b078367yro                          (long long)bucket.mBucketStartNs);
2022b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
2032b0f88678b2877a8e9f83cea60f097322b078367yro                          (long long)bucket.mBucketEndNs);
2042b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->write(FIELD_TYPE_INT64 | FIELD_ID_DURATION, (long long)bucket.mDuration);
2052b0f88678b2877a8e9f83cea60f097322b078367yro            mProto->end(bucketInfoToken);
2062b0f88678b2877a8e9f83cea60f097322b078367yro            VLOG("\t bucket [%lld - %lld] duration: %lld", (long long)bucket.mBucketStartNs,
2072b0f88678b2877a8e9f83cea60f097322b078367yro                 (long long)bucket.mBucketEndNs, (long long)bucket.mDuration);
2082b0f88678b2877a8e9f83cea60f097322b078367yro        }
2092b0f88678b2877a8e9f83cea60f097322b078367yro
2102b0f88678b2877a8e9f83cea60f097322b078367yro        mProto->end(wrapperToken);
211729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
2122b0f88678b2877a8e9f83cea60f097322b078367yro
2132b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->end(mProtoToken);
2142b0f88678b2877a8e9f83cea60f097322b078367yro    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS,
2152b0f88678b2877a8e9f83cea60f097322b078367yro                  (long long)mCurrentBucketStartTimeNs);
2162b0f88678b2877a8e9f83cea60f097322b078367yro
2172b0f88678b2877a8e9f83cea60f097322b078367yro    std::unique_ptr<uint8_t[]> buffer = serializeProto();
2182b0f88678b2877a8e9f83cea60f097322b078367yro
2192b0f88678b2877a8e9f83cea60f097322b078367yro    startNewProtoOutputStream(endTime);
2202b0f88678b2877a8e9f83cea60f097322b078367yro    mPastBuckets.clear();
2212b0f88678b2877a8e9f83cea60f097322b078367yro
2222b0f88678b2877a8e9f83cea60f097322b078367yro    // TODO: Once we migrate all MetricProducers to use ProtoOutputStream, we should return this:
2232b0f88678b2877a8e9f83cea60f097322b078367yro    // return std::move(buffer);
2242b0f88678b2877a8e9f83cea60f097322b078367yro    return StatsLogReport();
2252b0f88678b2877a8e9f83cea60f097322b078367yro}
226729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2275154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::flushIfNeeded(uint64_t eventTime) {
2285154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentBucketStartTimeNs + mBucketSizeNs > eventTime) {
229729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
230729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
231729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2325154a379303ab90a2b2914676a4441917a329b5dYao Chen    VLOG("flushing...........");
2335154a379303ab90a2b2914676a4441917a329b5dYao Chen    for (auto it = mCurrentSlicedDuration.begin(); it != mCurrentSlicedDuration.end(); ++it) {
2345154a379303ab90a2b2914676a4441917a329b5dYao Chen        if (it->second->flushIfNeeded(eventTime)) {
2355154a379303ab90a2b2914676a4441917a329b5dYao Chen            VLOG("erase bucket for key %s", it->first.c_str());
2365154a379303ab90a2b2914676a4441917a329b5dYao Chen            mCurrentSlicedDuration.erase(it);
237729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        }
238729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
239729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2405154a379303ab90a2b2914676a4441917a329b5dYao Chen    int numBucketsForward = (eventTime - mCurrentBucketStartTimeNs) / mBucketSizeNs;
2415154a379303ab90a2b2914676a4441917a329b5dYao Chen    mCurrentBucketStartTimeNs += numBucketsForward * mBucketSizeNs;
242729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
243729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2445154a379303ab90a2b2914676a4441917a329b5dYao Chenvoid DurationMetricProducer::onMatchedLogEventInternal(
2455154a379303ab90a2b2914676a4441917a329b5dYao Chen        const size_t matcherIndex, const HashableDimensionKey& eventKey,
2465154a379303ab90a2b2914676a4441917a329b5dYao Chen        const map<string, HashableDimensionKey>& conditionKeys, bool condition,
247b3dda41a5a48ddfa44dc8fa939ab495926a0195dChenjie Yu        const LogEvent& event, bool scheduledPull) {
2485154a379303ab90a2b2914676a4441917a329b5dYao Chen    flushIfNeeded(event.GetTimestampNs());
249729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2505154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (matcherIndex == mStopAllIndex) {
2515154a379303ab90a2b2914676a4441917a329b5dYao Chen        for (auto& pair : mCurrentSlicedDuration) {
2525154a379303ab90a2b2914676a4441917a329b5dYao Chen            pair.second->noteStopAll(event.GetTimestampNs());
2535154a379303ab90a2b2914676a4441917a329b5dYao Chen        }
254729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen        return;
255729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
256729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2575154a379303ab90a2b2914676a4441917a329b5dYao Chen    HashableDimensionKey atomKey = getHashableKey(getDimensionKey(event, mInternalDimension));
258729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2595154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (mCurrentSlicedDuration.find(eventKey) == mCurrentSlicedDuration.end()) {
2605154a379303ab90a2b2914676a4441917a329b5dYao Chen        mCurrentSlicedDuration[eventKey] = createDurationTracker(mPastBuckets[eventKey]);
2615154a379303ab90a2b2914676a4441917a329b5dYao Chen    }
262729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2635154a379303ab90a2b2914676a4441917a329b5dYao Chen    auto it = mCurrentSlicedDuration.find(eventKey);
264729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
2655154a379303ab90a2b2914676a4441917a329b5dYao Chen    if (matcherIndex == mStartIndex) {
2665154a379303ab90a2b2914676a4441917a329b5dYao Chen        it->second->noteStart(atomKey, condition, event.GetTimestampNs(), conditionKeys);
2675154a379303ab90a2b2914676a4441917a329b5dYao Chen    } else if (matcherIndex == mStopIndex) {
2685154a379303ab90a2b2914676a4441917a329b5dYao Chen        it->second->noteStop(atomKey, event.GetTimestampNs());
269729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen    }
270729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}
271729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen
27269007c82625dd8b19bd68d1031191e2ff83b5f49yrosize_t DurationMetricProducer::byteSize() {
2732b0f88678b2877a8e9f83cea60f097322b078367yro  size_t totalSize = 0;
2742b0f88678b2877a8e9f83cea60f097322b078367yro  for (const auto& pair : mPastBuckets) {
2752b0f88678b2877a8e9f83cea60f097322b078367yro      totalSize += pair.second.size() * kBucketSize;
2762b0f88678b2877a8e9f83cea60f097322b078367yro  }
2772b0f88678b2877a8e9f83cea60f097322b078367yro  return totalSize;
27869007c82625dd8b19bd68d1031191e2ff83b5f49yro}
27969007c82625dd8b19bd68d1031191e2ff83b5f49yro
280729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace statsd
281729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace os
282729093df0dd7d7038ad43b16ecdb59a1404f3b50Yao Chen}  // namespace android
283