• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <android/util/ProtoOutputStream.h>
20 #include <gtest/gtest_prod.h>
21 #include <kll.h>
22 
23 #include <optional>
24 
25 #include "MetricProducer.h"
26 #include "ValueMetricProducer.h"
27 #include "condition/ConditionTimer.h"
28 #include "condition/ConditionTracker.h"
29 #include "matchers/EventMatcherWizard.h"
30 #include "src/statsd_config.pb.h"
31 #include "stats_log_util.h"
32 
33 using dist_proc::aggregation::KllQuantile;
34 
35 namespace android {
36 namespace os {
37 namespace statsd {
38 
39 // Uses KllQuantile to aggregate values within buckets.
40 //
41 // There are different events that might complete a bucket
42 // - a condition change
43 // - an app upgrade
44 // - an alarm set to the end of the bucket
45 class KllMetricProducer : public ValueMetricProducer<std::unique_ptr<KllQuantile>, Empty> {
46 public:
47     KllMetricProducer(const ConfigKey& key, const KllMetric& kllMetric, const uint64_t protoHash,
48                       const PullOptions& pullOptions, const BucketOptions& bucketOptions,
49                       const WhatOptions& whatOptions, const ConditionOptions& conditionOptions,
50                       const StateOptions& stateOptions, const ActivationOptions& activationOptions,
51                       const GuardrailOptions& guardrailOptions);
52 
getMetricType()53     inline MetricType getMetricType() const override {
54         return METRIC_TYPE_KLL;
55     }
56 
57 protected:
58 private:
getConditionIdForMetric(const StatsdConfig & config,const int configIndex)59     inline optional<int64_t> getConditionIdForMetric(const StatsdConfig& config,
60                                                      const int configIndex) const override {
61         const KllMetric& metric = config.kll_metric(configIndex);
62         return metric.has_condition() ? make_optional(metric.condition()) : nullopt;
63     }
64 
getWhatAtomMatcherIdForMetric(const StatsdConfig & config,const int configIndex)65     inline int64_t getWhatAtomMatcherIdForMetric(const StatsdConfig& config,
66                                                  const int configIndex) const override {
67         return config.kll_metric(configIndex).what();
68     }
69 
getConditionLinksForMetric(const StatsdConfig & config,const int configIndex)70     inline ConditionLinks getConditionLinksForMetric(const StatsdConfig& config,
71                                                      const int configIndex) const override {
72         return config.kll_metric(configIndex).links();
73     }
74 
75     // Determine whether or not a LogEvent can be skipped.
canSkipLogEventLocked(const MetricDimensionKey & eventKey,bool condition,int64_t eventTimeNs,const std::map<int,HashableDimensionKey> & statePrimaryKeys)76     inline bool canSkipLogEventLocked(
77             const MetricDimensionKey& eventKey, bool condition, int64_t eventTimeNs,
78             const std::map<int, HashableDimensionKey>& statePrimaryKeys) const override {
79         // Can only skip if the condition is false.
80         // We assume metric is pushed since KllMetric doesn't support pulled metrics.
81         return !condition;
82     }
83 
84     DumpProtoFields getDumpProtoFields() const override;
85 
aggregatedValueToString(const std::unique_ptr<KllQuantile> & aggregate)86     inline std::string aggregatedValueToString(
87             const std::unique_ptr<KllQuantile>& aggregate) const override {
88         return std::to_string(aggregate->num_values()) + " values";
89     }
90 
multipleBucketsSkipped(const int64_t numBucketsForward)91     inline bool multipleBucketsSkipped(const int64_t numBucketsForward) const override {
92         // Always false because we assume KllMetric is pushed only for now.
93         return false;
94     }
95 
96     // The KllQuantile ptr ownership is transferred to newly created PastBuckets from Intervals.
97     PastBucket<std::unique_ptr<KllQuantile>> buildPartialBucket(
98             int64_t bucketEndTime, std::vector<Interval>& intervals) override;
99 
100     void writePastBucketAggregateToProto(const int aggIndex,
101                                          const std::unique_ptr<KllQuantile>& kll,
102                                          const int sampleSize,
103                                          ProtoOutputStream* const protoOutput) const override;
104 
105     bool aggregateFields(const int64_t eventTimeNs, const MetricDimensionKey& eventKey,
106                          const LogEvent& event, std::vector<Interval>& intervals,
107                          Empty& empty) override;
108 
109     // Internal function to calculate the current used bytes.
110     size_t byteSizeLocked() const override;
111 
112     FRIEND_TEST(KllMetricProducerTest, TestByteSize);
113     FRIEND_TEST(KllMetricProducerTest, TestPushedEventsWithoutCondition);
114     FRIEND_TEST(KllMetricProducerTest, TestPushedEventsWithCondition);
115     FRIEND_TEST(KllMetricProducerTest, TestForcedBucketSplitWhenConditionUnknownSkipsBucket);
116 
117     FRIEND_TEST(KllMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown);
118     FRIEND_TEST(KllMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall);
119     FRIEND_TEST(KllMetricProducerTest_BucketDrop, TestBucketDropWhenDataUnavailable);
120 
121     FRIEND_TEST(KllMetricProducerTest_PartialBucket, TestPushedEventsMultipleBuckets);
122 
123     FRIEND_TEST(ConfigUpdateTest, TestUpdateKllMetrics);
124 };
125 
126 }  // namespace statsd
127 }  // namespace os
128 }  // namespace android
129