blob: 278ac81a6e7ffdc4b2ad3cf187ef22b9374d178b [file] [log] [blame]
tommi@webrtc.org5c3ee4b2014-12-09 10:47:011/*
kjellanderb24317b2016-02-10 15:54:432 * Copyright 2014 The WebRTC project authors. All Rights Reserved.
tommi@webrtc.org5c3ee4b2014-12-09 10:47:013 *
kjellanderb24317b2016-02-10 15:54:434 * 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.
tommi@webrtc.org5c3ee4b2014-12-09 10:47:019 */
10
Henrik Boström3e6931b2022-11-11 09:07:3411#include "api/legacy_stats_types.h"
tommi@webrtc.org5c3ee4b2014-12-09 10:47:0112
tommi@webrtc.orgd3900292015-03-12 16:35:5513#include <string.h>
14
Tommi0fe65102023-03-31 10:09:3015#include <utility>
16
Steve Antona59dcc32019-03-25 20:53:0717#include "absl/algorithm/container.h"
Niels Möller7c8c4db2022-06-13 08:36:3818#include "api/make_ref_counted.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "rtc_base/checks.h"
Niels Möller6832ee22021-06-24 14:05:1720#include "rtc_base/string_encode.h"
tommi@webrtc.orgd3900292015-03-12 16:35:5521
22// TODO(tommi): Could we have a static map of value name -> expected type
henrikg91d6ede2015-09-17 07:24:3423// and use this to RTC_DCHECK on correct usage (somewhat strongly typed values)?
tommi@webrtc.orgd3900292015-03-12 16:35:5524// Alternatively, we could define the names+type in a separate document and
25// generate strongly typed inline C++ code that forces the correct type to be
26// used for a given name at compile time.
27
tommi@webrtc.org5c3ee4b2014-12-09 10:47:0128namespace webrtc {
tommi@webrtc.org4fb7e252015-01-21 11:36:1829namespace {
tommi@webrtc.org5c3ee4b2014-12-09 10:47:0130
tommi@webrtc.org4fb7e252015-01-21 11:36:1831// The id of StatsReport of type kStatsReportTypeBwe.
32const char kStatsReportVideoBweId[] = "bweforvideo";
tommi@webrtc.orgc9d155f2014-12-09 18:18:0633
tommi@webrtc.org4fb7e252015-01-21 11:36:1834// NOTE: These names need to be consistent with an external
35// specification (W3C Stats Identifiers).
36const char* InternalTypeToString(StatsReport::StatsType type) {
37 switch (type) {
38 case StatsReport::kStatsReportTypeSession:
39 return "googLibjingleSession";
40 case StatsReport::kStatsReportTypeBwe:
41 return "VideoBwe";
42 case StatsReport::kStatsReportTypeRemoteSsrc:
43 return "remoteSsrc";
44 case StatsReport::kStatsReportTypeSsrc:
45 return "ssrc";
46 case StatsReport::kStatsReportTypeTrack:
47 return "googTrack";
48 case StatsReport::kStatsReportTypeIceLocalCandidate:
49 return "localcandidate";
50 case StatsReport::kStatsReportTypeIceRemoteCandidate:
51 return "remotecandidate";
52 case StatsReport::kStatsReportTypeTransport:
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:3053 return "transport";
tommi@webrtc.org4fb7e252015-01-21 11:36:1854 case StatsReport::kStatsReportTypeComponent:
55 return "googComponent";
56 case StatsReport::kStatsReportTypeCandidatePair:
57 return "googCandidatePair";
58 case StatsReport::kStatsReportTypeCertificate:
59 return "googCertificate";
60 case StatsReport::kStatsReportTypeDataChannel:
61 return "datachannel";
62 }
Artem Titovd3251962021-11-15 15:57:0763 RTC_DCHECK_NOTREACHED();
tommi@webrtc.org4fb7e252015-01-21 11:36:1864 return nullptr;
tommi@webrtc.orgc9d155f2014-12-09 18:18:0665}
66
tommi@webrtc.orgd3900292015-03-12 16:35:5567class BandwidthEstimationId : public StatsReport::IdBase {
tommi@webrtc.org4fb7e252015-01-21 11:36:1868 public:
tommi@webrtc.orgd3900292015-03-12 16:35:5569 BandwidthEstimationId()
70 : StatsReport::IdBase(StatsReport::kStatsReportTypeBwe) {}
tommi@webrtc.org4fb7e252015-01-21 11:36:1871 std::string ToString() const override { return kStatsReportVideoBweId; }
72};
tommi@webrtc.org8e327c42015-01-19 20:41:2673
tommi@webrtc.orgd3900292015-03-12 16:35:5574class TypedId : public StatsReport::IdBase {
tommi@webrtc.org4fb7e252015-01-21 11:36:1875 public:
tommi@webrtc.org4fb7e252015-01-21 11:36:1876 TypedId(StatsReport::StatsType type, const std::string& id)
tommi@webrtc.orgd3900292015-03-12 16:35:5577 : StatsReport::IdBase(type), id_(id) {}
tommi@webrtc.org8e327c42015-01-19 20:41:2678
tommi@webrtc.orgd3900292015-03-12 16:35:5579 bool Equals(const IdBase& other) const override {
80 return IdBase::Equals(other) &&
tommi@webrtc.org4fb7e252015-01-21 11:36:1881 static_cast<const TypedId&>(other).id_ == id_;
82 }
tommi@webrtc.orgc9d155f2014-12-09 18:18:0683
tommi@webrtc.org4fb7e252015-01-21 11:36:1884 std::string ToString() const override {
85 return std::string(InternalTypeToString(type_)) + kSeparator + id_;
86 }
tommi@webrtc.orgc9d155f2014-12-09 18:18:0687
tommi@webrtc.org4fb7e252015-01-21 11:36:1888 protected:
89 const std::string id_;
90};
tommi@webrtc.orgc9d155f2014-12-09 18:18:0691
tommi@webrtc.orgd3900292015-03-12 16:35:5592class TypedIntId : public StatsReport::IdBase {
decurtis@webrtc.org322a5642015-02-03 22:09:3793 public:
94 TypedIntId(StatsReport::StatsType type, int id)
tommi@webrtc.orgd3900292015-03-12 16:35:5595 : StatsReport::IdBase(type), id_(id) {}
decurtis@webrtc.org322a5642015-02-03 22:09:3796
tommi@webrtc.orgd3900292015-03-12 16:35:5597 bool Equals(const IdBase& other) const override {
98 return IdBase::Equals(other) &&
decurtis@webrtc.org322a5642015-02-03 22:09:3799 static_cast<const TypedIntId&>(other).id_ == id_;
100 }
101
102 std::string ToString() const override {
Yves Gerey665174f2018-06-19 13:03:05103 return std::string(InternalTypeToString(type_)) + kSeparator +
Jonas Olsson6b1985d2018-07-05 09:59:48104 rtc::ToString(id_);
decurtis@webrtc.org322a5642015-02-03 22:09:37105 }
106
107 protected:
108 const int id_;
109};
110
tommi@webrtc.org4fb7e252015-01-21 11:36:18111class IdWithDirection : public TypedId {
112 public:
Yves Gerey665174f2018-06-19 13:03:05113 IdWithDirection(StatsReport::StatsType type,
114 const std::string& id,
tommi@webrtc.org4fb7e252015-01-21 11:36:18115 StatsReport::Direction direction)
116 : TypedId(type, id), direction_(direction) {}
tommi@webrtc.orgc9d155f2014-12-09 18:18:06117
tommi@webrtc.orgd3900292015-03-12 16:35:55118 bool Equals(const IdBase& other) const override {
tommi@webrtc.org4fb7e252015-01-21 11:36:18119 return TypedId::Equals(other) &&
120 static_cast<const IdWithDirection&>(other).direction_ == direction_;
121 }
tommi@webrtc.orgc9d155f2014-12-09 18:18:06122
tommi@webrtc.org4fb7e252015-01-21 11:36:18123 std::string ToString() const override {
124 std::string ret(TypedId::ToString());
decurtis@webrtc.org322a5642015-02-03 22:09:37125 ret += kSeparator;
tommi@webrtc.org4fb7e252015-01-21 11:36:18126 ret += direction_ == StatsReport::kSend ? "send" : "recv";
127 return ret;
128 }
tommi@webrtc.orgc9d155f2014-12-09 18:18:06129
tommi@webrtc.org4fb7e252015-01-21 11:36:18130 private:
131 const StatsReport::Direction direction_;
132};
133
134class CandidateId : public TypedId {
135 public:
136 CandidateId(bool local, const std::string& id)
Yves Gerey665174f2018-06-19 13:03:05137 : TypedId(local ? StatsReport::kStatsReportTypeIceLocalCandidate
138 : StatsReport::kStatsReportTypeIceRemoteCandidate,
139 id) {}
tommi@webrtc.org4fb7e252015-01-21 11:36:18140
Yves Gerey665174f2018-06-19 13:03:05141 std::string ToString() const override { return "Cand-" + id_; }
tommi@webrtc.org4fb7e252015-01-21 11:36:18142};
143
tommi@webrtc.orgd3900292015-03-12 16:35:55144class ComponentId : public StatsReport::IdBase {
tommi@webrtc.org4fb7e252015-01-21 11:36:18145 public:
146 ComponentId(const std::string& content_name, int component)
Yves Gerey665174f2018-06-19 13:03:05147 : ComponentId(StatsReport::kStatsReportTypeComponent,
148 content_name,
149 component) {}
tommi@webrtc.org4fb7e252015-01-21 11:36:18150
tommi@webrtc.orgd3900292015-03-12 16:35:55151 bool Equals(const IdBase& other) const override {
152 return IdBase::Equals(other) &&
Yves Gerey665174f2018-06-19 13:03:05153 static_cast<const ComponentId&>(other).component_ == component_ &&
154 static_cast<const ComponentId&>(other).content_name_ ==
155 content_name_;
tommi@webrtc.org4fb7e252015-01-21 11:36:18156 }
157
Yves Gerey665174f2018-06-19 13:03:05158 std::string ToString() const override { return ToString("Channel-"); }
tommi@webrtc.org4fb7e252015-01-21 11:36:18159
160 protected:
Yves Gerey665174f2018-06-19 13:03:05161 ComponentId(StatsReport::StatsType type,
162 const std::string& content_name,
tommi@webrtc.org4fb7e252015-01-21 11:36:18163 int component)
Yves Gerey665174f2018-06-19 13:03:05164 : IdBase(type), content_name_(content_name), component_(component) {}
tommi@webrtc.org4fb7e252015-01-21 11:36:18165
166 std::string ToString(const char* prefix) const {
167 std::string ret(prefix);
168 ret += content_name_;
169 ret += '-';
Jonas Olsson6b1985d2018-07-05 09:59:48170 ret += rtc::ToString(component_);
tommi@webrtc.org4fb7e252015-01-21 11:36:18171 return ret;
172 }
173
174 private:
175 const std::string content_name_;
176 const int component_;
177};
178
179class CandidatePairId : public ComponentId {
180 public:
181 CandidatePairId(const std::string& content_name, int component, int index)
Yves Gerey665174f2018-06-19 13:03:05182 : ComponentId(StatsReport::kStatsReportTypeCandidatePair,
183 content_name,
184 component),
tommi@webrtc.org4fb7e252015-01-21 11:36:18185 index_(index) {}
186
tommi@webrtc.orgd3900292015-03-12 16:35:55187 bool Equals(const IdBase& other) const override {
tommi@webrtc.org4fb7e252015-01-21 11:36:18188 return ComponentId::Equals(other) &&
Yves Gerey665174f2018-06-19 13:03:05189 static_cast<const CandidatePairId&>(other).index_ == index_;
tommi@webrtc.org4fb7e252015-01-21 11:36:18190 }
191
192 std::string ToString() const override {
193 std::string ret(ComponentId::ToString("Conn-"));
194 ret += '-';
Jonas Olsson6b1985d2018-07-05 09:59:48195 ret += rtc::ToString(index_);
tommi@webrtc.org4fb7e252015-01-21 11:36:18196 return ret;
197 }
198
199 private:
200 const int index_;
201};
202
203} // namespace
204
tommi@webrtc.orgd3900292015-03-12 16:35:55205StatsReport::IdBase::IdBase(StatsType type) : type_(type) {}
206StatsReport::IdBase::~IdBase() {}
tommi@webrtc.org4fb7e252015-01-21 11:36:18207
Yves Gerey665174f2018-06-19 13:03:05208StatsReport::StatsType StatsReport::IdBase::type() const {
209 return type_;
210}
tommi@webrtc.org4fb7e252015-01-21 11:36:18211
tommi@webrtc.orgd3900292015-03-12 16:35:55212bool StatsReport::IdBase::Equals(const IdBase& other) const {
tommi@webrtc.org4fb7e252015-01-21 11:36:18213 return other.type_ == type_;
tommi@webrtc.orgc9d155f2014-12-09 18:18:06214}
215
Peter Boström0c4e06b2015-10-07 10:23:21216StatsReport::Value::Value(StatsValueName name, int64_t value, Type int_type)
tommi@webrtc.orgd3900292015-03-12 16:35:55217 : name(name), type_(int_type) {
henrikg91d6ede2015-09-17 07:24:34218 RTC_DCHECK(type_ == kInt || type_ == kInt64);
tommi@webrtc.orgd3900292015-03-12 16:35:55219 type_ == kInt ? value_.int_ = static_cast<int>(value) : value_.int64_ = value;
220}
221
222StatsReport::Value::Value(StatsValueName name, float f)
223 : name(name), type_(kFloat) {
224 value_.float_ = f;
225}
226
tommi@webrtc.orgc9d155f2014-12-09 18:18:06227StatsReport::Value::Value(StatsValueName name, const std::string& value)
tommi@webrtc.orgd3900292015-03-12 16:35:55228 : name(name), type_(kString) {
229 value_.string_ = new std::string(value);
230}
231
232StatsReport::Value::Value(StatsValueName name, const char* value)
233 : name(name), type_(kStaticString) {
234 value_.static_string_ = value;
235}
236
237StatsReport::Value::Value(StatsValueName name, bool b)
238 : name(name), type_(kBool) {
239 value_.bool_ = b;
240}
241
242StatsReport::Value::Value(StatsValueName name, const Id& value)
243 : name(name), type_(kId) {
244 value_.id_ = new Id(value);
245}
246
247StatsReport::Value::~Value() {
248 switch (type_) {
249 case kInt:
250 case kInt64:
251 case kFloat:
252 case kBool:
253 case kStaticString:
254 break;
255 case kString:
256 delete value_.string_;
257 break;
258 case kId:
259 delete value_.id_;
260 break;
261 }
262}
263
264bool StatsReport::Value::Equals(const Value& other) const {
265 if (name != other.name)
266 return false;
267
268 // There's a 1:1 relation between a name and a type, so we don't have to
269 // check that.
henrikg91d6ede2015-09-17 07:24:34270 RTC_DCHECK_EQ(type_, other.type_);
tommi@webrtc.orgd3900292015-03-12 16:35:55271
272 switch (type_) {
273 case kInt:
274 return value_.int_ == other.value_.int_;
275 case kInt64:
276 return value_.int64_ == other.value_.int64_;
277 case kFloat:
278 return value_.float_ == other.value_.float_;
279 case kStaticString: {
kwiberg5377bc72016-10-04 20:46:56280#if RTC_DCHECK_IS_ON
tommi@webrtc.orgd3900292015-03-12 16:35:55281 if (value_.static_string_ != other.value_.static_string_) {
henrikg91d6ede2015-09-17 07:24:34282 RTC_DCHECK(strcmp(value_.static_string_, other.value_.static_string_) !=
283 0)
tommi@webrtc.orgd3900292015-03-12 16:35:55284 << "Duplicate global?";
285 }
286#endif
287 return value_.static_string_ == other.value_.static_string_;
288 }
289 case kString:
290 return *value_.string_ == *other.value_.string_;
291 case kBool:
292 return value_.bool_ == other.value_.bool_;
293 case kId:
294 return (*value_.id_)->Equals(*other.value_.id_);
295 }
Artem Titovd3251962021-11-15 15:57:07296 RTC_DCHECK_NOTREACHED();
tommi@webrtc.orgd3900292015-03-12 16:35:55297 return false;
298}
299
300bool StatsReport::Value::operator==(const std::string& value) const {
301 return (type_ == kString && value_.string_->compare(value) == 0) ||
302 (type_ == kStaticString && value.compare(value_.static_string_) == 0);
303}
304
305bool StatsReport::Value::operator==(const char* value) const {
306 if (type_ == kString)
307 return value_.string_->compare(value) == 0;
308 if (type_ != kStaticString)
309 return false;
kwiberg5377bc72016-10-04 20:46:56310#if RTC_DCHECK_IS_ON
tommi@webrtc.orgd3900292015-03-12 16:35:55311 if (value_.static_string_ != value)
henrikg91d6ede2015-09-17 07:24:34312 RTC_DCHECK(strcmp(value_.static_string_, value) != 0)
313 << "Duplicate global?";
tommi@webrtc.orgd3900292015-03-12 16:35:55314#endif
315 return value == value_.static_string_;
316}
317
Peter Boström0c4e06b2015-10-07 10:23:21318bool StatsReport::Value::operator==(int64_t value) const {
Yves Gerey665174f2018-06-19 13:03:05319 return type_ == kInt ? value_.int_ == static_cast<int>(value)
320 : (type_ == kInt64 ? value_.int64_ == value : false);
tommi@webrtc.orgd3900292015-03-12 16:35:55321}
322
323bool StatsReport::Value::operator==(bool value) const {
324 return type_ == kBool && value_.bool_ == value;
325}
326
327bool StatsReport::Value::operator==(float value) const {
328 return type_ == kFloat && value_.float_ == value;
329}
330
331bool StatsReport::Value::operator==(const Id& value) const {
332 return type_ == kId && (*value_.id_)->Equals(value);
333}
334
335int StatsReport::Value::int_val() const {
Ruslan Burakov2594f272019-03-12 10:10:57336 RTC_DCHECK_EQ(type_, kInt);
tommi@webrtc.orgd3900292015-03-12 16:35:55337 return value_.int_;
338}
339
Peter Boström0c4e06b2015-10-07 10:23:21340int64_t StatsReport::Value::int64_val() const {
Ruslan Burakov2594f272019-03-12 10:10:57341 RTC_DCHECK_EQ(type_, kInt64);
tommi@webrtc.orgd3900292015-03-12 16:35:55342 return value_.int64_;
343}
344
345float StatsReport::Value::float_val() const {
Ruslan Burakov2594f272019-03-12 10:10:57346 RTC_DCHECK_EQ(type_, kFloat);
tommi@webrtc.orgd3900292015-03-12 16:35:55347 return value_.float_;
348}
349
350const char* StatsReport::Value::static_string_val() const {
Ruslan Burakov2594f272019-03-12 10:10:57351 RTC_DCHECK_EQ(type_, kStaticString);
tommi@webrtc.orgd3900292015-03-12 16:35:55352 return value_.static_string_;
353}
354
355const std::string& StatsReport::Value::string_val() const {
Ruslan Burakov2594f272019-03-12 10:10:57356 RTC_DCHECK_EQ(type_, kString);
tommi@webrtc.orgd3900292015-03-12 16:35:55357 return *value_.string_;
358}
359
360bool StatsReport::Value::bool_val() const {
Ruslan Burakov2594f272019-03-12 10:10:57361 RTC_DCHECK_EQ(type_, kBool);
tommi@webrtc.orgd3900292015-03-12 16:35:55362 return value_.bool_;
tommi@webrtc.orgc9d155f2014-12-09 18:18:06363}
364
tommi@webrtc.orgc9d155f2014-12-09 18:18:06365const char* StatsReport::Value::display_name() const {
tommi@webrtc.orgc57310b2014-12-12 17:41:28366 switch (name) {
Minyue2a8a78c2016-04-07 14:48:15367 case kStatsValueNameAecDivergentFilterFraction:
368 return "aecDivergentFilterFraction";
tommi@webrtc.orgc57310b2014-12-12 17:41:28369 case kStatsValueNameAudioOutputLevel:
370 return "audioOutputLevel";
371 case kStatsValueNameAudioInputLevel:
372 return "audioInputLevel";
373 case kStatsValueNameBytesSent:
374 return "bytesSent";
Steve Anton2dbc69f2017-08-25 00:15:13375 case kStatsValueNameConcealedSamples:
376 return "concealedSamples";
Gustaf Ullberg9a2e9062017-09-18 07:28:20377 case kStatsValueNameConcealmentEvents:
378 return "concealmentEvents";
tommi@webrtc.orgc57310b2014-12-12 17:41:28379 case kStatsValueNamePacketsSent:
380 return "packetsSent";
381 case kStatsValueNameBytesReceived:
382 return "bytesReceived";
decurtis@webrtc.org487a4442015-01-15 22:55:07383 case kStatsValueNameLabel:
384 return "label";
tommi@webrtc.orgc57310b2014-12-12 17:41:28385 case kStatsValueNamePacketsReceived:
386 return "packetsReceived";
387 case kStatsValueNamePacketsLost:
388 return "packetsLost";
decurtis@webrtc.org487a4442015-01-15 22:55:07389 case kStatsValueNameProtocol:
390 return "protocol";
Steve Anton2dbc69f2017-08-25 00:15:13391 case kStatsValueNameTotalSamplesReceived:
392 return "totalSamplesReceived";
tommi@webrtc.orgc57310b2014-12-12 17:41:28393 case kStatsValueNameTransportId:
394 return "transportId";
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:30395 case kStatsValueNameSelectedCandidatePairId:
396 return "selectedCandidatePairId";
tommi@webrtc.orgc57310b2014-12-12 17:41:28397 case kStatsValueNameSsrc:
398 return "ssrc";
decurtis@webrtc.org487a4442015-01-15 22:55:07399 case kStatsValueNameState:
400 return "state";
401 case kStatsValueNameDataChannelId:
402 return "datachannelid";
sakale5ba44e2016-10-26 14:09:24403 case kStatsValueNameFramesDecoded:
404 return "framesDecoded";
sakal43536c32016-10-24 08:46:43405 case kStatsValueNameFramesEncoded:
406 return "framesEncoded";
Gustaf Ullbergb0a02072017-10-02 10:00:34407 case kStatsValueNameJitterBufferDelay:
408 return "jitterBufferDelay";
Peter Boströmb7d9a972015-12-18 15:01:11409 case kStatsValueNameCodecImplementationName:
410 return "codecImplementationName";
fippobec70ab2016-01-28 09:27:15411 case kStatsValueNameMediaType:
412 return "mediaType";
sakal87da4042016-10-31 13:53:47413 case kStatsValueNameQpSum:
414 return "qpSum";
tommi@webrtc.orgc57310b2014-12-12 17:41:28415 // 'goog' prefixed constants.
Henrik Lundin8e6fd462015-06-02 07:24:52416 case kStatsValueNameAccelerateRate:
417 return "googAccelerateRate";
tommi@webrtc.orgc57310b2014-12-12 17:41:28418 case kStatsValueNameActiveConnection:
419 return "googActiveConnection";
420 case kStatsValueNameActualEncBitrate:
421 return "googActualEncBitrate";
422 case kStatsValueNameAvailableReceiveBandwidth:
423 return "googAvailableReceiveBandwidth";
424 case kStatsValueNameAvailableSendBandwidth:
425 return "googAvailableSendBandwidth";
426 case kStatsValueNameAvgEncodeMs:
427 return "googAvgEncodeMs";
428 case kStatsValueNameBucketDelay:
429 return "googBucketDelay";
430 case kStatsValueNameBandwidthLimitedResolution:
431 return "googBandwidthLimitedResolution";
zhihuang5ecf16c2016-06-02 00:09:15432 // STUN ping related attributes.
Qingsi Wang72a43a12018-02-21 00:03:18433 //
zhihuang5ecf16c2016-06-02 00:09:15434 // TODO(zhihuang) Rename these stats to follow the standards.
Qingsi Wang72a43a12018-02-21 00:03:18435 // Connectivity checks.
zhihuang5ecf16c2016-06-02 00:09:15436 case kStatsValueNameSentPingRequestsTotal:
437 return "requestsSent";
438 case kStatsValueNameSentPingRequestsBeforeFirstResponse:
439 return "consentRequestsSent";
440 case kStatsValueNameSentPingResponses:
441 return "responsesSent";
442 case kStatsValueNameRecvPingRequests:
443 return "requestsReceived";
444 case kStatsValueNameRecvPingResponses:
445 return "responsesReceived";
Qingsi Wang72a43a12018-02-21 00:03:18446 // STUN Keepalive pings.
447 case kStatsValueNameSentStunKeepaliveRequests:
448 return "stunKeepaliveRequestsSent";
449 case kStatsValueNameRecvStunKeepaliveResponses:
450 return "stunKeepaliveResponsesReceived";
451 case kStatsValueNameStunKeepaliveRttTotal:
452 return "stunKeepaliveRttTotal";
453 case kStatsValueNameStunKeepaliveRttSquaredTotal:
454 return "stunKeepaliveRttSquaredTotal";
guoweis@webrtc.org950c5182014-12-16 23:01:31455
456 // Candidate related attributes. Values are taken from
457 // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
458 case kStatsValueNameCandidateIPAddress:
459 return "ipAddress";
460 case kStatsValueNameCandidateNetworkType:
461 return "networkType";
462 case kStatsValueNameCandidatePortNumber:
463 return "portNumber";
464 case kStatsValueNameCandidatePriority:
465 return "priority";
466 case kStatsValueNameCandidateTransportType:
467 return "transport";
468 case kStatsValueNameCandidateType:
469 return "candidateType";
470
tommi@webrtc.orgc57310b2014-12-12 17:41:28471 case kStatsValueNameChannelId:
472 return "googChannelId";
473 case kStatsValueNameCodecName:
474 return "googCodecName";
475 case kStatsValueNameComponent:
476 return "googComponent";
477 case kStatsValueNameContentName:
478 return "googContentName";
ilnik2e1b40b2017-09-04 14:57:17479 case kStatsValueNameContentType:
480 return "googContentType";
tommi@webrtc.orgc57310b2014-12-12 17:41:28481 case kStatsValueNameCpuLimitedResolution:
482 return "googCpuLimitedResolution";
483 case kStatsValueNameDecodingCTSG:
484 return "googDecodingCTSG";
485 case kStatsValueNameDecodingCTN:
486 return "googDecodingCTN";
henrik.lundin63489782016-09-20 08:47:12487 case kStatsValueNameDecodingMutedOutput:
488 return "googDecodingMuted";
tommi@webrtc.orgc57310b2014-12-12 17:41:28489 case kStatsValueNameDecodingNormal:
490 return "googDecodingNormal";
491 case kStatsValueNameDecodingPLC:
492 return "googDecodingPLC";
Alex Narest5b5d97c2019-08-07 16:15:08493 case kStatsValueNameDecodingCodecPLC:
494 return "googDecodingCodecPLC";
tommi@webrtc.orgc57310b2014-12-12 17:41:28495 case kStatsValueNameDecodingCNG:
496 return "googDecodingCNG";
497 case kStatsValueNameDecodingPLCCNG:
498 return "googDecodingPLCCNG";
499 case kStatsValueNameDer:
500 return "googDerBase64";
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:30501 case kStatsValueNameDtlsCipher:
502 return "dtlsCipher";
tommi@webrtc.orgc57310b2014-12-12 17:41:28503 case kStatsValueNameEchoDelayMedian:
504 return "googEchoCancellationEchoDelayMedian";
505 case kStatsValueNameEchoDelayStdDev:
506 return "googEchoCancellationEchoDelayStdDev";
507 case kStatsValueNameEchoReturnLoss:
508 return "googEchoCancellationReturnLoss";
509 case kStatsValueNameEchoReturnLossEnhancement:
510 return "googEchoCancellationReturnLossEnhancement";
511 case kStatsValueNameEncodeUsagePercent:
512 return "googEncodeUsagePercent";
513 case kStatsValueNameExpandRate:
514 return "googExpandRate";
515 case kStatsValueNameFingerprint:
516 return "googFingerprint";
517 case kStatsValueNameFingerprintAlgorithm:
518 return "googFingerprintAlgorithm";
519 case kStatsValueNameFirsReceived:
520 return "googFirsReceived";
521 case kStatsValueNameFirsSent:
522 return "googFirsSent";
Benjamin Wright514f0842018-12-10 17:55:17523 case kStatsValueNameFirstFrameReceivedToDecodedMs:
524 return "googFirstFrameReceivedToDecodedMs";
tommi@webrtc.orgc57310b2014-12-12 17:41:28525 case kStatsValueNameFrameHeightInput:
526 return "googFrameHeightInput";
527 case kStatsValueNameFrameHeightReceived:
528 return "googFrameHeightReceived";
529 case kStatsValueNameFrameHeightSent:
530 return "googFrameHeightSent";
531 case kStatsValueNameFrameRateReceived:
532 return "googFrameRateReceived";
533 case kStatsValueNameFrameRateDecoded:
534 return "googFrameRateDecoded";
535 case kStatsValueNameFrameRateOutput:
536 return "googFrameRateOutput";
537 case kStatsValueNameDecodeMs:
538 return "googDecodeMs";
539 case kStatsValueNameMaxDecodeMs:
540 return "googMaxDecodeMs";
541 case kStatsValueNameCurrentDelayMs:
542 return "googCurrentDelayMs";
543 case kStatsValueNameTargetDelayMs:
544 return "googTargetDelayMs";
545 case kStatsValueNameJitterBufferMs:
546 return "googJitterBufferMs";
547 case kStatsValueNameMinPlayoutDelayMs:
548 return "googMinPlayoutDelayMs";
549 case kStatsValueNameRenderDelayMs:
550 return "googRenderDelayMs";
551 case kStatsValueNameCaptureStartNtpTimeMs:
552 return "googCaptureStartNtpTimeMs";
553 case kStatsValueNameFrameRateInput:
554 return "googFrameRateInput";
555 case kStatsValueNameFrameRateSent:
556 return "googFrameRateSent";
557 case kStatsValueNameFrameWidthInput:
558 return "googFrameWidthInput";
559 case kStatsValueNameFrameWidthReceived:
560 return "googFrameWidthReceived";
561 case kStatsValueNameFrameWidthSent:
562 return "googFrameWidthSent";
Åsa Perssonc3ed6302017-11-16 13:04:52563 case kStatsValueNameHasEnteredLowResolution:
564 return "googHasEnteredLowResolution";
Ilya Nikolaevskiy70473fc2018-02-28 15:35:03565 case kStatsValueNameHugeFramesSent:
566 return "hugeFramesSent";
tommi@webrtc.orgc57310b2014-12-12 17:41:28567 case kStatsValueNameInitiator:
568 return "googInitiator";
ilnika79cc282017-08-23 12:24:10569 case kStatsValueNameInterframeDelayMaxMs:
570 return "googInterframeDelayMax";
tommi@webrtc.orgc57310b2014-12-12 17:41:28571 case kStatsValueNameIssuerId:
572 return "googIssuerId";
573 case kStatsValueNameJitterReceived:
574 return "googJitterReceived";
575 case kStatsValueNameLocalAddress:
576 return "googLocalAddress";
guoweis@webrtc.org950c5182014-12-16 23:01:31577 case kStatsValueNameLocalCandidateId:
578 return "localCandidateId";
tommi@webrtc.orgc57310b2014-12-12 17:41:28579 case kStatsValueNameLocalCandidateType:
580 return "googLocalCandidateType";
581 case kStatsValueNameLocalCertificateId:
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:30582 return "localCertificateId";
tommi@webrtc.orgc57310b2014-12-12 17:41:28583 case kStatsValueNameAdaptationChanges:
584 return "googAdaptationChanges";
585 case kStatsValueNameNacksReceived:
586 return "googNacksReceived";
587 case kStatsValueNameNacksSent:
588 return "googNacksSent";
Henrik Lundin8e6fd462015-06-02 07:24:52589 case kStatsValueNamePreemptiveExpandRate:
590 return "googPreemptiveExpandRate";
tommi@webrtc.orgc57310b2014-12-12 17:41:28591 case kStatsValueNamePlisReceived:
592 return "googPlisReceived";
593 case kStatsValueNamePlisSent:
594 return "googPlisSent";
595 case kStatsValueNamePreferredJitterBufferMs:
596 return "googPreferredJitterBufferMs";
Peter Thatcher04ac81f2015-09-21 18:48:28597 case kStatsValueNameReceiving:
tommi@webrtc.orgc57310b2014-12-12 17:41:28598 return "googReadable";
tommi@webrtc.orgc57310b2014-12-12 17:41:28599 case kStatsValueNameRemoteAddress:
600 return "googRemoteAddress";
guoweis@webrtc.org950c5182014-12-16 23:01:31601 case kStatsValueNameRemoteCandidateId:
602 return "remoteCandidateId";
tommi@webrtc.orgc57310b2014-12-12 17:41:28603 case kStatsValueNameRemoteCandidateType:
604 return "googRemoteCandidateType";
605 case kStatsValueNameRemoteCertificateId:
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:30606 return "remoteCertificateId";
ivoc8c63a822016-10-21 11:10:03607 case kStatsValueNameResidualEchoLikelihood:
608 return "googResidualEchoLikelihood";
ivoc4e477a12017-01-15 16:29:46609 case kStatsValueNameResidualEchoLikelihoodRecentMax:
610 return "googResidualEchoLikelihoodRecentMax";
ivoce1198e02017-09-08 15:13:19611 case kStatsValueNameAnaBitrateActionCounter:
612 return "googAnaBitrateActionCounter";
613 case kStatsValueNameAnaChannelActionCounter:
614 return "googAnaChannelActionCounter";
615 case kStatsValueNameAnaDtxActionCounter:
616 return "googAnaDtxActionCounter";
617 case kStatsValueNameAnaFecActionCounter:
618 return "googAnaFecActionCounter";
ivoc0d0b9122017-09-08 20:24:21619 case kStatsValueNameAnaFrameLengthIncreaseCounter:
620 return "googAnaFrameLengthIncreaseCounter";
621 case kStatsValueNameAnaFrameLengthDecreaseCounter:
622 return "googAnaFrameLengthDecreaseCounter";
623 case kStatsValueNameAnaUplinkPacketLossFraction:
624 return "googAnaUplinkPacketLossFraction";
tommi@webrtc.orgc57310b2014-12-12 17:41:28625 case kStatsValueNameRetransmitBitrate:
626 return "googRetransmitBitrate";
627 case kStatsValueNameRtt:
628 return "googRtt";
minyue@webrtc.org652bc372015-02-18 23:50:46629 case kStatsValueNameSecondaryDecodedRate:
630 return "googSecondaryDecodedRate";
minyue-webrtc0e320ec2017-08-28 11:51:27631 case kStatsValueNameSecondaryDiscardedRate:
632 return "googSecondaryDiscardedRate";
tommi@webrtc.orgc57310b2014-12-12 17:41:28633 case kStatsValueNameSendPacketsDiscarded:
634 return "packetsDiscardedOnSend";
minyue@webrtc.org652bc372015-02-18 23:50:46635 case kStatsValueNameSpeechExpandRate:
636 return "googSpeechExpandRate";
pthatcher@webrtc.org7bea1ff2015-03-04 01:38:30637 case kStatsValueNameSrtpCipher:
638 return "srtpCipher";
tommi@webrtc.orgc57310b2014-12-12 17:41:28639 case kStatsValueNameTargetEncBitrate:
640 return "googTargetEncBitrate";
zsteine76bd3a2017-07-14 19:17:49641 case kStatsValueNameTotalAudioEnergy:
642 return "totalAudioEnergy";
643 case kStatsValueNameTotalSamplesDuration:
644 return "totalSamplesDuration";
tommi@webrtc.orgc57310b2014-12-12 17:41:28645 case kStatsValueNameTransmitBitrate:
646 return "googTransmitBitrate";
647 case kStatsValueNameTransportType:
648 return "googTransportType";
649 case kStatsValueNameTrackId:
650 return "googTrackId";
ilnik2edc6842017-07-06 10:06:50651 case kStatsValueNameTimingFrameInfo:
652 return "googTimingFrameInfo";
tommi@webrtc.orgc57310b2014-12-12 17:41:28653 case kStatsValueNameWritable:
654 return "googWritable";
Alex Narestbbeb1092019-08-16 09:49:04655 case kStatsValueNameAudioDeviceUnderrunCounter:
656 return "googAudioDeviceUnderrunCounter";
Jonas Oreland0ee44222021-12-02 09:48:45657 case kStatsValueNameLocalCandidateRelayProtocol:
658 return "googLocalCandidateRelayProtocol";
tommi@webrtc.orgc57310b2014-12-12 17:41:28659 }
660
661 return nullptr;
tommi@webrtc.orgc9d155f2014-12-09 18:18:06662}
663
tommi@webrtc.orgd3900292015-03-12 16:35:55664std::string StatsReport::Value::ToString() const {
665 switch (type_) {
666 case kInt:
667 return rtc::ToString(value_.int_);
668 case kInt64:
669 return rtc::ToString(value_.int64_);
670 case kFloat:
671 return rtc::ToString(value_.float_);
672 case kStaticString:
673 return std::string(value_.static_string_);
674 case kString:
675 return *value_.string_;
676 case kBool:
677 return value_.bool_ ? "true" : "false";
678 case kId:
679 return (*value_.id_)->ToString();
680 }
Artem Titovd3251962021-11-15 15:57:07681 RTC_DCHECK_NOTREACHED();
tommi@webrtc.orgd3900292015-03-12 16:35:55682 return std::string();
tommi@webrtc.orgafa6d162015-03-02 11:27:48683}
684
tommi@webrtc.orgd3900292015-03-12 16:35:55685StatsReport::StatsReport(const Id& id) : id_(id), timestamp_(0.0) {
henrikg91d6ede2015-09-17 07:24:34686 RTC_DCHECK(id_.get());
tommi@webrtc.org4fb7e252015-01-21 11:36:18687}
688
ossu7bb87ee2017-01-23 12:56:25689StatsReport::~StatsReport() = default;
690
tommi@webrtc.org4fb7e252015-01-21 11:36:18691// static
tommi@webrtc.orgd3900292015-03-12 16:35:55692StatsReport::Id StatsReport::NewBandwidthEstimationId() {
Niels Möllerbf750412021-07-22 08:08:25693 return rtc::make_ref_counted<BandwidthEstimationId>();
tommi@webrtc.org4fb7e252015-01-21 11:36:18694}
695
696// static
tommi@webrtc.orgd3900292015-03-12 16:35:55697StatsReport::Id StatsReport::NewTypedId(StatsType type, const std::string& id) {
Niels Möllerbf750412021-07-22 08:08:25698 return rtc::make_ref_counted<TypedId>(type, id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18699}
700
701// static
tommi@webrtc.orgd3900292015-03-12 16:35:55702StatsReport::Id StatsReport::NewTypedIntId(StatsType type, int id) {
Niels Möllerbf750412021-07-22 08:08:25703 return rtc::make_ref_counted<TypedIntId>(type, id);
decurtis@webrtc.org322a5642015-02-03 22:09:37704}
705
706// static
tommi@webrtc.orgd3900292015-03-12 16:35:55707StatsReport::Id StatsReport::NewIdWithDirection(
Yves Gerey665174f2018-06-19 13:03:05708 StatsType type,
709 const std::string& id,
710 StatsReport::Direction direction) {
Niels Möllerbf750412021-07-22 08:08:25711 return rtc::make_ref_counted<IdWithDirection>(type, id, direction);
tommi@webrtc.org4fb7e252015-01-21 11:36:18712}
713
714// static
tommi@webrtc.orgd3900292015-03-12 16:35:55715StatsReport::Id StatsReport::NewCandidateId(bool local, const std::string& id) {
Niels Möllerbf750412021-07-22 08:08:25716 return rtc::make_ref_counted<CandidateId>(local, id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18717}
718
719// static
Yves Gerey665174f2018-06-19 13:03:05720StatsReport::Id StatsReport::NewComponentId(const std::string& content_name,
721 int component) {
Niels Möllerbf750412021-07-22 08:08:25722 return rtc::make_ref_counted<ComponentId>(content_name, component);
tommi@webrtc.org4fb7e252015-01-21 11:36:18723}
724
725// static
Yves Gerey665174f2018-06-19 13:03:05726StatsReport::Id StatsReport::NewCandidatePairId(const std::string& content_name,
727 int component,
728 int index) {
Niels Möllerbf750412021-07-22 08:08:25729 return rtc::make_ref_counted<CandidatePairId>(content_name, component, index);
tommi@webrtc.org4fb7e252015-01-21 11:36:18730}
731
732const char* StatsReport::TypeToString() const {
733 return InternalTypeToString(id_->type());
734}
735
tommi@webrtc.org92f40182015-03-04 15:25:19736void StatsReport::AddString(StatsReport::StatsValueName name,
737 const std::string& value) {
tommi@webrtc.orgd3900292015-03-12 16:35:55738 const Value* found = FindValue(name);
739 if (!found || !(*found == value))
740 values_[name] = ValuePtr(new Value(name, value));
741}
742
743void StatsReport::AddString(StatsReport::StatsValueName name,
744 const char* value) {
745 const Value* found = FindValue(name);
746 if (!found || !(*found == value))
747 values_[name] = ValuePtr(new Value(name, value));
tommi@webrtc.orgc9d155f2014-12-09 18:18:06748}
749
Peter Boström0c4e06b2015-10-07 10:23:21750void StatsReport::AddInt64(StatsReport::StatsValueName name, int64_t value) {
tommi@webrtc.orgd3900292015-03-12 16:35:55751 const Value* found = FindValue(name);
752 if (!found || !(*found == value))
753 values_[name] = ValuePtr(new Value(name, value, Value::kInt64));
tommi@webrtc.orgc9d155f2014-12-09 18:18:06754}
755
tommi@webrtc.org92f40182015-03-04 15:25:19756void StatsReport::AddInt(StatsReport::StatsValueName name, int value) {
tommi@webrtc.orgd3900292015-03-12 16:35:55757 const Value* found = FindValue(name);
Peter Boström0c4e06b2015-10-07 10:23:21758 if (!found || !(*found == static_cast<int64_t>(value)))
tommi@webrtc.orgd3900292015-03-12 16:35:55759 values_[name] = ValuePtr(new Value(name, value, Value::kInt));
tommi@webrtc.orgc9d155f2014-12-09 18:18:06760}
761
tommi@webrtc.org92f40182015-03-04 15:25:19762void StatsReport::AddFloat(StatsReport::StatsValueName name, float value) {
tommi@webrtc.orgd3900292015-03-12 16:35:55763 const Value* found = FindValue(name);
764 if (!found || !(*found == value))
765 values_[name] = ValuePtr(new Value(name, value));
tommi@webrtc.org92f40182015-03-04 15:25:19766}
tommi@webrtc.orgc9d155f2014-12-09 18:18:06767
768void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) {
tommi@webrtc.orgd3900292015-03-12 16:35:55769 const Value* found = FindValue(name);
770 if (!found || !(*found == value))
771 values_[name] = ValuePtr(new Value(name, value));
tommi@webrtc.org8e327c42015-01-19 20:41:26772}
773
Yves Gerey665174f2018-06-19 13:03:05774void StatsReport::AddId(StatsReport::StatsValueName name, const Id& value) {
tommi@webrtc.orgd3900292015-03-12 16:35:55775 const Value* found = FindValue(name);
776 if (!found || !(*found == value))
777 values_[name] = ValuePtr(new Value(name, value));
tommi@webrtc.orgc9d155f2014-12-09 18:18:06778}
779
tommi@webrtc.org4fb7e252015-01-21 11:36:18780const StatsReport::Value* StatsReport::FindValue(StatsValueName name) const {
tommi@webrtc.org92f40182015-03-04 15:25:19781 Values::const_iterator it = values_.find(name);
782 return it == values_.end() ? nullptr : it->second.get();
tommi@webrtc.orgc9d155f2014-12-09 18:18:06783}
784
Yves Gerey665174f2018-06-19 13:03:05785StatsCollection::StatsCollection() {}
tommi@webrtc.orgc9d155f2014-12-09 18:18:06786
tommi@webrtc.org4fb7e252015-01-21 11:36:18787StatsCollection::~StatsCollection() {
Tommi0fe65102023-03-31 10:09:30788 RTC_DCHECK_RUN_ON(&thread_checker_);
tommi@webrtc.org4fb7e252015-01-21 11:36:18789 for (auto* r : list_)
790 delete r;
791}
792
793StatsCollection::const_iterator StatsCollection::begin() const {
Tommi0fe65102023-03-31 10:09:30794 RTC_DCHECK_RUN_ON(&thread_checker_);
tommi@webrtc.orgc9d155f2014-12-09 18:18:06795 return list_.begin();
796}
797
tommi@webrtc.org4fb7e252015-01-21 11:36:18798StatsCollection::const_iterator StatsCollection::end() const {
Tommi0fe65102023-03-31 10:09:30799 RTC_DCHECK_RUN_ON(&thread_checker_);
tommi@webrtc.orgc9d155f2014-12-09 18:18:06800 return list_.end();
801}
802
tommi@webrtc.org4fb7e252015-01-21 11:36:18803size_t StatsCollection::size() const {
Tommi0fe65102023-03-31 10:09:30804 RTC_DCHECK_RUN_ON(&thread_checker_);
tommi@webrtc.org4fb7e252015-01-21 11:36:18805 return list_.size();
tommi@webrtc.orgc9d155f2014-12-09 18:18:06806}
807
tommi@webrtc.orgd3900292015-03-12 16:35:55808StatsReport* StatsCollection::InsertNew(const StatsReport::Id& id) {
Tommi0fe65102023-03-31 10:09:30809 RTC_DCHECK_RUN_ON(&thread_checker_);
henrikg91d6ede2015-09-17 07:24:34810 RTC_DCHECK(Find(id) == nullptr);
tommi@webrtc.orgd3900292015-03-12 16:35:55811 StatsReport* report = new StatsReport(id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18812 list_.push_back(report);
813 return report;
tommi@webrtc.orgc9d155f2014-12-09 18:18:06814}
815
tommi@webrtc.orgd3900292015-03-12 16:35:55816StatsReport* StatsCollection::FindOrAddNew(const StatsReport::Id& id) {
Tommi0fe65102023-03-31 10:09:30817 RTC_DCHECK_RUN_ON(&thread_checker_);
tommi@webrtc.orgd3900292015-03-12 16:35:55818 StatsReport* ret = Find(id);
819 return ret ? ret : InsertNew(id);
tommi@webrtc.org4fb7e252015-01-21 11:36:18820}
821
tommi@webrtc.orgd3900292015-03-12 16:35:55822StatsReport* StatsCollection::ReplaceOrAddNew(const StatsReport::Id& id) {
Tommi0fe65102023-03-31 10:09:30823 RTC_DCHECK_RUN_ON(&thread_checker_);
henrikg91d6ede2015-09-17 07:24:34824 RTC_DCHECK(id.get());
Steve Antona59dcc32019-03-25 20:53:07825 Container::iterator it = absl::c_find_if(
826 list_,
Yves Gerey665174f2018-06-19 13:03:05827 [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
tommi@webrtc.org4fb7e252015-01-21 11:36:18828 if (it != end()) {
tommi@webrtc.orgd3900292015-03-12 16:35:55829 StatsReport* report = new StatsReport((*it)->id());
tommi@webrtc.org4fb7e252015-01-21 11:36:18830 delete *it;
tommi@webrtc.org4fb7e252015-01-21 11:36:18831 *it = report;
832 return report;
833 }
tommi@webrtc.orgd3900292015-03-12 16:35:55834 return InsertNew(id);
tommi@webrtc.orgc9d155f2014-12-09 18:18:06835}
836
Tommi0fe65102023-03-31 10:09:30837StatsCollection::Container StatsCollection::DetachCollection() {
838 RTC_DCHECK_RUN_ON(&thread_checker_);
839#if RTC_DCHECK_IS_ON
840 for (auto* report : list_)
841 report->DetachSequenceCheckers();
842#endif
843 return std::move(list_);
844}
845
846void StatsCollection::MergeCollection(Container collection) {
847 RTC_DCHECK_RUN_ON(&thread_checker_);
848 for (auto* report : collection) {
849#if RTC_DCHECK_IS_ON
850 report->AttachSequenceCheckers();
851#endif
852 Container::iterator it = absl::c_find_if(list_, [&](const StatsReport* r) {
853 return r->id()->Equals(report->id());
854 });
855 if (it == list_.end()) {
856 list_.push_back(report);
857 } else {
858 delete *it;
859 *it = report;
860 }
861 }
862}
863
Artem Titov0e61fdd2021-07-25 19:50:14864// Looks for a report with the given `id`. If one is not found, null
tommi@webrtc.orgc9d155f2014-12-09 18:18:06865// will be returned.
tommi@webrtc.org4fb7e252015-01-21 11:36:18866StatsReport* StatsCollection::Find(const StatsReport::Id& id) {
Tommi0fe65102023-03-31 10:09:30867 RTC_DCHECK_RUN_ON(&thread_checker_);
Steve Antona59dcc32019-03-25 20:53:07868 Container::iterator it = absl::c_find_if(
869 list_,
Yves Gerey665174f2018-06-19 13:03:05870 [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
tommi@webrtc.org4fb7e252015-01-21 11:36:18871 return it == list_.end() ? nullptr : *it;
872}
873
tommi@webrtc.org5c3ee4b2014-12-09 10:47:01874} // namespace webrtc