blob: fb6017f415f86cbe6356c4b02cb02987b1a43a7e [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
Steve Anton10542f22019-01-11 09:11:00 -080017#include "rtc_base/constructor_magic.h"
asapersson0e9d6d92016-05-23 06:07:55 -070018
19namespace webrtc {
20
21class AggregatedCounter;
22class Clock;
asaperssonfe647f42016-11-01 00:21:34 -070023class Samples;
asapersson0e9d6d92016-05-23 06:07:55 -070024
25// |StatsCounterObserver| is called periodically when a metric is updated.
26class StatsCounterObserver {
27 public:
28 virtual void OnMetricUpdated(int sample) = 0;
29
30 virtual ~StatsCounterObserver() {}
31};
32
33struct AggregatedStats {
asapersson43cb7162016-11-15 08:20:48 -080034 std::string ToString() const;
asapersson076c0112016-11-30 05:17:16 -080035 std::string ToStringWithMultiplier(int multiplier) const;
asapersson43cb7162016-11-15 08:20:48 -080036
asapersson0e9d6d92016-05-23 06:07:55 -070037 int64_t num_samples = 0;
38 int min = -1;
39 int max = -1;
40 int average = -1;
41 // TODO(asapersson): Consider adding median/percentiles.
42};
43
44// Classes which periodically computes a metric.
45//
46// During a period, |kProcessIntervalMs|, different metrics can be computed e.g:
47// - |AvgCounter|: average of samples
48// - |PercentCounter|: percentage of samples
49// - |PermilleCounter|: permille of samples
50//
51// Each periodic metric can be either:
52// - reported to an |observer| each period
53// - aggregated during the call (e.g. min, max, average)
54//
55// periodically computed
56// GetMetric() GetMetric() => AggregatedStats
57// ^ ^ (e.g. min/max/avg)
58// | |
59// | * * * * | ** * * * * | ...
60// |<- process interval ->|
61//
62// (*) - samples
63//
64//
65// Example usage:
66//
67// AvgCounter counter(&clock, nullptr);
68// counter.Add(5);
69// counter.Add(1);
70// counter.Add(6); // process interval passed -> GetMetric() avg:4
71// counter.Add(7);
72// counter.Add(3); // process interval passed -> GetMetric() avg:5
73// counter.Add(10);
74// counter.Add(20); // process interval passed -> GetMetric() avg:15
75// AggregatedStats stats = counter.GetStats();
76// stats: {min:4, max:15, avg:8}
77//
78
79// Note: StatsCounter takes ownership of |observer|.
80
81class StatsCounter {
82 public:
83 virtual ~StatsCounter();
84
asaperssonce2e1362016-09-09 00:13:35 -070085 // Gets metric within an interval. Returns true on success false otherwise.
asapersson0e9d6d92016-05-23 06:07:55 -070086 virtual bool GetMetric(int* metric) const = 0;
87
asaperssonce2e1362016-09-09 00:13:35 -070088 // Gets the value to use for an interval without samples.
89 virtual int GetValueForEmptyInterval() const = 0;
90
91 // Gets aggregated stats (i.e. aggregate of periodically computed metrics).
asapersson0e9d6d92016-05-23 06:07:55 -070092 AggregatedStats GetStats();
93
asaperssonce2e1362016-09-09 00:13:35 -070094 // Reports metrics for elapsed intervals to AggregatedCounter and GetStats.
95 AggregatedStats ProcessAndGetStats();
96
97 // Reports metrics for elapsed intervals to AggregatedCounter and pauses stats
98 // (i.e. empty intervals will be discarded until next sample is added).
99 void ProcessAndPause();
100
asapersson93e1e232017-02-06 05:18:35 -0800101 // As above with a minimum pause time. Added samples within this interval will
102 // not resume the stats (i.e. stop the pause).
103 void ProcessAndPauseForDuration(int64_t min_pause_time_ms);
104
105 // Reports metrics for elapsed intervals to AggregatedCounter and stops pause.
106 void ProcessAndStopPause();
107
asapersson250fd972016-09-08 00:07:21 -0700108 // Checks if a sample has been added (i.e. Add or Set called).
109 bool HasSample() const;
110
asapersson0e9d6d92016-05-23 06:07:55 -0700111 protected:
112 StatsCounter(Clock* clock,
asaperssone402a142016-10-06 23:39:15 -0700113 int64_t process_intervals_ms,
asapersson0e9d6d92016-05-23 06:07:55 -0700114 bool include_empty_intervals,
115 StatsCounterObserver* observer);
116
117 void Add(int sample);
asapersson93e1e232017-02-06 05:18:35 -0800118 void Set(int64_t sample, uint32_t stream_id);
119 void SetLast(int64_t sample, uint32_t stream_id);
asapersson0e9d6d92016-05-23 06:07:55 -0700120
asaperssonfe647f42016-11-01 00:21:34 -0700121 const bool include_empty_intervals_;
asaperssone402a142016-10-06 23:39:15 -0700122 const int64_t process_intervals_ms_;
asaperssonfe647f42016-11-01 00:21:34 -0700123 const std::unique_ptr<AggregatedCounter> aggregated_counter_;
124 const std::unique_ptr<Samples> samples_;
asaperssonce2e1362016-09-09 00:13:35 -0700125
asapersson0e9d6d92016-05-23 06:07:55 -0700126 private:
asaperssonce2e1362016-09-09 00:13:35 -0700127 bool TimeToProcess(int* num_elapsed_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700128 void TryProcess();
asaperssonce2e1362016-09-09 00:13:35 -0700129 void ReportMetricToAggregatedCounter(int value, int num_values_to_add) const;
130 bool IncludeEmptyIntervals() const;
asapersson93e1e232017-02-06 05:18:35 -0800131 void Resume();
132 void ResumeIfMinTimePassed();
asapersson0e9d6d92016-05-23 06:07:55 -0700133
134 Clock* const clock_;
asapersson0e9d6d92016-05-23 06:07:55 -0700135 const std::unique_ptr<StatsCounterObserver> observer_;
asapersson0e9d6d92016-05-23 06:07:55 -0700136 int64_t last_process_time_ms_;
asaperssonce2e1362016-09-09 00:13:35 -0700137 bool paused_;
asapersson93e1e232017-02-06 05:18:35 -0800138 int64_t pause_time_ms_;
139 int64_t min_pause_time_ms_;
asapersson0e9d6d92016-05-23 06:07:55 -0700140};
141
142// AvgCounter: average of samples
143//
144// | * * * | * * | ...
145// | Add(5) Add(1) Add(6) | Add(5) Add(5) |
146// GetMetric | (5 + 1 + 6) / 3 | (5 + 5) / 2 |
147//
asaperssonce2e1362016-09-09 00:13:35 -0700148// |include_empty_intervals|: If set, intervals without samples will be included
149// in the stats. The value for an interval is
150// determined by GetValueForEmptyInterval().
151//
asapersson0e9d6d92016-05-23 06:07:55 -0700152class AvgCounter : public StatsCounter {
153 public:
asaperssonce2e1362016-09-09 00:13:35 -0700154 AvgCounter(Clock* clock,
155 StatsCounterObserver* observer,
156 bool include_empty_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700157 ~AvgCounter() override {}
158
159 void Add(int sample);
160
161 private:
162 bool GetMetric(int* metric) const override;
163
asaperssonce2e1362016-09-09 00:13:35 -0700164 // Returns the last computed metric (i.e. from GetMetric).
165 int GetValueForEmptyInterval() const override;
166
asapersson0e9d6d92016-05-23 06:07:55 -0700167 RTC_DISALLOW_COPY_AND_ASSIGN(AvgCounter);
168};
169
170// MaxCounter: maximum of samples
171//
172// | * * * | * * | ...
173// | Add(5) Add(1) Add(6) | Add(5) Add(5) |
174// GetMetric | max: (5, 1, 6) | max: (5, 5) |
175//
176class MaxCounter : public StatsCounter {
177 public:
asaperssone402a142016-10-06 23:39:15 -0700178 MaxCounter(Clock* clock,
179 StatsCounterObserver* observer,
180 int64_t process_intervals_ms);
asapersson0e9d6d92016-05-23 06:07:55 -0700181 ~MaxCounter() override {}
182
183 void Add(int sample);
184
185 private:
186 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700187 int GetValueForEmptyInterval() const override;
asapersson0e9d6d92016-05-23 06:07:55 -0700188
189 RTC_DISALLOW_COPY_AND_ASSIGN(MaxCounter);
190};
191
192// PercentCounter: percentage of samples
193//
194// | * * * | * * | ...
195// | Add(T) Add(F) Add(T) | Add(F) Add(T) |
196// GetMetric | 100 * 2 / 3 | 100 * 1 / 2 |
197//
198class PercentCounter : public StatsCounter {
199 public:
200 PercentCounter(Clock* clock, StatsCounterObserver* observer);
201 ~PercentCounter() override {}
202
203 void Add(bool sample);
204
205 private:
206 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700207 int GetValueForEmptyInterval() const override;
asapersson0e9d6d92016-05-23 06:07:55 -0700208
209 RTC_DISALLOW_COPY_AND_ASSIGN(PercentCounter);
210};
211
212// PermilleCounter: permille of samples
213//
214// | * * * | * * | ...
215// | Add(T) Add(F) Add(T) | Add(F) Add(T) |
216// GetMetric | 1000 * 2 / 3 | 1000 * 1 / 2 |
217//
218class PermilleCounter : public StatsCounter {
219 public:
220 PermilleCounter(Clock* clock, StatsCounterObserver* observer);
221 ~PermilleCounter() override {}
222
223 void Add(bool sample);
224
225 private:
226 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700227 int GetValueForEmptyInterval() const override;
asapersson0e9d6d92016-05-23 06:07:55 -0700228
229 RTC_DISALLOW_COPY_AND_ASSIGN(PermilleCounter);
230};
231
232// RateCounter: units per second
233//
234// | * * * | * * | ...
235// | Add(5) Add(1) Add(6) | Add(5) Add(5) |
236// |<------ 2 sec ------->| |
237// GetMetric | (5 + 1 + 6) / 2 | (5 + 5) / 2 |
238//
asaperssonce2e1362016-09-09 00:13:35 -0700239// |include_empty_intervals|: If set, intervals without samples will be included
240// in the stats. The value for an interval is
241// determined by GetValueForEmptyInterval().
242//
asapersson0e9d6d92016-05-23 06:07:55 -0700243class RateCounter : public StatsCounter {
244 public:
asapersson5093b382016-08-15 01:20:30 -0700245 RateCounter(Clock* clock,
246 StatsCounterObserver* observer,
247 bool include_empty_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700248 ~RateCounter() override {}
249
250 void Add(int sample);
251
252 private:
253 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700254 int GetValueForEmptyInterval() const override; // Returns zero.
asapersson0e9d6d92016-05-23 06:07:55 -0700255
256 RTC_DISALLOW_COPY_AND_ASSIGN(RateCounter);
257};
258
259// RateAccCounter: units per second (used for counters)
260//
261// | * * * | * * | ...
262// | Set(5) Set(6) Set(8) | Set(11) Set(13) |
263// |<------ 2 sec ------->| |
asapersson93e1e232017-02-06 05:18:35 -0800264// GetMetric | (8 - 0) / 2 | (13 - 8) / 2 |
asapersson0e9d6d92016-05-23 06:07:55 -0700265//
asaperssonce2e1362016-09-09 00:13:35 -0700266// |include_empty_intervals|: If set, intervals without samples will be included
267// in the stats. The value for an interval is
268// determined by GetValueForEmptyInterval().
269//
asapersson0e9d6d92016-05-23 06:07:55 -0700270class RateAccCounter : public StatsCounter {
271 public:
asapersson5093b382016-08-15 01:20:30 -0700272 RateAccCounter(Clock* clock,
273 StatsCounterObserver* observer,
274 bool include_empty_intervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700275 ~RateAccCounter() override {}
276
asapersson93e1e232017-02-06 05:18:35 -0800277 void Set(int64_t sample, uint32_t stream_id);
278
279 // Sets the value for previous interval.
280 // To be used if a value other than zero is initially required.
281 void SetLast(int64_t sample, uint32_t stream_id);
asapersson0e9d6d92016-05-23 06:07:55 -0700282
283 private:
284 bool GetMetric(int* metric) const override;
asaperssonce2e1362016-09-09 00:13:35 -0700285 int GetValueForEmptyInterval() const override; // Returns zero.
asapersson0e9d6d92016-05-23 06:07:55 -0700286
287 RTC_DISALLOW_COPY_AND_ASSIGN(RateAccCounter);
288};
289
290} // namespace webrtc
291
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200292#endif // VIDEO_STATS_COUNTER_H_