Line data Source code
1 : /*
2 : * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #ifndef WEBRTC_VIDEO_STATS_COUNTER_H_
12 : #define WEBRTC_VIDEO_STATS_COUNTER_H_
13 :
14 : #include <memory>
15 : #include <string>
16 :
17 : #include "webrtc/base/constructormagic.h"
18 : #include "webrtc/typedefs.h"
19 :
20 : namespace webrtc {
21 :
22 : class AggregatedCounter;
23 : class Clock;
24 : class Samples;
25 :
26 : // |StatsCounterObserver| is called periodically when a metric is updated.
27 : class StatsCounterObserver {
28 : public:
29 : virtual void OnMetricUpdated(int sample) = 0;
30 :
31 : virtual ~StatsCounterObserver() {}
32 : };
33 :
34 0 : struct AggregatedStats {
35 : std::string ToString() const;
36 : std::string ToStringWithMultiplier(int multiplier) const;
37 :
38 : int64_t num_samples = 0;
39 : int min = -1;
40 : int max = -1;
41 : int average = -1;
42 : // TODO(asapersson): Consider adding median/percentiles.
43 : };
44 :
45 : // Classes which periodically computes a metric.
46 : //
47 : // During a period, |kProcessIntervalMs|, different metrics can be computed e.g:
48 : // - |AvgCounter|: average of samples
49 : // - |PercentCounter|: percentage of samples
50 : // - |PermilleCounter|: permille of samples
51 : //
52 : // Each periodic metric can be either:
53 : // - reported to an |observer| each period
54 : // - aggregated during the call (e.g. min, max, average)
55 : //
56 : // periodically computed
57 : // GetMetric() GetMetric() => AggregatedStats
58 : // ^ ^ (e.g. min/max/avg)
59 : // | |
60 : // | * * * * | ** * * * * | ...
61 : // |<- process interval ->|
62 : //
63 : // (*) - samples
64 : //
65 : //
66 : // Example usage:
67 : //
68 : // AvgCounter counter(&clock, nullptr);
69 : // counter.Add(5);
70 : // counter.Add(1);
71 : // counter.Add(6); // process interval passed -> GetMetric() avg:4
72 : // counter.Add(7);
73 : // counter.Add(3); // process interval passed -> GetMetric() avg:5
74 : // counter.Add(10);
75 : // counter.Add(20); // process interval passed -> GetMetric() avg:15
76 : // AggregatedStats stats = counter.GetStats();
77 : // stats: {min:4, max:15, avg:8}
78 : //
79 :
80 : // Note: StatsCounter takes ownership of |observer|.
81 :
82 : class StatsCounter {
83 : public:
84 : virtual ~StatsCounter();
85 :
86 : // Gets metric within an interval. Returns true on success false otherwise.
87 : virtual bool GetMetric(int* metric) const = 0;
88 :
89 : // Gets the value to use for an interval without samples.
90 : virtual int GetValueForEmptyInterval() const = 0;
91 :
92 : // Gets aggregated stats (i.e. aggregate of periodically computed metrics).
93 : AggregatedStats GetStats();
94 :
95 : // Reports metrics for elapsed intervals to AggregatedCounter and GetStats.
96 : AggregatedStats ProcessAndGetStats();
97 :
98 : // Reports metrics for elapsed intervals to AggregatedCounter and pauses stats
99 : // (i.e. empty intervals will be discarded until next sample is added).
100 : void ProcessAndPause();
101 :
102 : // Checks if a sample has been added (i.e. Add or Set called).
103 : bool HasSample() const;
104 :
105 : protected:
106 : StatsCounter(Clock* clock,
107 : int64_t process_intervals_ms,
108 : bool include_empty_intervals,
109 : StatsCounterObserver* observer);
110 :
111 : void Add(int sample);
112 : void Set(int sample, uint32_t stream_id);
113 :
114 : const bool include_empty_intervals_;
115 : const int64_t process_intervals_ms_;
116 : const std::unique_ptr<AggregatedCounter> aggregated_counter_;
117 : const std::unique_ptr<Samples> samples_;
118 :
119 : private:
120 : bool TimeToProcess(int* num_elapsed_intervals);
121 : void TryProcess();
122 : void ReportMetricToAggregatedCounter(int value, int num_values_to_add) const;
123 : bool IncludeEmptyIntervals() const;
124 :
125 : Clock* const clock_;
126 : const std::unique_ptr<StatsCounterObserver> observer_;
127 : int64_t last_process_time_ms_;
128 : bool paused_;
129 : };
130 :
131 : // AvgCounter: average of samples
132 : //
133 : // | * * * | * * | ...
134 : // | Add(5) Add(1) Add(6) | Add(5) Add(5) |
135 : // GetMetric | (5 + 1 + 6) / 3 | (5 + 5) / 2 |
136 : //
137 : // |include_empty_intervals|: If set, intervals without samples will be included
138 : // in the stats. The value for an interval is
139 : // determined by GetValueForEmptyInterval().
140 : //
141 : class AvgCounter : public StatsCounter {
142 : public:
143 : AvgCounter(Clock* clock,
144 : StatsCounterObserver* observer,
145 : bool include_empty_intervals);
146 0 : ~AvgCounter() override {}
147 :
148 : void Add(int sample);
149 :
150 : private:
151 : bool GetMetric(int* metric) const override;
152 :
153 : // Returns the last computed metric (i.e. from GetMetric).
154 : int GetValueForEmptyInterval() const override;
155 :
156 : RTC_DISALLOW_COPY_AND_ASSIGN(AvgCounter);
157 : };
158 :
159 : // MaxCounter: maximum of samples
160 : //
161 : // | * * * | * * | ...
162 : // | Add(5) Add(1) Add(6) | Add(5) Add(5) |
163 : // GetMetric | max: (5, 1, 6) | max: (5, 5) |
164 : //
165 : class MaxCounter : public StatsCounter {
166 : public:
167 : MaxCounter(Clock* clock,
168 : StatsCounterObserver* observer,
169 : int64_t process_intervals_ms);
170 0 : ~MaxCounter() override {}
171 :
172 : void Add(int sample);
173 :
174 : private:
175 : bool GetMetric(int* metric) const override;
176 : int GetValueForEmptyInterval() const override;
177 :
178 : RTC_DISALLOW_COPY_AND_ASSIGN(MaxCounter);
179 : };
180 :
181 : // PercentCounter: percentage of samples
182 : //
183 : // | * * * | * * | ...
184 : // | Add(T) Add(F) Add(T) | Add(F) Add(T) |
185 : // GetMetric | 100 * 2 / 3 | 100 * 1 / 2 |
186 : //
187 : class PercentCounter : public StatsCounter {
188 : public:
189 : PercentCounter(Clock* clock, StatsCounterObserver* observer);
190 0 : ~PercentCounter() override {}
191 :
192 : void Add(bool sample);
193 :
194 : private:
195 : bool GetMetric(int* metric) const override;
196 : int GetValueForEmptyInterval() const override;
197 :
198 : RTC_DISALLOW_COPY_AND_ASSIGN(PercentCounter);
199 : };
200 :
201 : // PermilleCounter: permille of samples
202 : //
203 : // | * * * | * * | ...
204 : // | Add(T) Add(F) Add(T) | Add(F) Add(T) |
205 : // GetMetric | 1000 * 2 / 3 | 1000 * 1 / 2 |
206 : //
207 : class PermilleCounter : public StatsCounter {
208 : public:
209 : PermilleCounter(Clock* clock, StatsCounterObserver* observer);
210 0 : ~PermilleCounter() override {}
211 :
212 : void Add(bool sample);
213 :
214 : private:
215 : bool GetMetric(int* metric) const override;
216 : int GetValueForEmptyInterval() const override;
217 :
218 : RTC_DISALLOW_COPY_AND_ASSIGN(PermilleCounter);
219 : };
220 :
221 : // RateCounter: units per second
222 : //
223 : // | * * * | * * | ...
224 : // | Add(5) Add(1) Add(6) | Add(5) Add(5) |
225 : // |<------ 2 sec ------->| |
226 : // GetMetric | (5 + 1 + 6) / 2 | (5 + 5) / 2 |
227 : //
228 : // |include_empty_intervals|: If set, intervals without samples will be included
229 : // in the stats. The value for an interval is
230 : // determined by GetValueForEmptyInterval().
231 : //
232 : class RateCounter : public StatsCounter {
233 : public:
234 : RateCounter(Clock* clock,
235 : StatsCounterObserver* observer,
236 : bool include_empty_intervals);
237 0 : ~RateCounter() override {}
238 :
239 : void Add(int sample);
240 :
241 : private:
242 : bool GetMetric(int* metric) const override;
243 : int GetValueForEmptyInterval() const override; // Returns zero.
244 :
245 : RTC_DISALLOW_COPY_AND_ASSIGN(RateCounter);
246 : };
247 :
248 : // RateAccCounter: units per second (used for counters)
249 : //
250 : // | * * * | * * | ...
251 : // | Set(5) Set(6) Set(8) | Set(11) Set(13) |
252 : // |<------ 2 sec ------->| |
253 : // GetMetric | 8 / 2 | (13 - 8) / 2 |
254 : //
255 : // |include_empty_intervals|: If set, intervals without samples will be included
256 : // in the stats. The value for an interval is
257 : // determined by GetValueForEmptyInterval().
258 : //
259 : class RateAccCounter : public StatsCounter {
260 : public:
261 : RateAccCounter(Clock* clock,
262 : StatsCounterObserver* observer,
263 : bool include_empty_intervals);
264 0 : ~RateAccCounter() override {}
265 :
266 : void Set(int sample, uint32_t stream_id);
267 :
268 : private:
269 : bool GetMetric(int* metric) const override;
270 : int GetValueForEmptyInterval() const override; // Returns zero.
271 :
272 : RTC_DISALLOW_COPY_AND_ASSIGN(RateAccCounter);
273 : };
274 :
275 : } // namespace webrtc
276 :
277 : #endif // WEBRTC_VIDEO_STATS_COUNTER_H_
|