rtc_stats.h (8491B)
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 11 #ifndef API_STATS_RTC_STATS_H_ 12 #define API_STATS_RTC_STATS_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <memory> 18 #include <optional> 19 #include <string> 20 #include <vector> 21 22 #include "api/stats/attribute.h" 23 #include "api/units/timestamp.h" 24 #include "rtc_base/checks.h" 25 #include "rtc_base/system/rtc_export.h" 26 27 namespace webrtc { 28 29 // Abstract base class for RTCStats-derived dictionaries, see 30 // https://w3c.github.io/webrtc-stats/. 31 // 32 // All derived classes must have the following static variable defined: 33 // static const char kType[]; 34 // It is used as a unique class identifier and a string representation of the 35 // class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*. 36 // Use the `WEBRTC_RTCSTATS_IMPL` macro when implementing subclasses, see macro 37 // for details. 38 // 39 // Derived classes list their dictionary attributes, std::optional<T>, as 40 // public fields, allowing the following: 41 // 42 // RTCFooStats foo("fooId", Timestamp::Micros(GetCurrentTime())); 43 // foo.bar = 42; 44 // foo.baz = std::vector<std::string>(); 45 // foo.baz->push_back("hello world"); 46 // uint32_t x = *foo.bar; 47 // 48 // Pointers to all the attributes are available with `Attributes()`, allowing 49 // iteration: 50 // 51 // for (const auto& attribute : foo.Attributes()) { 52 // printf("%s = %s\n", attribute.name(), attribute.ToString().c_str()); 53 // } 54 class RTC_EXPORT RTCStats { 55 public: 56 RTCStats(const std::string& id, Timestamp timestamp) 57 : id_(id), timestamp_(timestamp) {} 58 RTCStats(const RTCStats& other); 59 virtual ~RTCStats(); 60 61 virtual std::unique_ptr<RTCStats> copy() const = 0; 62 63 const std::string& id() const { return id_; } 64 // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds. 65 Timestamp timestamp() const { return timestamp_; } 66 void set_timestamp(Timestamp timestamp) { timestamp_ = timestamp; } 67 68 // Returns the static member variable `kType` of the implementing class. 69 virtual const char* type() const = 0; 70 // Returns all attributes of this stats object, i.e. a list of its individual 71 // metrics as viewed via the Attribute wrapper. 72 std::vector<Attribute> Attributes() const; 73 template <typename T> 74 Attribute GetAttribute(const std::optional<T>& stat) const { 75 for (const auto& attribute : Attributes()) { 76 if (!attribute.holds_alternative<T>()) { 77 continue; 78 } 79 if (std::get<const std::optional<T>*>(attribute.as_variant()) == &stat) { 80 return attribute; 81 } 82 } 83 RTC_CHECK_NOTREACHED(); 84 } 85 // Checks if the two stats objects are of the same type and have the same 86 // attribute values. Timestamps are not compared. These operators are exposed 87 // for testing. 88 bool operator==(const RTCStats& other) const; 89 bool operator!=(const RTCStats& other) const; 90 91 // Creates a JSON readable string representation of the stats 92 // object, listing all of its attributes (names and values). 93 std::string ToJson() const; 94 95 // Downcasts the stats object to an `RTCStats` subclass `T`. DCHECKs that the 96 // object is of type `T`. 97 template <typename T> 98 const T& cast_to() const { 99 RTC_DCHECK_EQ(type(), T::kType); 100 return static_cast<const T&>(*this); 101 } 102 103 protected: 104 virtual std::vector<Attribute> AttributesImpl( 105 size_t additional_capacity) const; 106 107 std::string id_; 108 Timestamp timestamp_; 109 }; 110 111 // All `RTCStats` classes should use these macros. 112 // `WEBRTC_RTCSTATS_DECL` is placed in a public section of the class definition. 113 // `WEBRTC_RTCSTATS_IMPL` is placed outside the class definition (in a .cc). 114 // 115 // These macros declare (in _DECL) and define (in _IMPL) the static `kType` and 116 // overrides methods as required by subclasses of `RTCStats`: `copy`, `type` and 117 // `AttributesImpl`. The |...| argument is a list of addresses to each attribute 118 // defined in the implementing class. The list must have at least one attribute. 119 // 120 // (Since class names need to be known to implement these methods this cannot be 121 // part of the base `RTCStats`. While these methods could be implemented using 122 // templates, that would only work for immediate subclasses. Subclasses of 123 // subclasses also have to override these methods, resulting in boilerplate 124 // code. Using a macro avoids this and works for any `RTCStats` class, including 125 // grandchildren.) 126 // 127 // Sample usage: 128 // 129 // rtcfoostats.h: 130 // class RTCFooStats : public RTCStats { 131 // public: 132 // WEBRTC_RTCSTATS_DECL(); 133 // 134 // RTCFooStats(const std::string& id, Timestamp timestamp); 135 // 136 // std::optional<int32_t> foo; 137 // std::optional<int32_t> bar; 138 // }; 139 // 140 // rtcfoostats.cc: 141 // WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats" 142 // &foo, 143 // &bar); 144 // 145 // RTCFooStats::RTCFooStats(const std::string& id, Timestamp timestamp) 146 // : RTCStats(id, timestamp), 147 // foo("foo"), 148 // bar("bar") { 149 // } 150 // 151 #define WEBRTC_RTCSTATS_DECL(SelfT) \ 152 protected: \ 153 std::vector<webrtc::Attribute> AttributesImpl(size_t additional_capacity) \ 154 const override; \ 155 \ 156 public: \ 157 static const char kType[]; \ 158 \ 159 template <typename Sink> \ 160 friend void AbslStringify(Sink& sink, const SelfT& stats) { \ 161 sink.Append(stats.ToJson()); \ 162 } \ 163 \ 164 std::unique_ptr<webrtc::RTCStats> copy() const override; \ 165 const char* type() const override 166 167 #define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \ 168 const char this_class::kType[] = type_str; \ 169 \ 170 std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \ 171 return std::make_unique<this_class>(*this); \ 172 } \ 173 \ 174 const char* this_class::type() const { \ 175 return this_class::kType; \ 176 } \ 177 \ 178 std::vector<webrtc::Attribute> this_class::AttributesImpl( \ 179 size_t additional_capacity) const { \ 180 webrtc::AttributeInit attribute_inits[] = {__VA_ARGS__}; \ 181 size_t attribute_inits_size = \ 182 sizeof(attribute_inits) / sizeof(attribute_inits[0]); \ 183 std::vector<webrtc::Attribute> attributes = parent_class::AttributesImpl( \ 184 attribute_inits_size + additional_capacity); \ 185 for (size_t i = 0; i < attribute_inits_size; ++i) { \ 186 attributes.push_back(std::visit( \ 187 [&](const auto* field) { \ 188 return Attribute(attribute_inits[i].name, field); \ 189 }, \ 190 attribute_inits[i].variant)); \ 191 } \ 192 return attributes; \ 193 } 194 195 } // namespace webrtc 196 197 #endif // API_STATS_RTC_STATS_H_