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 #ifndef PC_RTC_STATS_COLLECTOR_H_ 12 #define PC_RTC_STATS_COLLECTOR_H_ 13 14 #include <stdint.h> 15 16 #include <cstdint> 17 #include <map> 18 #include <memory> 19 #include <set> 20 #include <string> 21 #include <vector> 22 23 #include "absl/types/optional.h" 24 #include "api/data_channel_interface.h" 25 #include "api/media_types.h" 26 #include "api/scoped_refptr.h" 27 #include "api/stats/rtc_stats_collector_callback.h" 28 #include "api/stats/rtc_stats_report.h" 29 #include "api/stats/rtcstats_objects.h" 30 #include "call/call.h" 31 #include "media/base/media_channel.h" 32 #include "pc/data_channel_utils.h" 33 #include "pc/peer_connection_internal.h" 34 #include "pc/rtp_receiver.h" 35 #include "pc/rtp_sender.h" 36 #include "pc/rtp_transceiver.h" 37 #include "pc/sctp_data_channel.h" 38 #include "pc/track_media_info_map.h" 39 #include "pc/transport_stats.h" 40 #include "rtc_base/checks.h" 41 #include "rtc_base/event.h" 42 #include "rtc_base/ref_count.h" 43 #include "rtc_base/ssl_certificate.h" 44 #include "rtc_base/ssl_identity.h" 45 #include "rtc_base/synchronization/mutex.h" 46 #include "rtc_base/third_party/sigslot/sigslot.h" 47 #include "rtc_base/thread.h" 48 #include "rtc_base/time_utils.h" 49 50 namespace webrtc { 51 52 class RtpSenderInternal; 53 class RtpReceiverInternal; 54 55 // All public methods of the collector are to be called on the signaling thread. 56 // Stats are gathered on the signaling, worker and network threads 57 // asynchronously. The callback is invoked on the signaling thread. Resulting 58 // reports are cached for `cache_lifetime_` ms. 59 class RTCStatsCollector : public rtc::RefCountInterface, 60 public sigslot::has_slots<> { 61 public: 62 static rtc::scoped_refptr<RTCStatsCollector> Create( 63 PeerConnectionInternal* pc, 64 int64_t cache_lifetime_us = 50 * rtc::kNumMicrosecsPerMillisec); 65 66 // Gets a recent stats report. If there is a report cached that is still fresh 67 // it is returned, otherwise new stats are gathered and returned. A report is 68 // considered fresh for `cache_lifetime_` ms. const RTCStatsReports are safe 69 // to use across multiple threads and may be destructed on any thread. 70 // If the optional selector argument is used, stats are filtered according to 71 // stats selection algorithm before delivery. 72 // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm 73 void GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback> callback); 74 // If `selector` is null the selection algorithm is still applied (interpreted 75 // as: no RTP streams are sent by selector). The result is empty. 76 void GetStatsReport(rtc::scoped_refptr<RtpSenderInternal> selector, 77 rtc::scoped_refptr<RTCStatsCollectorCallback> callback); 78 // If `selector` is null the selection algorithm is still applied (interpreted 79 // as: no RTP streams are received by selector). The result is empty. 80 void GetStatsReport(rtc::scoped_refptr<RtpReceiverInternal> selector, 81 rtc::scoped_refptr<RTCStatsCollectorCallback> callback); 82 // Clears the cache's reference to the most recent stats report. Subsequently 83 // calling `GetStatsReport` guarantees fresh stats. This method must be called 84 // any time the PeerConnection visibly changes as a result of an API call as 85 // per 86 // https://w3c.github.io/webrtc-stats/#guidelines-for-getstats-results-caching-throttling 87 // and it must be called any time negotiation happens. 88 void ClearCachedStatsReport(); 89 90 // If there is a `GetStatsReport` requests in-flight, waits until it has been 91 // completed. Must be called on the signaling thread. 92 void WaitForPendingRequest(); 93 94 protected: 95 RTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime_us); 96 ~RTCStatsCollector(); 97 98 struct CertificateStatsPair { 99 std::unique_ptr<rtc::SSLCertificateStats> local; 100 std::unique_ptr<rtc::SSLCertificateStats> remote; 101 102 CertificateStatsPair Copy() const; 103 }; 104 105 // Stats gathering on a particular thread. Virtual for the sake of testing. 106 virtual void ProducePartialResultsOnSignalingThreadImpl( 107 int64_t timestamp_us, 108 RTCStatsReport* partial_report); 109 virtual void ProducePartialResultsOnNetworkThreadImpl( 110 int64_t timestamp_us, 111 const std::map<std::string, cricket::TransportStats>& 112 transport_stats_by_name, 113 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, 114 RTCStatsReport* partial_report); 115 116 private: 117 class RequestInfo { 118 public: 119 enum class FilterMode { kAll, kSenderSelector, kReceiverSelector }; 120 121 // Constructs with FilterMode::kAll. 122 explicit RequestInfo( 123 rtc::scoped_refptr<RTCStatsCollectorCallback> callback); 124 // Constructs with FilterMode::kSenderSelector. The selection algorithm is 125 // applied even if `selector` is null, resulting in an empty report. 126 RequestInfo(rtc::scoped_refptr<RtpSenderInternal> selector, 127 rtc::scoped_refptr<RTCStatsCollectorCallback> callback); 128 // Constructs with FilterMode::kReceiverSelector. The selection algorithm is 129 // applied even if `selector` is null, resulting in an empty report. 130 RequestInfo(rtc::scoped_refptr<RtpReceiverInternal> selector, 131 rtc::scoped_refptr<RTCStatsCollectorCallback> callback); 132 filter_mode()133 FilterMode filter_mode() const { return filter_mode_; } callback()134 rtc::scoped_refptr<RTCStatsCollectorCallback> callback() const { 135 return callback_; 136 } sender_selector()137 rtc::scoped_refptr<RtpSenderInternal> sender_selector() const { 138 RTC_DCHECK(filter_mode_ == FilterMode::kSenderSelector); 139 return sender_selector_; 140 } receiver_selector()141 rtc::scoped_refptr<RtpReceiverInternal> receiver_selector() const { 142 RTC_DCHECK(filter_mode_ == FilterMode::kReceiverSelector); 143 return receiver_selector_; 144 } 145 146 private: 147 RequestInfo(FilterMode filter_mode, 148 rtc::scoped_refptr<RTCStatsCollectorCallback> callback, 149 rtc::scoped_refptr<RtpSenderInternal> sender_selector, 150 rtc::scoped_refptr<RtpReceiverInternal> receiver_selector); 151 152 FilterMode filter_mode_; 153 rtc::scoped_refptr<RTCStatsCollectorCallback> callback_; 154 rtc::scoped_refptr<RtpSenderInternal> sender_selector_; 155 rtc::scoped_refptr<RtpReceiverInternal> receiver_selector_; 156 }; 157 158 void GetStatsReportInternal(RequestInfo request); 159 160 // Structure for tracking stats about each RtpTransceiver managed by the 161 // PeerConnection. This can either by a Plan B style or Unified Plan style 162 // transceiver (i.e., can have 0 or many senders and receivers). 163 // Some fields are copied from the RtpTransceiver/BaseChannel object so that 164 // they can be accessed safely on threads other than the signaling thread. 165 // If a BaseChannel is not available (e.g., if signaling has not started), 166 // then `mid` and `transport_name` will be null. 167 struct RtpTransceiverStatsInfo { 168 rtc::scoped_refptr<RtpTransceiver> transceiver; 169 cricket::MediaType media_type; 170 absl::optional<std::string> mid; 171 absl::optional<std::string> transport_name; 172 TrackMediaInfoMap track_media_info_map; 173 }; 174 175 void DeliverCachedReport( 176 rtc::scoped_refptr<const RTCStatsReport> cached_report, 177 std::vector<RequestInfo> requests); 178 179 // Produces `RTCCertificateStats`. 180 void ProduceCertificateStats_n( 181 int64_t timestamp_us, 182 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, 183 RTCStatsReport* report) const; 184 // Produces `RTCDataChannelStats`. 185 void ProduceDataChannelStats_s(int64_t timestamp_us, 186 RTCStatsReport* report) const; 187 // Produces `RTCIceCandidatePairStats` and `RTCIceCandidateStats`. 188 void ProduceIceCandidateAndPairStats_n( 189 int64_t timestamp_us, 190 const std::map<std::string, cricket::TransportStats>& 191 transport_stats_by_name, 192 const Call::Stats& call_stats, 193 RTCStatsReport* report) const; 194 // Produces `RTCMediaStreamStats`. 195 void ProduceMediaStreamStats_s(int64_t timestamp_us, 196 RTCStatsReport* report) const; 197 // Produces `RTCMediaStreamTrackStats`. 198 void ProduceMediaStreamTrackStats_s(int64_t timestamp_us, 199 RTCStatsReport* report) const; 200 // Produces RTCMediaSourceStats, including RTCAudioSourceStats and 201 // RTCVideoSourceStats. 202 void ProduceMediaSourceStats_s(int64_t timestamp_us, 203 RTCStatsReport* report) const; 204 // Produces `RTCPeerConnectionStats`. 205 void ProducePeerConnectionStats_s(int64_t timestamp_us, 206 RTCStatsReport* report) const; 207 // Produces `RTCInboundRTPStreamStats`, `RTCOutboundRTPStreamStats`, 208 // `RTCRemoteInboundRtpStreamStats`, `RTCRemoteOutboundRtpStreamStats` and any 209 // referenced `RTCCodecStats`. This has to be invoked after transport stats 210 // have been created because some metrics are calculated through lookup of 211 // other metrics. 212 void ProduceRTPStreamStats_n( 213 int64_t timestamp_us, 214 const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos, 215 RTCStatsReport* report) const; 216 void ProduceAudioRTPStreamStats_n(int64_t timestamp_us, 217 const RtpTransceiverStatsInfo& stats, 218 RTCStatsReport* report) const; 219 void ProduceVideoRTPStreamStats_n(int64_t timestamp_us, 220 const RtpTransceiverStatsInfo& stats, 221 RTCStatsReport* report) const; 222 // Produces `RTCTransportStats`. 223 void ProduceTransportStats_n( 224 int64_t timestamp_us, 225 const std::map<std::string, cricket::TransportStats>& 226 transport_stats_by_name, 227 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, 228 RTCStatsReport* report) const; 229 230 // Helper function to stats-producing functions. 231 std::map<std::string, CertificateStatsPair> 232 PrepareTransportCertificateStats_n( 233 const std::map<std::string, cricket::TransportStats>& 234 transport_stats_by_name); 235 // The results are stored in `transceiver_stats_infos_` and `call_stats_`. 236 void PrepareTransceiverStatsInfosAndCallStats_s_w_n(); 237 238 // Stats gathering on a particular thread. 239 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us); 240 void ProducePartialResultsOnNetworkThread( 241 int64_t timestamp_us, 242 absl::optional<std::string> sctp_transport_name); 243 // Merges `network_report_` into `partial_report_` and completes the request. 244 // This is a NO-OP if `network_report_` is null. 245 void MergeNetworkReport_s(); 246 247 // Slots for signals (sigslot) that are wired up to `pc_`. 248 void OnSctpDataChannelCreated(SctpDataChannel* channel); 249 // Slots for signals (sigslot) that are wired up to `channel`. 250 void OnDataChannelOpened(DataChannelInterface* channel); 251 void OnDataChannelClosed(DataChannelInterface* channel); 252 253 PeerConnectionInternal* const pc_; 254 rtc::Thread* const signaling_thread_; 255 rtc::Thread* const worker_thread_; 256 rtc::Thread* const network_thread_; 257 258 int num_pending_partial_reports_; 259 int64_t partial_report_timestamp_us_; 260 // Reports that are produced on the signaling thread or the network thread are 261 // merged into this report. It is only touched on the signaling thread. Once 262 // all partial reports are merged this is the result of a request. 263 rtc::scoped_refptr<RTCStatsReport> partial_report_; 264 std::vector<RequestInfo> requests_; 265 // Holds the result of ProducePartialResultsOnNetworkThread(). It is merged 266 // into `partial_report_` on the signaling thread and then nulled by 267 // MergeNetworkReport_s(). Thread-safety is ensured by using 268 // `network_report_event_`. 269 rtc::scoped_refptr<RTCStatsReport> network_report_; 270 // If set, it is safe to touch the `network_report_` on the signaling thread. 271 // This is reset before async-invoking ProducePartialResultsOnNetworkThread() 272 // and set when ProducePartialResultsOnNetworkThread() is complete, after it 273 // has updated the value of `network_report_`. 274 rtc::Event network_report_event_; 275 276 // Cleared and set in `PrepareTransceiverStatsInfosAndCallStats_s_w_n`, 277 // starting out on the signaling thread, then network. Later read on the 278 // network and signaling threads as part of collecting stats and finally 279 // reset when the work is done. Initially this variable was added and not 280 // passed around as an arguments to avoid copies. This is thread safe due to 281 // how operations are sequenced and we don't start the stats collection 282 // sequence if one is in progress. As a future improvement though, we could 283 // now get rid of the variable and keep the data scoped within a stats 284 // collection sequence. 285 std::vector<RtpTransceiverStatsInfo> transceiver_stats_infos_; 286 // This cache avoids having to call rtc::SSLCertChain::GetStats(), which can 287 // relatively expensive. ClearCachedStatsReport() needs to be called on 288 // negotiation to ensure the cache is not obsolete. 289 Mutex cached_certificates_mutex_; 290 std::map<std::string, CertificateStatsPair> cached_certificates_by_transport_ 291 RTC_GUARDED_BY(cached_certificates_mutex_); 292 293 Call::Stats call_stats_; 294 295 // A timestamp, in microseconds, that is based on a timer that is 296 // monotonically increasing. That is, even if the system clock is modified the 297 // difference between the timer and this timestamp is how fresh the cached 298 // report is. 299 int64_t cache_timestamp_us_; 300 int64_t cache_lifetime_us_; 301 rtc::scoped_refptr<const RTCStatsReport> cached_report_; 302 303 // Data recorded and maintained by the stats collector during its lifetime. 304 // Some stats are produced from this record instead of other components. 305 struct InternalRecord { InternalRecordInternalRecord306 InternalRecord() : data_channels_opened(0), data_channels_closed(0) {} 307 308 // The opened count goes up when a channel is fully opened and the closed 309 // count goes up if a previously opened channel has fully closed. The opened 310 // count does not go down when a channel closes, meaning (opened - closed) 311 // is the number of channels currently opened. A channel that is closed 312 // before reaching the open state does not affect these counters. 313 uint32_t data_channels_opened; 314 uint32_t data_channels_closed; 315 // Identifies by address channels that have been opened, which remain in the 316 // set until they have been fully closed. 317 std::set<uintptr_t> opened_data_channels; 318 }; 319 InternalRecord internal_record_; 320 }; 321 322 const char* CandidateTypeToRTCIceCandidateTypeForTesting( 323 const std::string& type); 324 const char* DataStateToRTCDataChannelStateForTesting( 325 DataChannelInterface::DataState state); 326 327 } // namespace webrtc 328 329 #endif // PC_RTC_STATS_COLLECTOR_H_ 330