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 #include "api/stats/rtc_stats.h"
12
13 #include <cstdio>
14
15 #include "rtc_base/arraysize.h"
16 #include "rtc_base/string_encode.h"
17 #include "rtc_base/strings/string_builder.h"
18
19 namespace webrtc {
20
21 namespace {
22
23 // Produces "[a,b,c]". Works for non-vector |RTCStatsMemberInterface::Type|
24 // types.
25 template <typename T>
VectorToString(const std::vector<T> & vector)26 std::string VectorToString(const std::vector<T>& vector) {
27 rtc::StringBuilder sb;
28 sb << "[";
29 const char* separator = "";
30 for (const T& element : vector) {
31 sb << separator << rtc::ToString(element);
32 separator = ",";
33 }
34 sb << "]";
35 return sb.Release();
36 }
37
38 // Produces "[\"a\",\"b\",\"c\"]". Works for vectors of both const char* and
39 // std::string element types.
40 template <typename T>
VectorOfStringsToString(const std::vector<T> & strings)41 std::string VectorOfStringsToString(const std::vector<T>& strings) {
42 rtc::StringBuilder sb;
43 sb << "[";
44 const char* separator = "";
45 for (const T& element : strings) {
46 sb << separator << "\"" << rtc::ToString(element) << "\"";
47 separator = ",";
48 }
49 sb << "]";
50 return sb.Release();
51 }
52
53 template <typename T>
ToStringAsDouble(const T value)54 std::string ToStringAsDouble(const T value) {
55 // JSON represents numbers as floating point numbers with about 15 decimal
56 // digits of precision.
57 char buf[32];
58 const int len = std::snprintf(&buf[0], arraysize(buf), "%.16g",
59 static_cast<double>(value));
60 RTC_DCHECK_LE(len, arraysize(buf));
61 return std::string(&buf[0], len);
62 }
63
64 template <typename T>
VectorToStringAsDouble(const std::vector<T> & vector)65 std::string VectorToStringAsDouble(const std::vector<T>& vector) {
66 rtc::StringBuilder sb;
67 sb << "[";
68 const char* separator = "";
69 for (const T& element : vector) {
70 sb << separator << ToStringAsDouble<T>(element);
71 separator = ",";
72 }
73 sb << "]";
74 return sb.Release();
75 }
76
77 } // namespace
78
operator ==(const RTCStats & other) const79 bool RTCStats::operator==(const RTCStats& other) const {
80 if (type() != other.type() || id() != other.id())
81 return false;
82 std::vector<const RTCStatsMemberInterface*> members = Members();
83 std::vector<const RTCStatsMemberInterface*> other_members = other.Members();
84 RTC_DCHECK_EQ(members.size(), other_members.size());
85 for (size_t i = 0; i < members.size(); ++i) {
86 const RTCStatsMemberInterface* member = members[i];
87 const RTCStatsMemberInterface* other_member = other_members[i];
88 RTC_DCHECK_EQ(member->type(), other_member->type());
89 RTC_DCHECK_EQ(member->name(), other_member->name());
90 if (*member != *other_member)
91 return false;
92 }
93 return true;
94 }
95
operator !=(const RTCStats & other) const96 bool RTCStats::operator!=(const RTCStats& other) const {
97 return !(*this == other);
98 }
99
ToJson() const100 std::string RTCStats::ToJson() const {
101 rtc::StringBuilder sb;
102 sb << "{\"type\":\"" << type()
103 << "\","
104 "\"id\":\""
105 << id_
106 << "\","
107 "\"timestamp\":"
108 << timestamp_us_;
109 for (const RTCStatsMemberInterface* member : Members()) {
110 if (member->is_defined()) {
111 sb << ",\"" << member->name() << "\":";
112 if (member->is_string())
113 sb << "\"" << member->ValueToJson() << "\"";
114 else
115 sb << member->ValueToJson();
116 }
117 }
118 sb << "}";
119 return sb.Release();
120 }
121
Members() const122 std::vector<const RTCStatsMemberInterface*> RTCStats::Members() const {
123 return MembersOfThisObjectAndAncestors(0);
124 }
125
126 std::vector<const RTCStatsMemberInterface*>
MembersOfThisObjectAndAncestors(size_t additional_capacity) const127 RTCStats::MembersOfThisObjectAndAncestors(size_t additional_capacity) const {
128 std::vector<const RTCStatsMemberInterface*> members;
129 members.reserve(additional_capacity);
130 return members;
131 }
132
133 #define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \
134 template <> \
135 RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
136 return type; \
137 } \
138 template <> \
139 bool RTCStatsMember<T>::is_sequence() const { \
140 return is_seq; \
141 } \
142 template <> \
143 bool RTCStatsMember<T>::is_string() const { \
144 return is_str; \
145 } \
146 template <> \
147 std::string RTCStatsMember<T>::ValueToString() const { \
148 RTC_DCHECK(is_defined_); \
149 return to_str; \
150 } \
151 template <> \
152 std::string RTCStatsMember<T>::ValueToJson() const { \
153 RTC_DCHECK(is_defined_); \
154 return to_json; \
155 } \
156 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
157
158 WEBRTC_DEFINE_RTCSTATSMEMBER(bool,
159 kBool,
160 false,
161 false,
162 rtc::ToString(value_),
163 rtc::ToString(value_));
164 WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t,
165 kInt32,
166 false,
167 false,
168 rtc::ToString(value_),
169 rtc::ToString(value_));
170 WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
171 kUint32,
172 false,
173 false,
174 rtc::ToString(value_),
175 rtc::ToString(value_));
176 WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
177 kInt64,
178 false,
179 false,
180 rtc::ToString(value_),
181 ToStringAsDouble(value_));
182 WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
183 kUint64,
184 false,
185 false,
186 rtc::ToString(value_),
187 ToStringAsDouble(value_));
188 WEBRTC_DEFINE_RTCSTATSMEMBER(double,
189 kDouble,
190 false,
191 false,
192 rtc::ToString(value_),
193 ToStringAsDouble(value_));
194 WEBRTC_DEFINE_RTCSTATSMEMBER(std::string, kString, false, true, value_, value_);
195 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>,
196 kSequenceBool,
197 true,
198 false,
199 VectorToString(value_),
200 VectorToString(value_));
201 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
202 kSequenceInt32,
203 true,
204 false,
205 VectorToString(value_),
206 VectorToString(value_));
207 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
208 kSequenceUint32,
209 true,
210 false,
211 VectorToString(value_),
212 VectorToString(value_));
213 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
214 kSequenceInt64,
215 true,
216 false,
217 VectorToString(value_),
218 VectorToStringAsDouble(value_));
219 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
220 kSequenceUint64,
221 true,
222 false,
223 VectorToString(value_),
224 VectorToStringAsDouble(value_));
225 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
226 kSequenceDouble,
227 true,
228 false,
229 VectorToString(value_),
230 VectorToStringAsDouble(value_));
231 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
232 kSequenceString,
233 true,
234 false,
235 VectorOfStringsToString(value_),
236 VectorOfStringsToString(value_));
237
238 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
239 RTCNonStandardStatsMember<bool>;
240 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
241 RTCNonStandardStatsMember<int32_t>;
242 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
243 RTCNonStandardStatsMember<uint32_t>;
244 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
245 RTCNonStandardStatsMember<int64_t>;
246 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
247 RTCNonStandardStatsMember<uint64_t>;
248 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
249 RTCNonStandardStatsMember<double>;
250 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
251 RTCNonStandardStatsMember<std::string>;
252 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
253 RTCNonStandardStatsMember<std::vector<bool>>;
254 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
255 RTCNonStandardStatsMember<std::vector<int32_t>>;
256 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
257 RTCNonStandardStatsMember<std::vector<uint32_t>>;
258 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
259 RTCNonStandardStatsMember<std::vector<int64_t>>;
260 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
261 RTCNonStandardStatsMember<std::vector<uint64_t>>;
262 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
263 RTCNonStandardStatsMember<std::vector<double>>;
264 template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT)
265 RTCNonStandardStatsMember<std::vector<std::string>>;
266
267 } // namespace webrtc
268