• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 #ifndef ANDROID_EVENT_METRIC_H_
17 #define ANDROID_EVENT_METRIC_H_
18 
19 #include <media/MediaMetricsItem.h>
20 #include <utils/Timers.h>
21 
22 namespace android {
23 
24 // This is a simple holder for the statistics recorded in EventMetric.
25 struct EventStatistics {
26   // The count of times the event occurred.
27   int64_t count;
28 
29   // The minimum and maximum values recorded in the Record method.
30   double min;
31   double max;
32 
33   // The average (mean) of all values recorded.
34   double mean;
35   // The sum of squared devation. Variance can be calculated from
36   // this value.
37   //    var = sum_squared_deviation / count;
38   double sum_squared_deviation;
39 };
40 
41 // The EventMetric class is used to accumulate stats about an event over time.
42 // A common use case is to track clock timings for a method call or operation.
43 // An EventMetric can break down stats by a dimension specified by the
44 // application. E.g. an application may want to track counts broken out by
45 // error code or the size of some parameter.
46 //
47 // Example:
48 //
49 //   struct C {
50 //     status_t DoWork() {
51 //       unsigned long start_time = now();
52 //       status_t result;
53 //
54 //       // DO WORK and determine result;
55 //
56 //       work_event_.Record(now() - start_time, result);
57 //
58 //       return result;
59 //     }
60 //     EventMetric<status_t> work_event_;
61 //   };
62 //
63 //   C c;
64 //   c.DoWork();
65 //
66 //   std::map<int, int64_t> values;
67 //   metric.ExportValues(
68 //       [&] (int attribute_value, int64_t value) {
69 //            values[attribute_value] = value;
70 //       });
71 //   // Do something with the exported stat.
72 //
73 template<typename AttributeType>
74 class EventMetric {
75  public:
76   // Instantiate the counter with the given metric name and
77   // attribute names. |attribute_names| must not be null.
EventMetric(const std::string & metric_name,const std::string & attribute_name)78   EventMetric(
79       const std::string& metric_name,
80       const std::string& attribute_name)
81           : metric_name_(metric_name),
82             attribute_name_(attribute_name) {}
83 
84   // Increment the count of times the operation occurred with this
85   // combination of attributes.
Record(double value,AttributeType attribute)86   void Record(double value, AttributeType attribute) {
87     if (values_.find(attribute) != values_.end()) {
88       EventStatistics* stats = values_[attribute].get();
89       // Using method of provisional means.
90       double deviation = value - stats->mean;
91       stats->mean = stats->mean + (deviation / stats->count);
92       stats->sum_squared_deviation =
93           stats->sum_squared_deviation + (deviation * (value - stats->mean));
94       stats->count++;
95 
96       stats->min = stats->min < value ? stats->min : value;
97       stats->max = stats->max > value ? stats->max : value;
98     } else {
99       std::unique_ptr<EventStatistics> stats =
100           std::make_unique<EventStatistics>();
101       stats->count = 1;
102       stats->min = value;
103       stats->max = value;
104       stats->mean = value;
105       stats->sum_squared_deviation = 0;
106       values_[attribute] = std::move(stats);
107     }
108   };
109 
110   // Export the metrics to the provided |function|. Each value for Attribute
111   // has a separate set of stats. As such, |function| will be called once per
112   // value of Attribute.
ExportValues(std::function<void (const AttributeType &,const EventStatistics &)> function)113   void ExportValues(
114       std::function<void (const AttributeType&,
115                           const EventStatistics&)> function) const {
116     for (auto it = values_.begin(); it != values_.end(); it++) {
117       function(it->first, *(it->second));
118     }
119   }
120 
metric_name()121   const std::string& metric_name() const { return metric_name_; };
122 
123  private:
124   const std::string metric_name_;
125   const std::string attribute_name_;
126   std::map<AttributeType, std::unique_ptr<struct EventStatistics>> values_;
127 };
128 
129 // The EventTimer is a supporting class for EventMetric instances that are used
130 // to time methods. The EventTimer starts a timer when first in scope, and
131 // records the timing when exiting scope.
132 //
133 // Example:
134 //
135 // EventMetric<int> my_metric;
136 //
137 // {
138 //   EventTimer<int> my_timer(&my_metric);
139 //   // Set the attribute to associate with this timing.
140 //   my_timer.SetAttribtue(42);
141 //
142 //   // Do some work that you want to time.
143 //
144 // }  // The EventTimer destructor will record the the timing in my_metric;
145 //
146 template<typename AttributeType>
147 class EventTimer {
148  public:
EventTimer(EventMetric<AttributeType> * metric)149   explicit EventTimer(EventMetric<AttributeType>* metric)
150       :start_time_(systemTime()), metric_(metric) {
151   }
152 
~EventTimer()153   virtual ~EventTimer() {
154     if (metric_) {
155       metric_->Record(ns2us(systemTime() - start_time_), attribute_);
156     }
157   }
158 
159   // Set the attribute to associate with this timing. E.g. this can be used to
160   // record the return code from the work that was timed.
SetAttribute(const AttributeType & attribute)161   void SetAttribute(const AttributeType& attribute) {
162     attribute_ = attribute;
163   }
164 
165  protected:
166   // Visible for testing only.
167   nsecs_t start_time_;
168 
169  private:
170   EventMetric<AttributeType>* metric_;
171   AttributeType attribute_;
172 };
173 
174 }  // namespace android
175 
176 #endif  // ANDROID_EVENT_METRIC_H_
177