• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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