blob: e6d9d184fe7a692f7d69cdc7746e52016e5678ca [file] [log] [blame]
hbosd565b732016-08-30 14:04:35 -07001/*
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
Steve Anton10542f22019-01-11 09:11:00 -080011#ifndef PC_RTC_STATS_COLLECTOR_H_
12#define PC_RTC_STATS_COLLECTOR_H_
hbosd565b732016-08-30 14:04:35 -070013
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000014#include <stdint.h>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000015
16#include <cstdint>
hbos2fa7c672016-10-24 04:00:05 -070017#include <map>
hbosd565b732016-08-30 14:04:35 -070018#include <memory>
hbos82ebe022016-11-14 01:41:09 -080019#include <set>
Steve Anton36b29d12017-10-30 09:57:42 -070020#include <string>
hbosc82f2e12016-09-05 01:36:50 -070021#include <vector>
hbosd565b732016-08-30 14:04:35 -070022
Danil Chapovalov66cadcc2018-06-19 16:47:43 +020023#include "absl/types/optional.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000024#include "api/data_channel_interface.h"
25#include "api/media_types.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010026#include "api/scoped_refptr.h"
Steve Anton10542f22019-01-11 09:11:00 -080027#include "api/stats/rtc_stats_collector_callback.h"
28#include "api/stats/rtc_stats_report.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "api/stats/rtcstats_objects.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "call/call.h"
Steve Anton10542f22019-01-11 09:11:00 -080031#include "media/base/media_channel.h"
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070032#include "pc/data_channel_utils.h"
Steve Anton10542f22019-01-11 09:11:00 -080033#include "pc/peer_connection_internal.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000034#include "pc/rtp_receiver.h"
35#include "pc/rtp_sender.h"
36#include "pc/rtp_transceiver.h"
37#include "pc/sctp_data_channel.h"
Steve Anton10542f22019-01-11 09:11:00 -080038#include "pc/track_media_info_map.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000039#include "pc/transport_stats.h"
40#include "rtc_base/checks.h"
Henrik Boström40b030e2019-02-28 09:49:31 +010041#include "rtc_base/event.h"
Steve Anton10542f22019-01-11 09:11:00 -080042#include "rtc_base/ref_count.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000043#include "rtc_base/ssl_certificate.h"
Steve Anton10542f22019-01-11 09:11:00 -080044#include "rtc_base/ssl_identity.h"
Artem Titove41c4332018-07-25 15:04:28 +020045#include "rtc_base/third_party/sigslot/sigslot.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000046#include "rtc_base/thread.h"
Steve Anton10542f22019-01-11 09:11:00 -080047#include "rtc_base/time_utils.h"
hbosd565b732016-08-30 14:04:35 -070048
49namespace webrtc {
50
Henrik Boström5b3541f2018-03-19 13:52:56 +010051class RtpSenderInternal;
52class RtpReceiverInternal;
53
hbosc82f2e12016-09-05 01:36:50 -070054// All public methods of the collector are to be called on the signaling thread.
55// Stats are gathered on the signaling, worker and network threads
56// asynchronously. The callback is invoked on the signaling thread. Resulting
Artem Titov880fa812021-07-30 22:30:23 +020057// reports are cached for `cache_lifetime_` ms.
Tomas Gunnarssone6de5ae2021-04-22 18:16:35 +020058class RTCStatsCollector : public rtc::RefCountInterface,
hbos82ebe022016-11-14 01:41:09 -080059 public sigslot::has_slots<> {
hbosc82f2e12016-09-05 01:36:50 -070060 public:
61 static rtc::scoped_refptr<RTCStatsCollector> Create(
Steve Anton2d8609c2018-01-23 16:38:46 -080062 PeerConnectionInternal* pc,
hbos0e6758d2016-08-31 07:57:36 -070063 int64_t cache_lifetime_us = 50 * rtc::kNumMicrosecsPerMillisec);
hbosd565b732016-08-30 14:04:35 -070064
65 // Gets a recent stats report. If there is a report cached that is still fresh
66 // it is returned, otherwise new stats are gathered and returned. A report is
Artem Titov880fa812021-07-30 22:30:23 +020067 // considered fresh for `cache_lifetime_` ms. const RTCStatsReports are safe
hbosd565b732016-08-30 14:04:35 -070068 // to use across multiple threads and may be destructed on any thread.
Henrik Boström5b3541f2018-03-19 13:52:56 +010069 // If the optional selector argument is used, stats are filtered according to
70 // stats selection algorithm before delivery.
71 // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm
hbosc82f2e12016-09-05 01:36:50 -070072 void GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
Artem Titov880fa812021-07-30 22:30:23 +020073 // If `selector` is null the selection algorithm is still applied (interpreted
Henrik Boström5b3541f2018-03-19 13:52:56 +010074 // as: no RTP streams are sent by selector). The result is empty.
75 void GetStatsReport(rtc::scoped_refptr<RtpSenderInternal> selector,
76 rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
Artem Titov880fa812021-07-30 22:30:23 +020077 // If `selector` is null the selection algorithm is still applied (interpreted
Henrik Boström5b3541f2018-03-19 13:52:56 +010078 // as: no RTP streams are received by selector). The result is empty.
79 void GetStatsReport(rtc::scoped_refptr<RtpReceiverInternal> selector,
80 rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
hbosd565b732016-08-30 14:04:35 -070081 // Clears the cache's reference to the most recent stats report. Subsequently
Artem Titov880fa812021-07-30 22:30:23 +020082 // calling `GetStatsReport` guarantees fresh stats.
hbosd565b732016-08-30 14:04:35 -070083 void ClearCachedStatsReport();
84
Artem Titov880fa812021-07-30 22:30:23 +020085 // If there is a `GetStatsReport` requests in-flight, waits until it has been
hbosb78306a2016-12-19 05:06:57 -080086 // completed. Must be called on the signaling thread.
87 void WaitForPendingRequest();
88
hbosc82f2e12016-09-05 01:36:50 -070089 protected:
Steve Anton2d8609c2018-01-23 16:38:46 -080090 RTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime_us);
hbosb78306a2016-12-19 05:06:57 -080091 ~RTCStatsCollector();
hbosd565b732016-08-30 14:04:35 -070092
Henrik Boström40b030e2019-02-28 09:49:31 +010093 struct CertificateStatsPair {
94 std::unique_ptr<rtc::SSLCertificateStats> local;
95 std::unique_ptr<rtc::SSLCertificateStats> remote;
96 };
hbosc82f2e12016-09-05 01:36:50 -070097
Henrik Boström40b030e2019-02-28 09:49:31 +010098 // Stats gathering on a particular thread. Virtual for the sake of testing.
99 virtual void ProducePartialResultsOnSignalingThreadImpl(
100 int64_t timestamp_us,
101 RTCStatsReport* partial_report);
102 virtual void ProducePartialResultsOnNetworkThreadImpl(
103 int64_t timestamp_us,
104 const std::map<std::string, cricket::TransportStats>&
105 transport_stats_by_name,
106 const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
107 RTCStatsReport* partial_report);
hbosc82f2e12016-09-05 01:36:50 -0700108
109 private:
Henrik Boström5b3541f2018-03-19 13:52:56 +0100110 class RequestInfo {
111 public:
112 enum class FilterMode { kAll, kSenderSelector, kReceiverSelector };
113
114 // Constructs with FilterMode::kAll.
115 explicit RequestInfo(
116 rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
117 // Constructs with FilterMode::kSenderSelector. The selection algorithm is
Artem Titov880fa812021-07-30 22:30:23 +0200118 // applied even if `selector` is null, resulting in an empty report.
Henrik Boström5b3541f2018-03-19 13:52:56 +0100119 RequestInfo(rtc::scoped_refptr<RtpSenderInternal> selector,
120 rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
121 // Constructs with FilterMode::kReceiverSelector. The selection algorithm is
Artem Titov880fa812021-07-30 22:30:23 +0200122 // applied even if `selector` is null, resulting in an empty report.
Henrik Boström5b3541f2018-03-19 13:52:56 +0100123 RequestInfo(rtc::scoped_refptr<RtpReceiverInternal> selector,
124 rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
125
126 FilterMode filter_mode() const { return filter_mode_; }
127 rtc::scoped_refptr<RTCStatsCollectorCallback> callback() const {
128 return callback_;
129 }
130 rtc::scoped_refptr<RtpSenderInternal> sender_selector() const {
131 RTC_DCHECK(filter_mode_ == FilterMode::kSenderSelector);
132 return sender_selector_;
133 }
134 rtc::scoped_refptr<RtpReceiverInternal> receiver_selector() const {
135 RTC_DCHECK(filter_mode_ == FilterMode::kReceiverSelector);
136 return receiver_selector_;
137 }
138
139 private:
140 RequestInfo(FilterMode filter_mode,
141 rtc::scoped_refptr<RTCStatsCollectorCallback> callback,
142 rtc::scoped_refptr<RtpSenderInternal> sender_selector,
143 rtc::scoped_refptr<RtpReceiverInternal> receiver_selector);
144
145 FilterMode filter_mode_;
146 rtc::scoped_refptr<RTCStatsCollectorCallback> callback_;
147 rtc::scoped_refptr<RtpSenderInternal> sender_selector_;
148 rtc::scoped_refptr<RtpReceiverInternal> receiver_selector_;
149 };
150
151 void GetStatsReportInternal(RequestInfo request);
152
Steve Anton57858b32018-02-15 15:19:50 -0800153 // Structure for tracking stats about each RtpTransceiver managed by the
154 // PeerConnection. This can either by a Plan B style or Unified Plan style
155 // transceiver (i.e., can have 0 or many senders and receivers).
156 // Some fields are copied from the RtpTransceiver/BaseChannel object so that
157 // they can be accessed safely on threads other than the signaling thread.
158 // If a BaseChannel is not available (e.g., if signaling has not started),
Artem Titov880fa812021-07-30 22:30:23 +0200159 // then `mid` and `transport_name` will be null.
Steve Anton57858b32018-02-15 15:19:50 -0800160 struct RtpTransceiverStatsInfo {
161 rtc::scoped_refptr<RtpTransceiver> transceiver;
162 cricket::MediaType media_type;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200163 absl::optional<std::string> mid;
164 absl::optional<std::string> transport_name;
Steve Anton57858b32018-02-15 15:19:50 -0800165 std::unique_ptr<TrackMediaInfoMap> track_media_info_map;
166 };
167
Taylor Brandstetter25e022f2018-03-08 09:53:47 -0800168 void DeliverCachedReport(
169 rtc::scoped_refptr<const RTCStatsReport> cached_report,
Henrik Boström5b3541f2018-03-19 13:52:56 +0100170 std::vector<RequestInfo> requests);
hbosc82f2e12016-09-05 01:36:50 -0700171
Artem Titov880fa812021-07-30 22:30:23 +0200172 // Produces `RTCCertificateStats`.
hbosdf6075a2016-12-19 04:58:02 -0800173 void ProduceCertificateStats_n(
hbos2fa7c672016-10-24 04:00:05 -0700174 int64_t timestamp_us,
175 const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
hbos6ab97ce2016-10-03 14:16:56 -0700176 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200177 // Produces `RTCCodecStats`.
hbosdf6075a2016-12-19 04:58:02 -0800178 void ProduceCodecStats_n(
Steve Anton57858b32018-02-15 15:19:50 -0800179 int64_t timestamp_us,
180 const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
hbos0adb8282016-11-23 02:32:06 -0800181 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200182 // Produces `RTCDataChannelStats`.
Yves Gerey665174f2018-06-19 15:03:05 +0200183 void ProduceDataChannelStats_s(int64_t timestamp_us,
184 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200185 // Produces `RTCIceCandidatePairStats` and `RTCIceCandidateStats`.
hbosdf6075a2016-12-19 04:58:02 -0800186 void ProduceIceCandidateAndPairStats_n(
stefanf79ade12017-06-02 06:44:03 -0700187 int64_t timestamp_us,
Steve Anton5dfde182018-02-06 10:34:40 -0800188 const std::map<std::string, cricket::TransportStats>&
189 transport_stats_by_name,
stefanf79ade12017-06-02 06:44:03 -0700190 const Call::Stats& call_stats,
hbosab9f6e42016-10-07 02:18:47 -0700191 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200192 // Produces `RTCMediaStreamStats`.
Steve Anton57858b32018-02-15 15:19:50 -0800193 void ProduceMediaStreamStats_s(int64_t timestamp_us,
194 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200195 // Produces `RTCMediaStreamTrackStats`.
Steve Anton57858b32018-02-15 15:19:50 -0800196 void ProduceMediaStreamTrackStats_s(int64_t timestamp_us,
197 RTCStatsReport* report) const;
Henrik Boström646fda02019-05-22 15:49:42 +0200198 // Produces RTCMediaSourceStats, including RTCAudioSourceStats and
199 // RTCVideoSourceStats.
200 void ProduceMediaSourceStats_s(int64_t timestamp_us,
201 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200202 // Produces `RTCPeerConnectionStats`.
Yves Gerey665174f2018-06-19 15:03:05 +0200203 void ProducePeerConnectionStats_s(int64_t timestamp_us,
204 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200205 // Produces `RTCInboundRTPStreamStats` and `RTCOutboundRTPStreamStats`.
Henrik Boström883eefc2019-05-27 13:40:25 +0200206 // This has to be invoked after codecs and transport stats have been created
207 // because some metrics are calculated through lookup of other metrics.
Steve Anton5dfde182018-02-06 10:34:40 -0800208 void ProduceRTPStreamStats_n(
209 int64_t timestamp_us,
Steve Anton57858b32018-02-15 15:19:50 -0800210 const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
Steve Anton5dfde182018-02-06 10:34:40 -0800211 RTCStatsReport* report) const;
Steve Anton57858b32018-02-15 15:19:50 -0800212 void ProduceAudioRTPStreamStats_n(int64_t timestamp_us,
213 const RtpTransceiverStatsInfo& stats,
214 RTCStatsReport* report) const;
215 void ProduceVideoRTPStreamStats_n(int64_t timestamp_us,
216 const RtpTransceiverStatsInfo& stats,
217 RTCStatsReport* report) const;
Artem Titov880fa812021-07-30 22:30:23 +0200218 // Produces `RTCTransportStats`.
hbosdf6075a2016-12-19 04:58:02 -0800219 void ProduceTransportStats_n(
Steve Anton5dfde182018-02-06 10:34:40 -0800220 int64_t timestamp_us,
221 const std::map<std::string, cricket::TransportStats>&
222 transport_stats_by_name,
hbos2fa7c672016-10-24 04:00:05 -0700223 const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
224 RTCStatsReport* report) const;
225
226 // Helper function to stats-producing functions.
227 std::map<std::string, CertificateStatsPair>
Steve Anton5dfde182018-02-06 10:34:40 -0800228 PrepareTransportCertificateStats_n(
229 const std::map<std::string, cricket::TransportStats>&
230 transport_stats_by_name) const;
Artem Titov880fa812021-07-30 22:30:23 +0200231 // The results are stored in `transceiver_stats_infos_` and `call_stats_`.
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200232 void PrepareTransceiverStatsInfosAndCallStats_s_w_n();
hbosd565b732016-08-30 14:04:35 -0700233
Henrik Boström40b030e2019-02-28 09:49:31 +0100234 // Stats gathering on a particular thread.
235 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us);
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200236 void ProducePartialResultsOnNetworkThread(
237 int64_t timestamp_us,
238 absl::optional<std::string> sctp_transport_name);
Artem Titov880fa812021-07-30 22:30:23 +0200239 // Merges `network_report_` into `partial_report_` and completes the request.
240 // This is a NO-OP if `network_report_` is null.
Henrik Boström40b030e2019-02-28 09:49:31 +0100241 void MergeNetworkReport_s();
242
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000243 // Slots for signals (sigslot) that are wired up to `pc_`.
244 void OnSctpDataChannelCreated(SctpDataChannel* channel);
Artem Titov880fa812021-07-30 22:30:23 +0200245 // Slots for signals (sigslot) that are wired up to `channel`.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700246 void OnDataChannelOpened(DataChannelInterface* channel);
247 void OnDataChannelClosed(DataChannelInterface* channel);
hbos82ebe022016-11-14 01:41:09 -0800248
Steve Anton2d8609c2018-01-23 16:38:46 -0800249 PeerConnectionInternal* const pc_;
hbosc82f2e12016-09-05 01:36:50 -0700250 rtc::Thread* const signaling_thread_;
251 rtc::Thread* const worker_thread_;
252 rtc::Thread* const network_thread_;
hbosc82f2e12016-09-05 01:36:50 -0700253
254 int num_pending_partial_reports_;
255 int64_t partial_report_timestamp_us_;
Henrik Boström40b030e2019-02-28 09:49:31 +0100256 // Reports that are produced on the signaling thread or the network thread are
257 // merged into this report. It is only touched on the signaling thread. Once
258 // all partial reports are merged this is the result of a request.
hbosc82f2e12016-09-05 01:36:50 -0700259 rtc::scoped_refptr<RTCStatsReport> partial_report_;
Henrik Boström5b3541f2018-03-19 13:52:56 +0100260 std::vector<RequestInfo> requests_;
Henrik Boström40b030e2019-02-28 09:49:31 +0100261 // Holds the result of ProducePartialResultsOnNetworkThread(). It is merged
Artem Titov880fa812021-07-30 22:30:23 +0200262 // into `partial_report_` on the signaling thread and then nulled by
Henrik Boström40b030e2019-02-28 09:49:31 +0100263 // MergeNetworkReport_s(). Thread-safety is ensured by using
Artem Titov880fa812021-07-30 22:30:23 +0200264 // `network_report_event_`.
Henrik Boström40b030e2019-02-28 09:49:31 +0100265 rtc::scoped_refptr<RTCStatsReport> network_report_;
Artem Titov880fa812021-07-30 22:30:23 +0200266 // If set, it is safe to touch the `network_report_` on the signaling thread.
Henrik Boström40b030e2019-02-28 09:49:31 +0100267 // This is reset before async-invoking ProducePartialResultsOnNetworkThread()
268 // and set when ProducePartialResultsOnNetworkThread() is complete, after it
Artem Titov880fa812021-07-30 22:30:23 +0200269 // has updated the value of `network_report_`.
Henrik Boström40b030e2019-02-28 09:49:31 +0100270 rtc::Event network_report_event_;
hbosc82f2e12016-09-05 01:36:50 -0700271
Tomas Gunnarssonbfd9ba82021-04-18 11:55:57 +0200272 // Cleared and set in `PrepareTransceiverStatsInfosAndCallStats_s_w_n`,
273 // starting out on the signaling thread, then network. Later read on the
274 // network and signaling threads as part of collecting stats and finally
275 // reset when the work is done. Initially this variable was added and not
276 // passed around as an arguments to avoid copies. This is thread safe due to
277 // how operations are sequenced and we don't start the stats collection
278 // sequence if one is in progress. As a future improvement though, we could
279 // now get rid of the variable and keep the data scoped within a stats
280 // collection sequence.
Steve Anton57858b32018-02-15 15:19:50 -0800281 std::vector<RtpTransceiverStatsInfo> transceiver_stats_infos_;
Steve Anton5dfde182018-02-06 10:34:40 -0800282
stefanf79ade12017-06-02 06:44:03 -0700283 Call::Stats call_stats_;
hbosdf6075a2016-12-19 04:58:02 -0800284
hbos0e6758d2016-08-31 07:57:36 -0700285 // A timestamp, in microseconds, that is based on a timer that is
286 // monotonically increasing. That is, even if the system clock is modified the
287 // difference between the timer and this timestamp is how fresh the cached
288 // report is.
289 int64_t cache_timestamp_us_;
290 int64_t cache_lifetime_us_;
hbosd565b732016-08-30 14:04:35 -0700291 rtc::scoped_refptr<const RTCStatsReport> cached_report_;
hbos82ebe022016-11-14 01:41:09 -0800292
293 // Data recorded and maintained by the stats collector during its lifetime.
294 // Some stats are produced from this record instead of other components.
295 struct InternalRecord {
Yves Gerey665174f2018-06-19 15:03:05 +0200296 InternalRecord() : data_channels_opened(0), data_channels_closed(0) {}
hbos82ebe022016-11-14 01:41:09 -0800297
298 // The opened count goes up when a channel is fully opened and the closed
299 // count goes up if a previously opened channel has fully closed. The opened
300 // count does not go down when a channel closes, meaning (opened - closed)
301 // is the number of channels currently opened. A channel that is closed
302 // before reaching the open state does not affect these counters.
303 uint32_t data_channels_opened;
304 uint32_t data_channels_closed;
305 // Identifies by address channels that have been opened, which remain in the
306 // set until they have been fully closed.
307 std::set<uintptr_t> opened_data_channels;
308 };
309 InternalRecord internal_record_;
hbosd565b732016-08-30 14:04:35 -0700310};
311
hboscc555c52016-10-18 12:48:31 -0700312const char* CandidateTypeToRTCIceCandidateTypeForTesting(
313 const std::string& type);
314const char* DataStateToRTCDataChannelStateForTesting(
315 DataChannelInterface::DataState state);
hbosab9f6e42016-10-07 02:18:47 -0700316
hbosd565b732016-08-30 14:04:35 -0700317} // namespace webrtc
318
Steve Anton10542f22019-01-11 09:11:00 -0800319#endif // PC_RTC_STATS_COLLECTOR_H_