302 lines
13 KiB
C
302 lines
13 KiB
C
|
/*
|
||
|
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
#ifndef PC_RTC_STATS_COLLECTOR_H_
|
||
|
#define PC_RTC_STATS_COLLECTOR_H_
|
||
|
|
||
|
#include <map>
|
||
|
#include <memory>
|
||
|
#include <set>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
#include "absl/types/optional.h"
|
||
|
#include "api/scoped_refptr.h"
|
||
|
#include "api/stats/rtc_stats_collector_callback.h"
|
||
|
#include "api/stats/rtc_stats_report.h"
|
||
|
#include "api/stats/rtcstats_objects.h"
|
||
|
#include "call/call.h"
|
||
|
#include "media/base/media_channel.h"
|
||
|
#include "pc/data_channel_utils.h"
|
||
|
#include "pc/peer_connection_internal.h"
|
||
|
#include "pc/track_media_info_map.h"
|
||
|
#include "rtc_base/event.h"
|
||
|
#include "rtc_base/ref_count.h"
|
||
|
#include "rtc_base/ssl_identity.h"
|
||
|
#include "rtc_base/third_party/sigslot/sigslot.h"
|
||
|
#include "rtc_base/time_utils.h"
|
||
|
|
||
|
namespace webrtc {
|
||
|
|
||
|
class RtpSenderInternal;
|
||
|
class RtpReceiverInternal;
|
||
|
|
||
|
// All public methods of the collector are to be called on the signaling thread.
|
||
|
// Stats are gathered on the signaling, worker and network threads
|
||
|
// asynchronously. The callback is invoked on the signaling thread. Resulting
|
||
|
// reports are cached for |cache_lifetime_| ms.
|
||
|
class RTCStatsCollector : public virtual rtc::RefCountInterface,
|
||
|
public sigslot::has_slots<> {
|
||
|
public:
|
||
|
static rtc::scoped_refptr<RTCStatsCollector> Create(
|
||
|
PeerConnectionInternal* pc,
|
||
|
int64_t cache_lifetime_us = 50 * rtc::kNumMicrosecsPerMillisec);
|
||
|
|
||
|
// Gets a recent stats report. If there is a report cached that is still fresh
|
||
|
// it is returned, otherwise new stats are gathered and returned. A report is
|
||
|
// considered fresh for |cache_lifetime_| ms. const RTCStatsReports are safe
|
||
|
// to use across multiple threads and may be destructed on any thread.
|
||
|
// If the optional selector argument is used, stats are filtered according to
|
||
|
// stats selection algorithm before delivery.
|
||
|
// https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm
|
||
|
void GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
|
||
|
// If |selector| is null the selection algorithm is still applied (interpreted
|
||
|
// as: no RTP streams are sent by selector). The result is empty.
|
||
|
void GetStatsReport(rtc::scoped_refptr<RtpSenderInternal> selector,
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
|
||
|
// If |selector| is null the selection algorithm is still applied (interpreted
|
||
|
// as: no RTP streams are received by selector). The result is empty.
|
||
|
void GetStatsReport(rtc::scoped_refptr<RtpReceiverInternal> selector,
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
|
||
|
// Clears the cache's reference to the most recent stats report. Subsequently
|
||
|
// calling |GetStatsReport| guarantees fresh stats.
|
||
|
void ClearCachedStatsReport();
|
||
|
|
||
|
// If there is a |GetStatsReport| requests in-flight, waits until it has been
|
||
|
// completed. Must be called on the signaling thread.
|
||
|
void WaitForPendingRequest();
|
||
|
|
||
|
protected:
|
||
|
RTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime_us);
|
||
|
~RTCStatsCollector();
|
||
|
|
||
|
struct CertificateStatsPair {
|
||
|
std::unique_ptr<rtc::SSLCertificateStats> local;
|
||
|
std::unique_ptr<rtc::SSLCertificateStats> remote;
|
||
|
};
|
||
|
|
||
|
// Stats gathering on a particular thread. Virtual for the sake of testing.
|
||
|
virtual void ProducePartialResultsOnSignalingThreadImpl(
|
||
|
int64_t timestamp_us,
|
||
|
RTCStatsReport* partial_report);
|
||
|
virtual void ProducePartialResultsOnNetworkThreadImpl(
|
||
|
int64_t timestamp_us,
|
||
|
const std::map<std::string, cricket::TransportStats>&
|
||
|
transport_stats_by_name,
|
||
|
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
||
|
RTCStatsReport* partial_report);
|
||
|
|
||
|
private:
|
||
|
class RequestInfo {
|
||
|
public:
|
||
|
enum class FilterMode { kAll, kSenderSelector, kReceiverSelector };
|
||
|
|
||
|
// Constructs with FilterMode::kAll.
|
||
|
explicit RequestInfo(
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
|
||
|
// Constructs with FilterMode::kSenderSelector. The selection algorithm is
|
||
|
// applied even if |selector| is null, resulting in an empty report.
|
||
|
RequestInfo(rtc::scoped_refptr<RtpSenderInternal> selector,
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
|
||
|
// Constructs with FilterMode::kReceiverSelector. The selection algorithm is
|
||
|
// applied even if |selector| is null, resulting in an empty report.
|
||
|
RequestInfo(rtc::scoped_refptr<RtpReceiverInternal> selector,
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback);
|
||
|
|
||
|
FilterMode filter_mode() const { return filter_mode_; }
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback() const {
|
||
|
return callback_;
|
||
|
}
|
||
|
rtc::scoped_refptr<RtpSenderInternal> sender_selector() const {
|
||
|
RTC_DCHECK(filter_mode_ == FilterMode::kSenderSelector);
|
||
|
return sender_selector_;
|
||
|
}
|
||
|
rtc::scoped_refptr<RtpReceiverInternal> receiver_selector() const {
|
||
|
RTC_DCHECK(filter_mode_ == FilterMode::kReceiverSelector);
|
||
|
return receiver_selector_;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
RequestInfo(FilterMode filter_mode,
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback,
|
||
|
rtc::scoped_refptr<RtpSenderInternal> sender_selector,
|
||
|
rtc::scoped_refptr<RtpReceiverInternal> receiver_selector);
|
||
|
|
||
|
FilterMode filter_mode_;
|
||
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback_;
|
||
|
rtc::scoped_refptr<RtpSenderInternal> sender_selector_;
|
||
|
rtc::scoped_refptr<RtpReceiverInternal> receiver_selector_;
|
||
|
};
|
||
|
|
||
|
void GetStatsReportInternal(RequestInfo request);
|
||
|
|
||
|
// Structure for tracking stats about each RtpTransceiver managed by the
|
||
|
// PeerConnection. This can either by a Plan B style or Unified Plan style
|
||
|
// transceiver (i.e., can have 0 or many senders and receivers).
|
||
|
// Some fields are copied from the RtpTransceiver/BaseChannel object so that
|
||
|
// they can be accessed safely on threads other than the signaling thread.
|
||
|
// If a BaseChannel is not available (e.g., if signaling has not started),
|
||
|
// then |mid| and |transport_name| will be null.
|
||
|
struct RtpTransceiverStatsInfo {
|
||
|
rtc::scoped_refptr<RtpTransceiver> transceiver;
|
||
|
cricket::MediaType media_type;
|
||
|
absl::optional<std::string> mid;
|
||
|
absl::optional<std::string> transport_name;
|
||
|
std::unique_ptr<TrackMediaInfoMap> track_media_info_map;
|
||
|
};
|
||
|
|
||
|
void DeliverCachedReport(
|
||
|
rtc::scoped_refptr<const RTCStatsReport> cached_report,
|
||
|
std::vector<RequestInfo> requests);
|
||
|
|
||
|
// Produces |RTCCertificateStats|.
|
||
|
void ProduceCertificateStats_n(
|
||
|
int64_t timestamp_us,
|
||
|
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCCodecStats|.
|
||
|
void ProduceCodecStats_n(
|
||
|
int64_t timestamp_us,
|
||
|
const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCDataChannelStats|.
|
||
|
void ProduceDataChannelStats_s(int64_t timestamp_us,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCIceCandidatePairStats| and |RTCIceCandidateStats|.
|
||
|
void ProduceIceCandidateAndPairStats_n(
|
||
|
int64_t timestamp_us,
|
||
|
const std::map<std::string, cricket::TransportStats>&
|
||
|
transport_stats_by_name,
|
||
|
const Call::Stats& call_stats,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCMediaStreamStats|.
|
||
|
void ProduceMediaStreamStats_s(int64_t timestamp_us,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCMediaStreamTrackStats|.
|
||
|
void ProduceMediaStreamTrackStats_s(int64_t timestamp_us,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces RTCMediaSourceStats, including RTCAudioSourceStats and
|
||
|
// RTCVideoSourceStats.
|
||
|
void ProduceMediaSourceStats_s(int64_t timestamp_us,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCPeerConnectionStats|.
|
||
|
void ProducePeerConnectionStats_s(int64_t timestamp_us,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCInboundRTPStreamStats| and |RTCOutboundRTPStreamStats|.
|
||
|
// This has to be invoked after codecs and transport stats have been created
|
||
|
// because some metrics are calculated through lookup of other metrics.
|
||
|
void ProduceRTPStreamStats_n(
|
||
|
int64_t timestamp_us,
|
||
|
const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
|
||
|
RTCStatsReport* report) const;
|
||
|
void ProduceAudioRTPStreamStats_n(int64_t timestamp_us,
|
||
|
const RtpTransceiverStatsInfo& stats,
|
||
|
RTCStatsReport* report) const;
|
||
|
void ProduceVideoRTPStreamStats_n(int64_t timestamp_us,
|
||
|
const RtpTransceiverStatsInfo& stats,
|
||
|
RTCStatsReport* report) const;
|
||
|
// Produces |RTCTransportStats|.
|
||
|
void ProduceTransportStats_n(
|
||
|
int64_t timestamp_us,
|
||
|
const std::map<std::string, cricket::TransportStats>&
|
||
|
transport_stats_by_name,
|
||
|
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
||
|
RTCStatsReport* report) const;
|
||
|
|
||
|
// Helper function to stats-producing functions.
|
||
|
std::map<std::string, CertificateStatsPair>
|
||
|
PrepareTransportCertificateStats_n(
|
||
|
const std::map<std::string, cricket::TransportStats>&
|
||
|
transport_stats_by_name) const;
|
||
|
std::vector<RtpTransceiverStatsInfo> PrepareTransceiverStatsInfos_s_w() const;
|
||
|
std::set<std::string> PrepareTransportNames_s() const;
|
||
|
|
||
|
// Stats gathering on a particular thread.
|
||
|
void ProducePartialResultsOnSignalingThread(int64_t timestamp_us);
|
||
|
void ProducePartialResultsOnNetworkThread(int64_t timestamp_us);
|
||
|
// Merges |network_report_| into |partial_report_| and completes the request.
|
||
|
// This is a NO-OP if |network_report_| is null.
|
||
|
void MergeNetworkReport_s();
|
||
|
|
||
|
// Slots for signals (sigslot) that are wired up to |pc_|.
|
||
|
void OnRtpDataChannelCreated(RtpDataChannel* channel);
|
||
|
void OnSctpDataChannelCreated(SctpDataChannel* channel);
|
||
|
// Slots for signals (sigslot) that are wired up to |channel|.
|
||
|
void OnDataChannelOpened(DataChannelInterface* channel);
|
||
|
void OnDataChannelClosed(DataChannelInterface* channel);
|
||
|
|
||
|
PeerConnectionInternal* const pc_;
|
||
|
rtc::Thread* const signaling_thread_;
|
||
|
rtc::Thread* const worker_thread_;
|
||
|
rtc::Thread* const network_thread_;
|
||
|
|
||
|
int num_pending_partial_reports_;
|
||
|
int64_t partial_report_timestamp_us_;
|
||
|
// Reports that are produced on the signaling thread or the network thread are
|
||
|
// merged into this report. It is only touched on the signaling thread. Once
|
||
|
// all partial reports are merged this is the result of a request.
|
||
|
rtc::scoped_refptr<RTCStatsReport> partial_report_;
|
||
|
std::vector<RequestInfo> requests_;
|
||
|
// Holds the result of ProducePartialResultsOnNetworkThread(). It is merged
|
||
|
// into |partial_report_| on the signaling thread and then nulled by
|
||
|
// MergeNetworkReport_s(). Thread-safety is ensured by using
|
||
|
// |network_report_event_|.
|
||
|
rtc::scoped_refptr<RTCStatsReport> network_report_;
|
||
|
// If set, it is safe to touch the |network_report_| on the signaling thread.
|
||
|
// This is reset before async-invoking ProducePartialResultsOnNetworkThread()
|
||
|
// and set when ProducePartialResultsOnNetworkThread() is complete, after it
|
||
|
// has updated the value of |network_report_|.
|
||
|
rtc::Event network_report_event_;
|
||
|
|
||
|
// Set in |GetStatsReport|, read in |ProducePartialResultsOnNetworkThread| and
|
||
|
// |ProducePartialResultsOnSignalingThread|, reset after work is complete. Not
|
||
|
// passed as arguments to avoid copies. This is thread safe - when we
|
||
|
// set/reset we know there are no pending stats requests in progress.
|
||
|
std::vector<RtpTransceiverStatsInfo> transceiver_stats_infos_;
|
||
|
std::set<std::string> transport_names_;
|
||
|
|
||
|
Call::Stats call_stats_;
|
||
|
|
||
|
// A timestamp, in microseconds, that is based on a timer that is
|
||
|
// monotonically increasing. That is, even if the system clock is modified the
|
||
|
// difference between the timer and this timestamp is how fresh the cached
|
||
|
// report is.
|
||
|
int64_t cache_timestamp_us_;
|
||
|
int64_t cache_lifetime_us_;
|
||
|
rtc::scoped_refptr<const RTCStatsReport> cached_report_;
|
||
|
|
||
|
// Data recorded and maintained by the stats collector during its lifetime.
|
||
|
// Some stats are produced from this record instead of other components.
|
||
|
struct InternalRecord {
|
||
|
InternalRecord() : data_channels_opened(0), data_channels_closed(0) {}
|
||
|
|
||
|
// The opened count goes up when a channel is fully opened and the closed
|
||
|
// count goes up if a previously opened channel has fully closed. The opened
|
||
|
// count does not go down when a channel closes, meaning (opened - closed)
|
||
|
// is the number of channels currently opened. A channel that is closed
|
||
|
// before reaching the open state does not affect these counters.
|
||
|
uint32_t data_channels_opened;
|
||
|
uint32_t data_channels_closed;
|
||
|
// Identifies by address channels that have been opened, which remain in the
|
||
|
// set until they have been fully closed.
|
||
|
std::set<uintptr_t> opened_data_channels;
|
||
|
};
|
||
|
InternalRecord internal_record_;
|
||
|
};
|
||
|
|
||
|
const char* CandidateTypeToRTCIceCandidateTypeForTesting(
|
||
|
const std::string& type);
|
||
|
const char* DataStateToRTCDataChannelStateForTesting(
|
||
|
DataChannelInterface::DataState state);
|
||
|
|
||
|
} // namespace webrtc
|
||
|
|
||
|
#endif // PC_RTC_STATS_COLLECTOR_H_
|