| /* |
| * Copyright 2016 The WebRTC Project Authors. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef API_STATS_RTC_STATS_H_ |
| #define API_STATS_RTC_STATS_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <map> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "api/stats/attribute.h" |
| #include "api/units/timestamp.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/system/rtc_export.h" |
| #include "rtc_base/system/rtc_export_template.h" |
| |
| namespace webrtc { |
| |
| // Abstract base class for RTCStats-derived dictionaries, see |
| // https://w3c.github.io/webrtc-stats/. |
| // |
| // All derived classes must have the following static variable defined: |
| // static const char kType[]; |
| // It is used as a unique class identifier and a string representation of the |
| // class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*. |
| // Use the `WEBRTC_RTCSTATS_IMPL` macro when implementing subclasses, see macro |
| // for details. |
| // |
| // Derived classes list their dictionary attributes, std::optional<T>, as |
| // public fields, allowing the following: |
| // |
| // RTCFooStats foo("fooId", Timestamp::Micros(GetCurrentTime())); |
| // foo.bar = 42; |
| // foo.baz = std::vector<std::string>(); |
| // foo.baz->push_back("hello world"); |
| // uint32_t x = *foo.bar; |
| // |
| // Pointers to all the attributes are available with `Attributes()`, allowing |
| // iteration: |
| // |
| // for (const auto& attribute : foo.Attributes()) { |
| // printf("%s = %s\n", attribute.name(), attribute.ToString().c_str()); |
| // } |
| class RTC_EXPORT RTCStats { |
| public: |
| RTCStats(const std::string& id, Timestamp timestamp) |
| : id_(id), timestamp_(timestamp) {} |
| RTCStats(const RTCStats& other); |
| virtual ~RTCStats(); |
| |
| virtual std::unique_ptr<RTCStats> copy() const = 0; |
| |
| const std::string& id() const { return id_; } |
| // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds. |
| Timestamp timestamp() const { return timestamp_; } |
| |
| // Returns the static member variable `kType` of the implementing class. |
| virtual const char* type() const = 0; |
| // Returns all attributes of this stats object, i.e. a list of its individual |
| // metrics as viewed via the Attribute wrapper. |
| std::vector<Attribute> Attributes() const; |
| template <typename T> |
| Attribute GetAttribute(const std::optional<T>& stat) const { |
| for (const auto& attribute : Attributes()) { |
| if (!attribute.holds_alternative<T>()) { |
| continue; |
| } |
| if (absl::get<const std::optional<T>*>(attribute.as_variant()) == &stat) { |
| return attribute; |
| } |
| } |
| RTC_CHECK_NOTREACHED(); |
| } |
| // Checks if the two stats objects are of the same type and have the same |
| // attribute values. Timestamps are not compared. These operators are exposed |
| // for testing. |
| bool operator==(const RTCStats& other) const; |
| bool operator!=(const RTCStats& other) const; |
| |
| // Creates a JSON readable string representation of the stats |
| // object, listing all of its attributes (names and values). |
| std::string ToJson() const; |
| |
| // Downcasts the stats object to an `RTCStats` subclass `T`. DCHECKs that the |
| // object is of type `T`. |
| template <typename T> |
| const T& cast_to() const { |
| RTC_DCHECK_EQ(type(), T::kType); |
| return static_cast<const T&>(*this); |
| } |
| |
| protected: |
| virtual std::vector<Attribute> AttributesImpl( |
| size_t additional_capacity) const; |
| |
| std::string const id_; |
| Timestamp timestamp_; |
| }; |
| |
| // All `RTCStats` classes should use these macros. |
| // `WEBRTC_RTCSTATS_DECL` is placed in a public section of the class definition. |
| // `WEBRTC_RTCSTATS_IMPL` is placed outside the class definition (in a .cc). |
| // |
| // These macros declare (in _DECL) and define (in _IMPL) the static `kType` and |
| // overrides methods as required by subclasses of `RTCStats`: `copy`, `type` and |
| // `AttributesImpl`. The |...| argument is a list of addresses to each attribute |
| // defined in the implementing class. The list must have at least one attribute. |
| // |
| // (Since class names need to be known to implement these methods this cannot be |
| // part of the base `RTCStats`. While these methods could be implemented using |
| // templates, that would only work for immediate subclasses. Subclasses of |
| // subclasses also have to override these methods, resulting in boilerplate |
| // code. Using a macro avoids this and works for any `RTCStats` class, including |
| // grandchildren.) |
| // |
| // Sample usage: |
| // |
| // rtcfoostats.h: |
| // class RTCFooStats : public RTCStats { |
| // public: |
| // WEBRTC_RTCSTATS_DECL(); |
| // |
| // RTCFooStats(const std::string& id, Timestamp timestamp); |
| // |
| // std::optional<int32_t> foo; |
| // std::optional<int32_t> bar; |
| // }; |
| // |
| // rtcfoostats.cc: |
| // WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats" |
| // &foo, |
| // &bar); |
| // |
| // RTCFooStats::RTCFooStats(const std::string& id, Timestamp timestamp) |
| // : RTCStats(id, timestamp), |
| // foo("foo"), |
| // bar("bar") { |
| // } |
| // |
| #define WEBRTC_RTCSTATS_DECL() \ |
| protected: \ |
| std::vector<webrtc::Attribute> AttributesImpl(size_t additional_capacity) \ |
| const override; \ |
| \ |
| public: \ |
| static const char kType[]; \ |
| \ |
| std::unique_ptr<webrtc::RTCStats> copy() const override; \ |
| const char* type() const override |
| |
| #define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \ |
| const char this_class::kType[] = type_str; \ |
| \ |
| std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \ |
| return std::make_unique<this_class>(*this); \ |
| } \ |
| \ |
| const char* this_class::type() const { \ |
| return this_class::kType; \ |
| } \ |
| \ |
| std::vector<webrtc::Attribute> this_class::AttributesImpl( \ |
| size_t additional_capacity) const { \ |
| webrtc::AttributeInit attribute_inits[] = {__VA_ARGS__}; \ |
| size_t attribute_inits_size = \ |
| sizeof(attribute_inits) / sizeof(attribute_inits[0]); \ |
| std::vector<webrtc::Attribute> attributes = parent_class::AttributesImpl( \ |
| attribute_inits_size + additional_capacity); \ |
| for (size_t i = 0; i < attribute_inits_size; ++i) { \ |
| attributes.push_back(absl::visit( \ |
| [&](const auto* field) { \ |
| return Attribute(attribute_inits[i].name, field); \ |
| }, \ |
| attribute_inits[i].variant)); \ |
| } \ |
| return attributes; \ |
| } |
| |
| } // namespace webrtc |
| |
| #endif // API_STATS_RTC_STATS_H_ |