webrtc/stats/rtc_stats.cc
Henrik Boström 0f1376529a Delete RTC[NonStandard/Restricted]StatsMember.
Whether a metric is to be exposed to JavaScript or not is a blink
implementation detail that the WebRTC repository does not need to be
concerned with.

This CL removes unused code and paves the way for the possibility of
making the one and only RTCStatsMember class be absl::optional<>-based
in the future.

Bug: webrtc:15162
Change-Id: I578715f48b8fcc3534b72b4c700fd6567f8d553e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/304722
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40139}
2023-05-25 08:39:48 +00:00

297 lines
11 KiB
C++

/*
* 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.
*/
#include "api/stats/rtc_stats.h"
#include <cstdio>
#include "rtc_base/arraysize.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace {
// Produces "[a,b,c]". Works for non-vector `RTCStatsMemberInterface::Type`
// types.
template <typename T>
std::string VectorToString(const std::vector<T>& vector) {
rtc::StringBuilder sb;
sb << "[";
const char* separator = "";
for (const T& element : vector) {
sb << separator << rtc::ToString(element);
separator = ",";
}
sb << "]";
return sb.Release();
}
// This overload is required because std::vector<bool> range loops don't
// return references but objects, causing -Wrange-loop-analysis diagnostics.
std::string VectorToString(const std::vector<bool>& vector) {
rtc::StringBuilder sb;
sb << "[";
const char* separator = "";
for (bool element : vector) {
sb << separator << rtc::ToString(element);
separator = ",";
}
sb << "]";
return sb.Release();
}
// Produces "[\"a\",\"b\",\"c\"]". Works for vectors of both const char* and
// std::string element types.
template <typename T>
std::string VectorOfStringsToString(const std::vector<T>& strings) {
rtc::StringBuilder sb;
sb << "[";
const char* separator = "";
for (const T& element : strings) {
sb << separator << "\"" << rtc::ToString(element) << "\"";
separator = ",";
}
sb << "]";
return sb.Release();
}
template <typename T>
std::string MapToString(const std::map<std::string, T>& map) {
rtc::StringBuilder sb;
sb << "{";
const char* separator = "";
for (const auto& element : map) {
sb << separator << rtc::ToString(element.first) << ":"
<< rtc::ToString(element.second);
separator = ",";
}
sb << "}";
return sb.Release();
}
template <typename T>
std::string ToStringAsDouble(const T value) {
// JSON represents numbers as floating point numbers with about 15 decimal
// digits of precision.
char buf[32];
const int len = std::snprintf(&buf[0], arraysize(buf), "%.16g",
static_cast<double>(value));
RTC_DCHECK_LE(len, arraysize(buf));
return std::string(&buf[0], len);
}
template <typename T>
std::string VectorToStringAsDouble(const std::vector<T>& vector) {
rtc::StringBuilder sb;
sb << "[";
const char* separator = "";
for (const T& element : vector) {
sb << separator << ToStringAsDouble<T>(element);
separator = ",";
}
sb << "]";
return sb.Release();
}
template <typename T>
std::string MapToStringAsDouble(const std::map<std::string, T>& map) {
rtc::StringBuilder sb;
sb << "{";
const char* separator = "";
for (const auto& element : map) {
sb << separator << "\"" << rtc::ToString(element.first)
<< "\":" << ToStringAsDouble(element.second);
separator = ",";
}
sb << "}";
return sb.Release();
}
} // namespace
bool RTCStats::operator==(const RTCStats& other) const {
if (type() != other.type() || id() != other.id())
return false;
std::vector<const RTCStatsMemberInterface*> members = Members();
std::vector<const RTCStatsMemberInterface*> other_members = other.Members();
RTC_DCHECK_EQ(members.size(), other_members.size());
for (size_t i = 0; i < members.size(); ++i) {
const RTCStatsMemberInterface* member = members[i];
const RTCStatsMemberInterface* other_member = other_members[i];
RTC_DCHECK_EQ(member->type(), other_member->type());
RTC_DCHECK_EQ(member->name(), other_member->name());
if (*member != *other_member)
return false;
}
return true;
}
bool RTCStats::operator!=(const RTCStats& other) const {
return !(*this == other);
}
std::string RTCStats::ToJson() const {
rtc::StringBuilder sb;
sb << "{\"type\":\"" << type()
<< "\","
"\"id\":\""
<< id_
<< "\","
"\"timestamp\":"
<< timestamp_.us();
for (const RTCStatsMemberInterface* member : Members()) {
if (member->is_defined()) {
sb << ",\"" << member->name() << "\":";
if (member->is_string())
sb << "\"" << member->ValueToJson() << "\"";
else
sb << member->ValueToJson();
}
}
sb << "}";
return sb.Release();
}
std::vector<const RTCStatsMemberInterface*> RTCStats::Members() const {
return MembersOfThisObjectAndAncestors(0);
}
std::vector<const RTCStatsMemberInterface*>
RTCStats::MembersOfThisObjectAndAncestors(size_t additional_capacity) const {
std::vector<const RTCStatsMemberInterface*> members;
members.reserve(additional_capacity);
return members;
}
#define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \
template <> \
RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
return type; \
} \
template <> \
bool RTCStatsMember<T>::is_sequence() const { \
return is_seq; \
} \
template <> \
bool RTCStatsMember<T>::is_string() const { \
return is_str; \
} \
template <> \
std::string RTCStatsMember<T>::ValueToString() const { \
RTC_DCHECK(value_.has_value()); \
return to_str; \
} \
template <> \
std::string RTCStatsMember<T>::ValueToJson() const { \
RTC_DCHECK(value_.has_value()); \
return to_json; \
} \
template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
WEBRTC_DEFINE_RTCSTATSMEMBER(bool,
kBool,
false,
false,
rtc::ToString(*value_),
rtc::ToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t,
kInt32,
false,
false,
rtc::ToString(*value_),
rtc::ToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
kUint32,
false,
false,
rtc::ToString(*value_),
rtc::ToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
kInt64,
false,
false,
rtc::ToString(*value_),
ToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
kUint64,
false,
false,
rtc::ToString(*value_),
ToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(double,
kDouble,
false,
false,
rtc::ToString(*value_),
ToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::string,
kString,
false,
true,
*value_,
*value_);
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>,
kSequenceBool,
true,
false,
VectorToString(*value_),
VectorToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
kSequenceInt32,
true,
false,
VectorToString(*value_),
VectorToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
kSequenceUint32,
true,
false,
VectorToString(*value_),
VectorToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
kSequenceInt64,
true,
false,
VectorToString(*value_),
VectorToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
kSequenceUint64,
true,
false,
VectorToString(*value_),
VectorToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
kSequenceDouble,
true,
false,
VectorToString(*value_),
VectorToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
kSequenceString,
true,
false,
VectorOfStringsToString(*value_),
VectorOfStringsToString(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64,
kMapStringUint64,
false,
false,
MapToString(*value_),
MapToStringAsDouble(*value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble,
kMapStringDouble,
false,
false,
MapToString(*value_),
MapToStringAsDouble(*value_));
} // namespace webrtc