metrics.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. //
  2. // Copyright (c) 2014 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 SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
  11. #define SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
  12. #include <stddef.h>
  13. #include <map>
  14. #include <memory>
  15. #include <string>
  16. #include "rtc_base/atomic_ops.h"
  17. #include "rtc_base/checks.h"
  18. #if defined(RTC_DISABLE_METRICS)
  19. #define RTC_METRICS_ENABLED 0
  20. #else
  21. #define RTC_METRICS_ENABLED 1
  22. #endif
  23. namespace webrtc {
  24. namespace metrics_impl {
  25. template <typename... Ts>
  26. void NoOp(const Ts&...) {}
  27. }
  28. }
  29. #if RTC_METRICS_ENABLED
  30. #define EXPECT_METRIC_EQ(val1, val2) EXPECT_EQ(val1, val2)
  31. #define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) \
  32. EXPECT_EQ_WAIT(val1, val2, timeout)
  33. #define EXPECT_METRIC_GT(val1, val2) EXPECT_GT(val1, val2)
  34. #define EXPECT_METRIC_LE(val1, val2) EXPECT_LE(val1, val2)
  35. #define EXPECT_METRIC_TRUE(conditon) EXPECT_TRUE(conditon)
  36. #define EXPECT_METRIC_FALSE(conditon) EXPECT_FALSE(conditon)
  37. #define EXPECT_METRIC_THAT(value, matcher) EXPECT_THAT(value, matcher)
  38. #else
  39. #define EXPECT_METRIC_EQ(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
  40. #define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) webrtc::metrics_impl::NoOp(val1, val2, timeout)
  41. #define EXPECT_METRIC_GT(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
  42. #define EXPECT_METRIC_LE(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
  43. #define EXPECT_METRIC_TRUE(condition) webrtc::metrics_impl::NoOp(condition || true)
  44. #define EXPECT_METRIC_FALSE(condition) webrtc::metrics_impl::NoOp(condition && false)
  45. #define EXPECT_METRIC_THAT(value, matcher) webrtc::metrics_impl::NoOp(value, testing::_)
  46. #endif
  47. #if RTC_METRICS_ENABLED
  48. // Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate
  49. // statistics.
  50. //
  51. // Histogram for counters.
  52. // RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count);
  53. //
  54. // Histogram for enumerators.
  55. // The boundary should be above the max enumerator sample.
  56. // RTC_HISTOGRAM_ENUMERATION(name, sample, boundary);
  57. //
  58. //
  59. // The macros use the methods HistogramFactoryGetCounts,
  60. // HistogramFactoryGetEnumeration and HistogramAdd.
  61. //
  62. // By default WebRTC provides implementations of the aforementioned methods
  63. // that can be found in system_wrappers/source/metrics.cc. If clients want to
  64. // provide a custom version, they will have to:
  65. //
  66. // 1. Compile WebRTC defining the preprocessor macro
  67. // WEBRTC_EXCLUDE_METRICS_DEFAULT (if GN is used this can be achieved
  68. // by setting the GN arg rtc_exclude_metrics_default to true).
  69. // 2. Provide implementations of:
  70. // Histogram* webrtc::metrics::HistogramFactoryGetCounts(
  71. // const std::string& name, int sample, int min, int max,
  72. // int bucket_count);
  73. // Histogram* webrtc::metrics::HistogramFactoryGetEnumeration(
  74. // const std::string& name, int sample, int boundary);
  75. // void webrtc::metrics::HistogramAdd(
  76. // Histogram* histogram_pointer, const std::string& name, int sample);
  77. //
  78. // Example usage:
  79. //
  80. // RTC_HISTOGRAM_COUNTS("WebRTC.Video.NacksSent", nacks_sent, 1, 100000, 100);
  81. //
  82. // enum Types {
  83. // kTypeX,
  84. // kTypeY,
  85. // kBoundary,
  86. // };
  87. //
  88. // RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary);
  89. //
  90. // NOTE: It is recommended to do the Chromium review for modifications to
  91. // histograms.xml before new metrics are committed to WebRTC.
  92. // Macros for adding samples to a named histogram.
  93. // Histogram for counters (exponentially spaced buckets).
  94. #define RTC_HISTOGRAM_COUNTS_100(name, sample) \
  95. RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50)
  96. #define RTC_HISTOGRAM_COUNTS_200(name, sample) \
  97. RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)
  98. #define RTC_HISTOGRAM_COUNTS_500(name, sample) \
  99. RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)
  100. #define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
  101. RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)
  102. #define RTC_HISTOGRAM_COUNTS_10000(name, sample) \
  103. RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50)
  104. #define RTC_HISTOGRAM_COUNTS_100000(name, sample) \
  105. RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50)
  106. #define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
  107. RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
  108. webrtc::metrics::HistogramFactoryGetCounts( \
  109. name, min, max, bucket_count))
  110. #define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
  111. RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
  112. webrtc::metrics::HistogramFactoryGetCountsLinear( \
  113. name, min, max, bucket_count))
  114. // Slow metrics: pointer to metric is acquired at each call and is not cached.
  115. //
  116. #define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
  117. RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100, 50)
  118. #define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \
  119. RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 200, 50)
  120. #define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) \
  121. RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 500, 50)
  122. #define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \
  123. RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 1000, 50)
  124. #define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \
  125. RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 10000, 50)
  126. #define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \
  127. RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100000, 50)
  128. #define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
  129. RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, \
  130. webrtc::metrics::HistogramFactoryGetCounts( \
  131. name, min, max, bucket_count))
  132. // Histogram for percentage (evenly spaced buckets).
  133. #define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \
  134. RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 101)
  135. // Histogram for booleans.
  136. #define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) \
  137. RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 2)
  138. // Histogram for enumerators (evenly spaced buckets).
  139. // |boundary| should be above the max enumerator sample.
  140. //
  141. // TODO(qingsi): Refactor the default implementation given by RtcHistogram,
  142. // which is already sparse, and remove the boundary argument from the macro.
  143. #define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
  144. RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
  145. name, sample, \
  146. webrtc::metrics::SparseHistogramFactoryGetEnumeration(name, boundary))
  147. // Histogram for percentage (evenly spaced buckets).
  148. #define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
  149. RTC_HISTOGRAM_ENUMERATION(name, sample, 101)
  150. // Histogram for booleans.
  151. #define RTC_HISTOGRAM_BOOLEAN(name, sample) \
  152. RTC_HISTOGRAM_ENUMERATION(name, sample, 2)
  153. // Histogram for enumerators (evenly spaced buckets).
  154. // |boundary| should be above the max enumerator sample.
  155. #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
  156. RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
  157. name, sample, \
  158. webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
  159. // The name of the histogram should not vary.
  160. // TODO(asapersson): Consider changing string to const char*.
  161. #define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
  162. factory_get_invocation) \
  163. do { \
  164. static webrtc::metrics::Histogram* atomic_histogram_pointer = nullptr; \
  165. webrtc::metrics::Histogram* histogram_pointer = \
  166. rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \
  167. if (!histogram_pointer) { \
  168. histogram_pointer = factory_get_invocation; \
  169. webrtc::metrics::Histogram* prev_pointer = \
  170. rtc::AtomicOps::CompareAndSwapPtr( \
  171. &atomic_histogram_pointer, \
  172. static_cast<webrtc::metrics::Histogram*>(nullptr), \
  173. histogram_pointer); \
  174. RTC_DCHECK(prev_pointer == nullptr || \
  175. prev_pointer == histogram_pointer); \
  176. } \
  177. if (histogram_pointer) { \
  178. webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
  179. } \
  180. } while (0)
  181. // The histogram is constructed/found for each call.
  182. // May be used for histograms with infrequent updates.`
  183. #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
  184. do { \
  185. webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \
  186. if (histogram_pointer) { \
  187. webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
  188. } \
  189. } while (0)
  190. // Helper macros.
  191. // Macros for calling a histogram with varying name (e.g. when using a metric
  192. // in different modes such as real-time vs screenshare). Fast, because pointer
  193. // is cached. |index| should be different for different names. Allowed |index|
  194. // values are 0, 1, and 2.
  195. #define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
  196. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  197. RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50))
  198. #define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) \
  199. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  200. RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50))
  201. #define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \
  202. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  203. RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50))
  204. #define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
  205. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  206. RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50))
  207. #define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \
  208. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  209. RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50))
  210. #define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \
  211. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  212. RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50))
  213. #define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
  214. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  215. RTC_HISTOGRAM_ENUMERATION(name, sample, boundary))
  216. #define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) \
  217. RTC_HISTOGRAMS_COMMON(index, name, sample, \
  218. RTC_HISTOGRAM_PERCENTAGE(name, sample))
  219. #define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
  220. do { \
  221. switch (index) { \
  222. case 0: \
  223. macro_invocation; \
  224. break; \
  225. case 1: \
  226. macro_invocation; \
  227. break; \
  228. case 2: \
  229. macro_invocation; \
  230. break; \
  231. default: \
  232. RTC_NOTREACHED(); \
  233. } \
  234. } while (0)
  235. #else
  236. ////////////////////////////////////////////////////////////////////////////////
  237. // This section defines no-op alternatives to the metrics macros when
  238. // RTC_METRICS_ENABLED is defined.
  239. #define RTC_HISTOGRAM_COUNTS_100(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  240. #define RTC_HISTOGRAM_COUNTS_200(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  241. #define RTC_HISTOGRAM_COUNTS_500(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  242. #define RTC_HISTOGRAM_COUNTS_1000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  243. #define RTC_HISTOGRAM_COUNTS_10000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  244. #define RTC_HISTOGRAM_COUNTS_100000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  245. #define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
  246. webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
  247. #define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
  248. webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
  249. #define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  250. #define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  251. #define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  252. #define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  253. #define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  254. #define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  255. #define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
  256. webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
  257. #define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  258. #define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  259. #define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
  260. webrtc::metrics_impl::NoOp(name, sample, boundary)
  261. #define RTC_HISTOGRAM_PERCENTAGE(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  262. #define RTC_HISTOGRAM_BOOLEAN(name, sample) webrtc::metrics_impl::NoOp(name, sample)
  263. #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
  264. webrtc::metrics_impl::NoOp(name, sample, boundary)
  265. #define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
  266. factory_get_invocation) \
  267. webrtc::metrics_impl::NoOp(constant_name, sample, factory_get_invocation)
  268. #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
  269. webrtc::metrics_impl::NoOp(name, sample, factory_get_invocation)
  270. #define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
  271. #define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
  272. #define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
  273. #define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
  274. webrtc::metrics_impl::NoOp(index, name, sample)
  275. #define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \
  276. webrtc::metrics_impl::NoOp(index, name, sample)
  277. #define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \
  278. webrtc::metrics_impl::NoOp(index, name, sample)
  279. #define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
  280. webrtc::metrics_impl::NoOp(index, name, sample, boundary)
  281. #define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) webrtc::metrics_impl::NoOp(index, name, sample)
  282. #define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
  283. webrtc::metrics_impl::NoOp(index, name, sample, macro_invocation)
  284. #endif // RTC_METRICS_ENABLED
  285. namespace webrtc {
  286. namespace metrics {
  287. // Time that should have elapsed for stats that are gathered once per call.
  288. enum { kMinRunTimeInSeconds = 10 };
  289. class Histogram;
  290. // Functions for getting pointer to histogram (constructs or finds the named
  291. // histogram).
  292. // Get histogram for counters.
  293. Histogram* HistogramFactoryGetCounts(const std::string& name,
  294. int min,
  295. int max,
  296. int bucket_count);
  297. // Get histogram for counters with linear bucket spacing.
  298. Histogram* HistogramFactoryGetCountsLinear(const std::string& name,
  299. int min,
  300. int max,
  301. int bucket_count);
  302. // Get histogram for enumerators.
  303. // |boundary| should be above the max enumerator sample.
  304. Histogram* HistogramFactoryGetEnumeration(const std::string& name,
  305. int boundary);
  306. // Get sparse histogram for enumerators.
  307. // |boundary| should be above the max enumerator sample.
  308. Histogram* SparseHistogramFactoryGetEnumeration(const std::string& name,
  309. int boundary);
  310. // Function for adding a |sample| to a histogram.
  311. void HistogramAdd(Histogram* histogram_pointer, int sample);
  312. struct SampleInfo {
  313. SampleInfo(const std::string& name, int min, int max, size_t bucket_count);
  314. ~SampleInfo();
  315. const std::string name;
  316. const int min;
  317. const int max;
  318. const size_t bucket_count;
  319. std::map<int, int> samples; // <value, # of events>
  320. };
  321. // Enables collection of samples.
  322. // This method should be called before any other call into webrtc.
  323. void Enable();
  324. // Gets histograms and clears all samples.
  325. void GetAndReset(
  326. std::map<std::string, std::unique_ptr<SampleInfo>>* histograms);
  327. // Functions below are mainly for testing.
  328. // Clears all samples.
  329. void Reset();
  330. // Returns the number of times the |sample| has been added to the histogram.
  331. int NumEvents(const std::string& name, int sample);
  332. // Returns the total number of added samples to the histogram.
  333. int NumSamples(const std::string& name);
  334. // Returns the minimum sample value (or -1 if the histogram has no samples).
  335. int MinSample(const std::string& name);
  336. // Returns a map with keys the samples with at least one event and values the
  337. // number of events for that sample.
  338. std::map<int, int> Samples(const std::string& name);
  339. } // namespace metrics
  340. } // namespace webrtc
  341. #endif // SYSTEM_WRAPPERS_INCLUDE_METRICS_H_