blob: 5a52e86bc964499399f5b7148c8e2bf1f5a20d24 [file] [log] [blame]
asapersson0e9d6d92016-05-23 06:07:55 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef VIDEO_STATS_COUNTER_H_
12#define VIDEO_STATS_COUNTER_H_
asapersson0e9d6d92016-05-23 06:07:55 -070013
14#include <memory>
asapersson43cb7162016-11-15 08:20:48 -080015#include <string>
asapersson0e9d6d92016-05-23 06:07:55 -070016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/constructormagic.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020018#include "typedefs.h" // NOLINT(build/include)
asapersson0e9d6d92016-05-23 06:07:55 -070019
20namespace webrtc {
21
22class AggregatedCounter;
23class Clock;
asaperssonfe647f42016-11-01 00:21:34 -070024class Samples;
asapersson0e9d6d92016-05-23 06:07:55 -070025
26// |StatsCounterObserver| is called periodically when a metric is updated.
27class StatsCounterObserver {
28 public:
29 virtual void OnMetricUpdated(int sample) = 0;
30
31 virtual ~StatsCounterObserver() {}
32};
33
34struct AggregatedStats {
asapersson43cb7162016-11-15 08:20:48 -080035 std::string ToString() const;
asapersson076c0112016-11-30 05:17:16 -080036 std::string ToStringWithMultiplier(int multiplier) const;
asapersson43cb7162016-11-15 08:20:48 -080037
asapersson0e9d6d92016-05-23 06:07:55 -070038 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
82class StatsCounter {
83 public:
84 virtual ~StatsCounter();
85
asaperssonce2e1362016-09-09 00:13:35 -070086 // Gets metric within an interval. Returns true on success false otherwise.
asapersson0e9d6d92016-05-23 06:07:55 -070087 virtual bool GetMetric(int* metric) const = 0;
88
asaperssonce2e1362016-09-09 00:13:35 -070089 // 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).
asapersson0e9d6d92016-05-23 06:07:55 -070093 AggregatedStats GetStats();
94
asaperssonce2e1362016-09-09 00:13:35 -070095 // 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
asapersson93e1e232017-02-06 05:18:35 -0800102 // As above with a minimum pause time. Added samples within this interval will
103 // not resume the stats (i.e. stop the pause).
104 void ProcessAndPauseForDuration(int64_t min_pause_time_ms);
105
106 // Reports metrics for elapsed intervals to AggregatedCounter and stops pause.
107 void ProcessAndStopPause();
108
asapersson250fd972016-09-08 00:07:21 -0700109 // Checks if a sample has been added (i.e. Add or Set called).
110 bool HasSample() const;
111
asapersson0e9d6d92016-05-23 06:07:55 -0700112 protected:
113 StatsCounter(Clock* clock,
asaperssone402a142016-10-06 23:39:15 -0700114 int64_t process_intervals_ms,
asapersson0e9d6d92016-05-23 06:07:55 -0700115 bool include_empty_intervals,
116 StatsCounterObserver* observer);
117
118 void Add(int sample);
asapersson93e1e232017-02-06 05:18:35 -0800119 void Set(int64_t sample, uint32_t stream_id);
120 void SetLast(int64_t sample, uint32_t stream_id);
asapersson0e9d6d92016-05-23 06:07:55 -0700121
asaperssonfe647f42016-11-01 00:21:34 -0700122 const bool include_empty_intervals_;
asaperssone402a142016-10-06 23:39:15 -0700123 const int64_t process_intervals_ms_;
asaperssonfe647f42016-11-01 00:21:34 -0700124 const std::unique_ptr<AggregatedCounter> aggregated_counter_;
125 const std::unique_ptr<Samples> samples_;
asaperssonce2e1362016-09-09 00:13:35 -0700126
asapersson0e9d6d92016-05-23 06:07:55 -0700127 private:
asaperssonce2e1362016-09-09 00:13:35 -0700128 bool TimeToProcess(int* num_elapsed_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700129 void TryProcess();
asaperssonce2e1362016-09-09 00:13:35 -0700130 void ReportMetricToAggregatedCounter(int value, int num_values_to_add) const;
131 bool IncludeEmptyIntervals() const;
asapersson93e1e232017-02-06 05:18:35 -0800132 void Resume();
133 void ResumeIfMinTimePassed();
asapersson0e9d6d92016-05-23 06:07:55 -0700134
135 Clock* const clock_;
asapersson0e9d6d92016-05-23 06:07:55 -0700136 const std::unique_ptr<StatsCounterObserver> observer_;
asapersson0e9d6d92016-05-23 06:07:55 -0700137 int64_t last_process_time_ms_;
asaperssonce2e1362016-09-09 00:13:35 -0700138 bool paused_;
asapersson93e1e232017-02-06 05:18:35 -0800139 int64_t pause_time_ms_;
140 int64_t min_pause_time_ms_;
asapersson0e9d6d92016-05-23 06:07:55 -0700141};
142
143// AvgCounter: average of samples
144//
145// | * * * | * * | ...
146// | Add(5) Add(1) Add(6) | Add(5) Add(5) |
147// GetMetric | (5 + 1 + 6) / 3 | (5 + 5) / 2 |
148//
asaperssonce2e1362016-09-09 00:13:35 -0700149// |include_empty_intervals|: If set, intervals without samples will be included
150// in the stats. The value for an interval is
151// determined by GetValueForEmptyInterval().
152//
asapersson0e9d6d92016-05-23 06:07:55 -0700153class AvgCounter : public StatsCounter {
154 public:
asaperssonce2e1362016-09-09 00:13:35 -0700155 AvgCounter(Clock* clock,
156 StatsCounterObserver* observer,
157 bool include_empty_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700158 ~AvgCounter() override {}
159
160 void Add(int sample);
161
162 private:
163 bool GetMetric(int* metric) const override;
164
asaperssonce2e1362016-09-09 00:13:35 -0700165 // Returns the last computed metric (i.e. from GetMetric).
166 int GetValueForEmptyInterval() const override;
167
asapersson0e9d6d92016-05-23 06:07:55 -0700168 RTC_DISALLOW_COPY_AND_ASSIGN(AvgCounter);
169};
170
171// MaxCounter: maximum of samples
172//
173// | * * * | * * | ...
174// | Add(5) Add(1) Add(6) | Add(5) Add(5) |
175// GetMetric | max: (5, 1, 6) | max: (5, 5) |
176//
177class MaxCounter : public StatsCounter {
178 public:
asaperssone402a142016-10-06 23:39:15 -0700179 MaxCounter(Clock* clock,
180 StatsCounterObserver* observer,
181 int64_t process_intervals_ms);
asapersson0e9d6d92016-05-23 06:07:55 -0700182 ~MaxCounter() override {}
183
184 void Add(int sample);
185
186 private:
187 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700188 int GetValueForEmptyInterval() const override;
asapersson0e9d6d92016-05-23 06:07:55 -0700189
190 RTC_DISALLOW_COPY_AND_ASSIGN(MaxCounter);
191};
192
193// PercentCounter: percentage of samples
194//
195// | * * * | * * | ...
196// | Add(T) Add(F) Add(T) | Add(F) Add(T) |
197// GetMetric | 100 * 2 / 3 | 100 * 1 / 2 |
198//
199class PercentCounter : public StatsCounter {
200 public:
201 PercentCounter(Clock* clock, StatsCounterObserver* observer);
202 ~PercentCounter() override {}
203
204 void Add(bool sample);
205
206 private:
207 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700208 int GetValueForEmptyInterval() const override;
asapersson0e9d6d92016-05-23 06:07:55 -0700209
210 RTC_DISALLOW_COPY_AND_ASSIGN(PercentCounter);
211};
212
213// PermilleCounter: permille of samples
214//
215// | * * * | * * | ...
216// | Add(T) Add(F) Add(T) | Add(F) Add(T) |
217// GetMetric | 1000 * 2 / 3 | 1000 * 1 / 2 |
218//
219class PermilleCounter : public StatsCounter {
220 public:
221 PermilleCounter(Clock* clock, StatsCounterObserver* observer);
222 ~PermilleCounter() override {}
223
224 void Add(bool sample);
225
226 private:
227 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700228 int GetValueForEmptyInterval() const override;
asapersson0e9d6d92016-05-23 06:07:55 -0700229
230 RTC_DISALLOW_COPY_AND_ASSIGN(PermilleCounter);
231};
232
233// RateCounter: units per second
234//
235// | * * * | * * | ...
236// | Add(5) Add(1) Add(6) | Add(5) Add(5) |
237// |<------ 2 sec ------->| |
238// GetMetric | (5 + 1 + 6) / 2 | (5 + 5) / 2 |
239//
asaperssonce2e1362016-09-09 00:13:35 -0700240// |include_empty_intervals|: If set, intervals without samples will be included
241// in the stats. The value for an interval is
242// determined by GetValueForEmptyInterval().
243//
asapersson0e9d6d92016-05-23 06:07:55 -0700244class RateCounter : public StatsCounter {
245 public:
asapersson5093b382016-08-15 01:20:30 -0700246 RateCounter(Clock* clock,
247 StatsCounterObserver* observer,
248 bool include_empty_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700249 ~RateCounter() override {}
250
251 void Add(int sample);
252
253 private:
254 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700255 int GetValueForEmptyInterval() const override; // Returns zero.
asapersson0e9d6d92016-05-23 06:07:55 -0700256
257 RTC_DISALLOW_COPY_AND_ASSIGN(RateCounter);
258};
259
260// RateAccCounter: units per second (used for counters)
261//
262// | * * * | * * | ...
263// | Set(5) Set(6) Set(8) | Set(11) Set(13) |
264// |<------ 2 sec ------->| |
asapersson93e1e232017-02-06 05:18:35 -0800265// GetMetric | (8 - 0) / 2 | (13 - 8) / 2 |
asapersson0e9d6d92016-05-23 06:07:55 -0700266//
asaperssonce2e1362016-09-09 00:13:35 -0700267// |include_empty_intervals|: If set, intervals without samples will be included
268// in the stats. The value for an interval is
269// determined by GetValueForEmptyInterval().
270//
asapersson0e9d6d92016-05-23 06:07:55 -0700271class RateAccCounter : public StatsCounter {
272 public:
asapersson5093b382016-08-15 01:20:30 -0700273 RateAccCounter(Clock* clock,
274 StatsCounterObserver* observer,
275 bool include_empty_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700276 ~RateAccCounter() override {}
277
asapersson93e1e232017-02-06 05:18:35 -0800278 void Set(int64_t sample, uint32_t stream_id);
279
280 // Sets the value for previous interval.
281 // To be used if a value other than zero is initially required.
282 void SetLast(int64_t sample, uint32_t stream_id);
asapersson0e9d6d92016-05-23 06:07:55 -0700283
284 private:
285 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700286 int GetValueForEmptyInterval() const override; // Returns zero.
asapersson0e9d6d92016-05-23 06:07:55 -0700287
288 RTC_DISALLOW_COPY_AND_ASSIGN(RateAccCounter);
289};
290
291} // namespace webrtc
292
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200293#endif // VIDEO_STATS_COUNTER_H_