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