stats_counter.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. #ifndef VIDEO_STATS_COUNTER_H_
  11. #define VIDEO_STATS_COUNTER_H_
  12. #include <memory>
  13. #include <string>
  14. #include "rtc_base/constructor_magic.h"
  15. namespace webrtc {
  16. class AggregatedCounter;
  17. class Clock;
  18. class Samples;
  19. // |StatsCounterObserver| is called periodically when a metric is updated.
  20. class StatsCounterObserver {
  21. public:
  22. virtual void OnMetricUpdated(int sample) = 0;
  23. virtual ~StatsCounterObserver() {}
  24. };
  25. struct AggregatedStats {
  26. std::string ToString() const;
  27. std::string ToStringWithMultiplier(int multiplier) const;
  28. int64_t num_samples = 0;
  29. int min = -1;
  30. int max = -1;
  31. int average = -1;
  32. // TODO(asapersson): Consider adding median/percentiles.
  33. };
  34. // Classes which periodically computes a metric.
  35. //
  36. // During a period, |kProcessIntervalMs|, different metrics can be computed e.g:
  37. // - |AvgCounter|: average of samples
  38. // - |PercentCounter|: percentage of samples
  39. // - |PermilleCounter|: permille of samples
  40. //
  41. // Each periodic metric can be either:
  42. // - reported to an |observer| each period
  43. // - aggregated during the call (e.g. min, max, average)
  44. //
  45. // periodically computed
  46. // GetMetric() GetMetric() => AggregatedStats
  47. // ^ ^ (e.g. min/max/avg)
  48. // | |
  49. // | * * * * | ** * * * * | ...
  50. // |<- process interval ->|
  51. //
  52. // (*) - samples
  53. //
  54. //
  55. // Example usage:
  56. //
  57. // AvgCounter counter(&clock, nullptr);
  58. // counter.Add(5);
  59. // counter.Add(1);
  60. // counter.Add(6); // process interval passed -> GetMetric() avg:4
  61. // counter.Add(7);
  62. // counter.Add(3); // process interval passed -> GetMetric() avg:5
  63. // counter.Add(10);
  64. // counter.Add(20); // process interval passed -> GetMetric() avg:15
  65. // AggregatedStats stats = counter.GetStats();
  66. // stats: {min:4, max:15, avg:8}
  67. //
  68. // Note: StatsCounter takes ownership of |observer|.
  69. class StatsCounter {
  70. public:
  71. virtual ~StatsCounter();
  72. // Gets metric within an interval. Returns true on success false otherwise.
  73. virtual bool GetMetric(int* metric) const = 0;
  74. // Gets the value to use for an interval without samples.
  75. virtual int GetValueForEmptyInterval() const = 0;
  76. // Gets aggregated stats (i.e. aggregate of periodically computed metrics).
  77. AggregatedStats GetStats();
  78. // Reports metrics for elapsed intervals to AggregatedCounter and GetStats.
  79. AggregatedStats ProcessAndGetStats();
  80. // Reports metrics for elapsed intervals to AggregatedCounter and pauses stats
  81. // (i.e. empty intervals will be discarded until next sample is added).
  82. void ProcessAndPause();
  83. // As above with a minimum pause time. Added samples within this interval will
  84. // not resume the stats (i.e. stop the pause).
  85. void ProcessAndPauseForDuration(int64_t min_pause_time_ms);
  86. // Reports metrics for elapsed intervals to AggregatedCounter and stops pause.
  87. void ProcessAndStopPause();
  88. // Checks if a sample has been added (i.e. Add or Set called).
  89. bool HasSample() const;
  90. protected:
  91. StatsCounter(Clock* clock,
  92. int64_t process_intervals_ms,
  93. bool include_empty_intervals,
  94. StatsCounterObserver* observer);
  95. void Add(int sample);
  96. void Set(int64_t sample, uint32_t stream_id);
  97. void SetLast(int64_t sample, uint32_t stream_id);
  98. const bool include_empty_intervals_;
  99. const int64_t process_intervals_ms_;
  100. const std::unique_ptr<AggregatedCounter> aggregated_counter_;
  101. const std::unique_ptr<Samples> samples_;
  102. private:
  103. bool TimeToProcess(int* num_elapsed_intervals);
  104. void TryProcess();
  105. void ReportMetricToAggregatedCounter(int value, int num_values_to_add) const;
  106. bool IncludeEmptyIntervals() const;
  107. void Resume();
  108. void ResumeIfMinTimePassed();
  109. Clock* const clock_;
  110. const std::unique_ptr<StatsCounterObserver> observer_;
  111. int64_t last_process_time_ms_;
  112. bool paused_;
  113. int64_t pause_time_ms_;
  114. int64_t min_pause_time_ms_;
  115. };
  116. // AvgCounter: average of samples
  117. //
  118. // | * * * | * * | ...
  119. // | Add(5) Add(1) Add(6) | Add(5) Add(5) |
  120. // GetMetric | (5 + 1 + 6) / 3 | (5 + 5) / 2 |
  121. //
  122. // |include_empty_intervals|: If set, intervals without samples will be included
  123. // in the stats. The value for an interval is
  124. // determined by GetValueForEmptyInterval().
  125. //
  126. class AvgCounter : public StatsCounter {
  127. public:
  128. AvgCounter(Clock* clock,
  129. StatsCounterObserver* observer,
  130. bool include_empty_intervals);
  131. ~AvgCounter() override {}
  132. void Add(int sample);
  133. private:
  134. bool GetMetric(int* metric) const override;
  135. // Returns the last computed metric (i.e. from GetMetric).
  136. int GetValueForEmptyInterval() const override;
  137. RTC_DISALLOW_COPY_AND_ASSIGN(AvgCounter);
  138. };
  139. // MaxCounter: maximum of samples
  140. //
  141. // | * * * | * * | ...
  142. // | Add(5) Add(1) Add(6) | Add(5) Add(5) |
  143. // GetMetric | max: (5, 1, 6) | max: (5, 5) |
  144. //
  145. class MaxCounter : public StatsCounter {
  146. public:
  147. MaxCounter(Clock* clock,
  148. StatsCounterObserver* observer,
  149. int64_t process_intervals_ms);
  150. ~MaxCounter() override {}
  151. void Add(int sample);
  152. private:
  153. bool GetMetric(int* metric) const override;
  154. int GetValueForEmptyInterval() const override;
  155. RTC_DISALLOW_COPY_AND_ASSIGN(MaxCounter);
  156. };
  157. // PercentCounter: percentage of samples
  158. //
  159. // | * * * | * * | ...
  160. // | Add(T) Add(F) Add(T) | Add(F) Add(T) |
  161. // GetMetric | 100 * 2 / 3 | 100 * 1 / 2 |
  162. //
  163. class PercentCounter : public StatsCounter {
  164. public:
  165. PercentCounter(Clock* clock, StatsCounterObserver* observer);
  166. ~PercentCounter() override {}
  167. void Add(bool sample);
  168. private:
  169. bool GetMetric(int* metric) const override;
  170. int GetValueForEmptyInterval() const override;
  171. RTC_DISALLOW_COPY_AND_ASSIGN(PercentCounter);
  172. };
  173. // PermilleCounter: permille of samples
  174. //
  175. // | * * * | * * | ...
  176. // | Add(T) Add(F) Add(T) | Add(F) Add(T) |
  177. // GetMetric | 1000 * 2 / 3 | 1000 * 1 / 2 |
  178. //
  179. class PermilleCounter : public StatsCounter {
  180. public:
  181. PermilleCounter(Clock* clock, StatsCounterObserver* observer);
  182. ~PermilleCounter() override {}
  183. void Add(bool sample);
  184. private:
  185. bool GetMetric(int* metric) const override;
  186. int GetValueForEmptyInterval() const override;
  187. RTC_DISALLOW_COPY_AND_ASSIGN(PermilleCounter);
  188. };
  189. // RateCounter: units per second
  190. //
  191. // | * * * | * * | ...
  192. // | Add(5) Add(1) Add(6) | Add(5) Add(5) |
  193. // |<------ 2 sec ------->| |
  194. // GetMetric | (5 + 1 + 6) / 2 | (5 + 5) / 2 |
  195. //
  196. // |include_empty_intervals|: If set, intervals without samples will be included
  197. // in the stats. The value for an interval is
  198. // determined by GetValueForEmptyInterval().
  199. //
  200. class RateCounter : public StatsCounter {
  201. public:
  202. RateCounter(Clock* clock,
  203. StatsCounterObserver* observer,
  204. bool include_empty_intervals);
  205. ~RateCounter() override {}
  206. void Add(int sample);
  207. private:
  208. bool GetMetric(int* metric) const override;
  209. int GetValueForEmptyInterval() const override; // Returns zero.
  210. RTC_DISALLOW_COPY_AND_ASSIGN(RateCounter);
  211. };
  212. // RateAccCounter: units per second (used for counters)
  213. //
  214. // | * * * | * * | ...
  215. // | Set(5) Set(6) Set(8) | Set(11) Set(13) |
  216. // |<------ 2 sec ------->| |
  217. // GetMetric | (8 - 0) / 2 | (13 - 8) / 2 |
  218. //
  219. // |include_empty_intervals|: If set, intervals without samples will be included
  220. // in the stats. The value for an interval is
  221. // determined by GetValueForEmptyInterval().
  222. //
  223. class RateAccCounter : public StatsCounter {
  224. public:
  225. RateAccCounter(Clock* clock,
  226. StatsCounterObserver* observer,
  227. bool include_empty_intervals);
  228. ~RateAccCounter() override {}
  229. void Set(int64_t sample, uint32_t stream_id);
  230. // Sets the value for previous interval.
  231. // To be used if a value other than zero is initially required.
  232. void SetLast(int64_t sample, uint32_t stream_id);
  233. private:
  234. bool GetMetric(int* metric) const override;
  235. int GetValueForEmptyInterval() const override; // Returns zero.
  236. RTC_DISALLOW_COPY_AND_ASSIGN(RateAccCounter);
  237. };
  238. } // namespace webrtc
  239. #endif // VIDEO_STATS_COUNTER_H_