rtc_stats.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * Copyright 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 API_STATS_RTC_STATS_H_
  11. #define API_STATS_RTC_STATS_H_
  12. #include <stddef.h>
  13. #include <stdint.h>
  14. #include <memory>
  15. #include <string>
  16. #include <utility>
  17. #include <vector>
  18. #include "rtc_base/checks.h"
  19. #include "rtc_base/system/rtc_export.h"
  20. #include "rtc_base/system/rtc_export_template.h"
  21. namespace webrtc {
  22. class RTCStatsMemberInterface;
  23. // Abstract base class for RTCStats-derived dictionaries, see
  24. // https://w3c.github.io/webrtc-stats/.
  25. //
  26. // All derived classes must have the following static variable defined:
  27. // static const char kType[];
  28. // It is used as a unique class identifier and a string representation of the
  29. // class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*.
  30. // Use the |WEBRTC_RTCSTATS_IMPL| macro when implementing subclasses, see macro
  31. // for details.
  32. //
  33. // Derived classes list their dictionary members, RTCStatsMember<T>, as public
  34. // fields, allowing the following:
  35. //
  36. // RTCFooStats foo("fooId", GetCurrentTime());
  37. // foo.bar = 42;
  38. // foo.baz = std::vector<std::string>();
  39. // foo.baz->push_back("hello world");
  40. // uint32_t x = *foo.bar;
  41. //
  42. // Pointers to all the members are available with |Members|, allowing iteration:
  43. //
  44. // for (const RTCStatsMemberInterface* member : foo.Members()) {
  45. // printf("%s = %s\n", member->name(), member->ValueToString().c_str());
  46. // }
  47. class RTC_EXPORT RTCStats {
  48. public:
  49. RTCStats(const std::string& id, int64_t timestamp_us)
  50. : id_(id), timestamp_us_(timestamp_us) {}
  51. RTCStats(std::string&& id, int64_t timestamp_us)
  52. : id_(std::move(id)), timestamp_us_(timestamp_us) {}
  53. virtual ~RTCStats() {}
  54. virtual std::unique_ptr<RTCStats> copy() const = 0;
  55. const std::string& id() const { return id_; }
  56. // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds.
  57. int64_t timestamp_us() const { return timestamp_us_; }
  58. // Returns the static member variable |kType| of the implementing class.
  59. virtual const char* type() const = 0;
  60. // Returns a vector of pointers to all the |RTCStatsMemberInterface| members
  61. // of this class. This allows for iteration of members. For a given class,
  62. // |Members| always returns the same members in the same order.
  63. std::vector<const RTCStatsMemberInterface*> Members() const;
  64. // Checks if the two stats objects are of the same type and have the same
  65. // member values. Timestamps are not compared. These operators are exposed for
  66. // testing.
  67. bool operator==(const RTCStats& other) const;
  68. bool operator!=(const RTCStats& other) const;
  69. // Creates a JSON readable string representation of the stats
  70. // object, listing all of its members (names and values).
  71. std::string ToJson() const;
  72. // Downcasts the stats object to an |RTCStats| subclass |T|. DCHECKs that the
  73. // object is of type |T|.
  74. template <typename T>
  75. const T& cast_to() const {
  76. RTC_DCHECK_EQ(type(), T::kType);
  77. return static_cast<const T&>(*this);
  78. }
  79. protected:
  80. // Gets a vector of all members of this |RTCStats| object, including members
  81. // derived from parent classes. |additional_capacity| is how many more members
  82. // shall be reserved in the vector (so that subclasses can allocate a vector
  83. // with room for both parent and child members without it having to resize).
  84. virtual std::vector<const RTCStatsMemberInterface*>
  85. MembersOfThisObjectAndAncestors(size_t additional_capacity) const;
  86. std::string const id_;
  87. int64_t timestamp_us_;
  88. };
  89. // All |RTCStats| classes should use these macros.
  90. // |WEBRTC_RTCSTATS_DECL| is placed in a public section of the class definition.
  91. // |WEBRTC_RTCSTATS_IMPL| is placed outside the class definition (in a .cc).
  92. //
  93. // These macros declare (in _DECL) and define (in _IMPL) the static |kType| and
  94. // overrides methods as required by subclasses of |RTCStats|: |copy|, |type| and
  95. // |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses
  96. // to each member defined in the implementing class. The list must have at least
  97. // one member.
  98. //
  99. // (Since class names need to be known to implement these methods this cannot be
  100. // part of the base |RTCStats|. While these methods could be implemented using
  101. // templates, that would only work for immediate subclasses. Subclasses of
  102. // subclasses also have to override these methods, resulting in boilerplate
  103. // code. Using a macro avoids this and works for any |RTCStats| class, including
  104. // grandchildren.)
  105. //
  106. // Sample usage:
  107. //
  108. // rtcfoostats.h:
  109. // class RTCFooStats : public RTCStats {
  110. // public:
  111. // WEBRTC_RTCSTATS_DECL();
  112. //
  113. // RTCFooStats(const std::string& id, int64_t timestamp_us);
  114. //
  115. // RTCStatsMember<int32_t> foo;
  116. // RTCStatsMember<int32_t> bar;
  117. // };
  118. //
  119. // rtcfoostats.cc:
  120. // WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats"
  121. // &foo,
  122. // &bar);
  123. //
  124. // RTCFooStats::RTCFooStats(const std::string& id, int64_t timestamp_us)
  125. // : RTCStats(id, timestamp_us),
  126. // foo("foo"),
  127. // bar("bar") {
  128. // }
  129. //
  130. #define WEBRTC_RTCSTATS_DECL() \
  131. protected: \
  132. std::vector<const webrtc::RTCStatsMemberInterface*> \
  133. MembersOfThisObjectAndAncestors(size_t local_var_additional_capacity) \
  134. const override; \
  135. \
  136. public: \
  137. static const char kType[]; \
  138. \
  139. std::unique_ptr<webrtc::RTCStats> copy() const override; \
  140. const char* type() const override
  141. #define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \
  142. const char this_class::kType[] = type_str; \
  143. \
  144. std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \
  145. return std::unique_ptr<webrtc::RTCStats>(new this_class(*this)); \
  146. } \
  147. \
  148. const char* this_class::type() const { return this_class::kType; } \
  149. \
  150. std::vector<const webrtc::RTCStatsMemberInterface*> \
  151. this_class::MembersOfThisObjectAndAncestors( \
  152. size_t local_var_additional_capacity) const { \
  153. const webrtc::RTCStatsMemberInterface* local_var_members[] = { \
  154. __VA_ARGS__}; \
  155. size_t local_var_members_count = \
  156. sizeof(local_var_members) / sizeof(local_var_members[0]); \
  157. std::vector<const webrtc::RTCStatsMemberInterface*> \
  158. local_var_members_vec = parent_class::MembersOfThisObjectAndAncestors( \
  159. local_var_members_count + local_var_additional_capacity); \
  160. RTC_DCHECK_GE( \
  161. local_var_members_vec.capacity() - local_var_members_vec.size(), \
  162. local_var_members_count + local_var_additional_capacity); \
  163. local_var_members_vec.insert(local_var_members_vec.end(), \
  164. &local_var_members[0], \
  165. &local_var_members[local_var_members_count]); \
  166. return local_var_members_vec; \
  167. }
  168. // A version of WEBRTC_RTCSTATS_IMPL() where "..." is omitted, used to avoid a
  169. // compile error on windows. This is used if the stats dictionary does not
  170. // declare any members of its own (but perhaps its parent dictionary does).
  171. #define WEBRTC_RTCSTATS_IMPL_NO_MEMBERS(this_class, parent_class, type_str) \
  172. const char this_class::kType[] = type_str; \
  173. \
  174. std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \
  175. return std::unique_ptr<webrtc::RTCStats>(new this_class(*this)); \
  176. } \
  177. \
  178. const char* this_class::type() const { return this_class::kType; } \
  179. \
  180. std::vector<const webrtc::RTCStatsMemberInterface*> \
  181. this_class::MembersOfThisObjectAndAncestors( \
  182. size_t local_var_additional_capacity) const { \
  183. return parent_class::MembersOfThisObjectAndAncestors(0); \
  184. }
  185. // Non-standard stats members can be exposed to the JavaScript API in Chrome
  186. // e.g. through origin trials. The group ID can be used by the blink layer to
  187. // determine if a stats member should be exposed or not. Multiple non-standard
  188. // stats members can share the same group ID so that they are exposed together.
  189. enum class NonStandardGroupId {
  190. // Group ID used for testing purposes only.
  191. kGroupIdForTesting,
  192. // I2E:
  193. // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/hE2B1iItPDk
  194. kRtcAudioJitterBufferMaxPackets,
  195. // I2E:
  196. // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/YbhMyqLXXXo
  197. kRtcStatsRelativePacketArrivalDelay,
  198. };
  199. // Interface for |RTCStats| members, which have a name and a value of a type
  200. // defined in a subclass. Only the types listed in |Type| are supported, these
  201. // are implemented by |RTCStatsMember<T>|. The value of a member may be
  202. // undefined, the value can only be read if |is_defined|.
  203. class RTCStatsMemberInterface {
  204. public:
  205. // Member value types.
  206. enum Type {
  207. kBool, // bool
  208. kInt32, // int32_t
  209. kUint32, // uint32_t
  210. kInt64, // int64_t
  211. kUint64, // uint64_t
  212. kDouble, // double
  213. kString, // std::string
  214. kSequenceBool, // std::vector<bool>
  215. kSequenceInt32, // std::vector<int32_t>
  216. kSequenceUint32, // std::vector<uint32_t>
  217. kSequenceInt64, // std::vector<int64_t>
  218. kSequenceUint64, // std::vector<uint64_t>
  219. kSequenceDouble, // std::vector<double>
  220. kSequenceString, // std::vector<std::string>
  221. };
  222. virtual ~RTCStatsMemberInterface() {}
  223. const char* name() const { return name_; }
  224. virtual Type type() const = 0;
  225. virtual bool is_sequence() const = 0;
  226. virtual bool is_string() const = 0;
  227. bool is_defined() const { return is_defined_; }
  228. // Is this part of the stats spec? Used so that chromium can easily filter
  229. // out anything unstandardized.
  230. virtual bool is_standardized() const = 0;
  231. // Non-standard stats members can have group IDs in order to be exposed in
  232. // JavaScript through experiments. Standardized stats have no group IDs.
  233. virtual std::vector<NonStandardGroupId> group_ids() const { return {}; }
  234. // Type and value comparator. The names are not compared. These operators are
  235. // exposed for testing.
  236. virtual bool operator==(const RTCStatsMemberInterface& other) const = 0;
  237. bool operator!=(const RTCStatsMemberInterface& other) const {
  238. return !(*this == other);
  239. }
  240. virtual std::string ValueToString() const = 0;
  241. // This is the same as ValueToString except for kInt64 and kUint64 types,
  242. // where the value is represented as a double instead of as an integer.
  243. // Since JSON stores numbers as floating point numbers, very large integers
  244. // cannot be accurately represented, so we prefer to display them as doubles
  245. // instead.
  246. virtual std::string ValueToJson() const = 0;
  247. template <typename T>
  248. const T& cast_to() const {
  249. RTC_DCHECK_EQ(type(), T::StaticType());
  250. return static_cast<const T&>(*this);
  251. }
  252. protected:
  253. RTCStatsMemberInterface(const char* name, bool is_defined)
  254. : name_(name), is_defined_(is_defined) {}
  255. const char* const name_;
  256. bool is_defined_;
  257. };
  258. // Template implementation of |RTCStatsMemberInterface|.
  259. // The supported types are the ones described by
  260. // |RTCStatsMemberInterface::Type|.
  261. template <typename T>
  262. class RTCStatsMember : public RTCStatsMemberInterface {
  263. public:
  264. explicit RTCStatsMember(const char* name)
  265. : RTCStatsMemberInterface(name, /*is_defined=*/false), value_() {}
  266. RTCStatsMember(const char* name, const T& value)
  267. : RTCStatsMemberInterface(name, /*is_defined=*/true), value_(value) {}
  268. RTCStatsMember(const char* name, T&& value)
  269. : RTCStatsMemberInterface(name, /*is_defined=*/true),
  270. value_(std::move(value)) {}
  271. explicit RTCStatsMember(const RTCStatsMember<T>& other)
  272. : RTCStatsMemberInterface(other.name_, other.is_defined_),
  273. value_(other.value_) {}
  274. explicit RTCStatsMember(RTCStatsMember<T>&& other)
  275. : RTCStatsMemberInterface(other.name_, other.is_defined_),
  276. value_(std::move(other.value_)) {}
  277. static Type StaticType();
  278. Type type() const override { return StaticType(); }
  279. bool is_sequence() const override;
  280. bool is_string() const override;
  281. bool is_standardized() const override { return true; }
  282. bool operator==(const RTCStatsMemberInterface& other) const override {
  283. if (type() != other.type() || is_standardized() != other.is_standardized())
  284. return false;
  285. const RTCStatsMember<T>& other_t =
  286. static_cast<const RTCStatsMember<T>&>(other);
  287. if (!is_defined_)
  288. return !other_t.is_defined();
  289. if (!other.is_defined())
  290. return false;
  291. return value_ == other_t.value_;
  292. }
  293. std::string ValueToString() const override;
  294. std::string ValueToJson() const override;
  295. template <typename U>
  296. inline T ValueOrDefault(U default_value) const {
  297. if (is_defined()) {
  298. return *(*this);
  299. }
  300. return default_value;
  301. }
  302. // Assignment operators.
  303. T& operator=(const T& value) {
  304. value_ = value;
  305. is_defined_ = true;
  306. return value_;
  307. }
  308. T& operator=(const T&& value) {
  309. value_ = std::move(value);
  310. is_defined_ = true;
  311. return value_;
  312. }
  313. // Value getters.
  314. T& operator*() {
  315. RTC_DCHECK(is_defined_);
  316. return value_;
  317. }
  318. const T& operator*() const {
  319. RTC_DCHECK(is_defined_);
  320. return value_;
  321. }
  322. // Value getters, arrow operator.
  323. T* operator->() {
  324. RTC_DCHECK(is_defined_);
  325. return &value_;
  326. }
  327. const T* operator->() const {
  328. RTC_DCHECK(is_defined_);
  329. return &value_;
  330. }
  331. private:
  332. T value_;
  333. };
  334. #define WEBRTC_DECLARE_RTCSTATSMEMBER(T) \
  335. template <> \
  336. RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
  337. template <> \
  338. RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const; \
  339. template <> \
  340. RTC_EXPORT bool RTCStatsMember<T>::is_string() const; \
  341. template <> \
  342. RTC_EXPORT std::string RTCStatsMember<T>::ValueToString() const; \
  343. template <> \
  344. RTC_EXPORT std::string RTCStatsMember<T>::ValueToJson() const; \
  345. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \
  346. RTCStatsMember<T>
  347. WEBRTC_DECLARE_RTCSTATSMEMBER(bool);
  348. WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t);
  349. WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t);
  350. WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t);
  351. WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t);
  352. WEBRTC_DECLARE_RTCSTATSMEMBER(double);
  353. WEBRTC_DECLARE_RTCSTATSMEMBER(std::string);
  354. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>);
  355. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>);
  356. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>);
  357. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>);
  358. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>);
  359. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>);
  360. WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>);
  361. // Using inheritance just so that it's obvious from the member's declaration
  362. // whether it's standardized or not.
  363. template <typename T>
  364. class RTCNonStandardStatsMember : public RTCStatsMember<T> {
  365. public:
  366. explicit RTCNonStandardStatsMember(const char* name)
  367. : RTCStatsMember<T>(name) {}
  368. RTCNonStandardStatsMember(const char* name,
  369. std::initializer_list<NonStandardGroupId> group_ids)
  370. : RTCStatsMember<T>(name), group_ids_(group_ids) {}
  371. RTCNonStandardStatsMember(const char* name, const T& value)
  372. : RTCStatsMember<T>(name, value) {}
  373. RTCNonStandardStatsMember(const char* name, T&& value)
  374. : RTCStatsMember<T>(name, std::move(value)) {}
  375. explicit RTCNonStandardStatsMember(const RTCNonStandardStatsMember<T>& other)
  376. : RTCStatsMember<T>(other), group_ids_(other.group_ids_) {}
  377. explicit RTCNonStandardStatsMember(RTCNonStandardStatsMember<T>&& other)
  378. : RTCStatsMember<T>(std::move(other)),
  379. group_ids_(std::move(other.group_ids_)) {}
  380. bool is_standardized() const override { return false; }
  381. std::vector<NonStandardGroupId> group_ids() const override {
  382. return group_ids_;
  383. }
  384. T& operator=(const T& value) { return RTCStatsMember<T>::operator=(value); }
  385. T& operator=(const T&& value) {
  386. return RTCStatsMember<T>::operator=(std::move(value));
  387. }
  388. private:
  389. std::vector<NonStandardGroupId> group_ids_;
  390. };
  391. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  392. RTCNonStandardStatsMember<bool>;
  393. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  394. RTCNonStandardStatsMember<int32_t>;
  395. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  396. RTCNonStandardStatsMember<uint32_t>;
  397. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  398. RTCNonStandardStatsMember<int64_t>;
  399. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  400. RTCNonStandardStatsMember<uint64_t>;
  401. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  402. RTCNonStandardStatsMember<double>;
  403. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  404. RTCNonStandardStatsMember<std::string>;
  405. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  406. RTCNonStandardStatsMember<std::vector<bool>>;
  407. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  408. RTCNonStandardStatsMember<std::vector<int32_t>>;
  409. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  410. RTCNonStandardStatsMember<std::vector<uint32_t>>;
  411. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  412. RTCNonStandardStatsMember<std::vector<int64_t>>;
  413. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  414. RTCNonStandardStatsMember<std::vector<uint64_t>>;
  415. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  416. RTCNonStandardStatsMember<std::vector<double>>;
  417. extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)
  418. RTCNonStandardStatsMember<std::vector<std::string>>;
  419. } // namespace webrtc
  420. #endif // API_STATS_RTC_STATS_H_