Connection Statistics
The stats API makes it easy to get information about your ongoing connections and other WebRTC internals. It closely follows the WebRTC Statistics API RFC. Note that the underlying WebRTC statistics API is not supported consistently from browser to browser. For instance Chrome exposes the most full-featured statistics whereas Edge does not implement it at all. In all cases where our statistics API is wrapping that provided by the browser, if the browser does not implement the given API then we simply return a null stats object. This is the expected behaviour and application code should be checking for null stats objects.
What follows is a code snippet showing how to get connection statistics:
connection.GetStats().Then((stats) => { var transport = stats.Streams[0].Transport; if (transport != null) { var localCandidates = transport.LocalCandidates; var remoteCandidates = transport.RemoteCandidates; var activeCandidatePair = transport.ActiveCandidatePair; var activeLocalCandidateId = activeCandidatePair.LocalCandidateId; var activeRemoteCandidateId = activeCandidatePair.RemoteCandidateId; for (var i = 0; i < localCandidates.Length; i++) { var localCandidate = localCandidates[i]; if (localCandidate.Id == activeLocalCandidateId) { // this is the active local candidate // check the protocol - UDP or TCP var localCandidateProtocol = localCandidate.Protocol; if (localCandidate.IsRelayed) { // check the relay server IP var relayServerIPAddress = localCandidate.IPAddress; } } } for (var i = 0; i < remoteCandidates.Length; i++) { var remoteCandidate = remoteCandidates[i]; if (remoteCandidate.Id == activeRemoteCandidateId) { // this is the active remote candidate if (remoteCandidate.IsRelayed) { // check the relay server IP var relayServerIPAddress = remoteCandidate.IPAddress; } } } } });
connection.getStats().then((stats) -> { TransportStats transport = stats.getStreams()[0].getTransport(); CandidateStats[] localCandidates = transport.getLocalCandidates(); CandidateStats[] remoteCandidates = transport.getRemoteCandidates(); CandidatePairStats activeCandidatePair = transport.getActiveCandidatePair(); String activeLocalCandidateId = activeCandidatePair.getLocalCandidateId(); String activeRemoteCandidateId = activeCandidatePair.getRemoteCandidateId(); for (int i = 0; i < localCandidates.length; i++) { CandidateStats localCandidate = localCandidates[i]; if (localCandidate.getId() == activeLocalCandidateId) { // this is the active local candidate if (localCandidate.getIsRelayed()) { // check the relay server IP String relayServerIPAddress = localCandidate.getIPAddress(); } } } for (int i = 0; i < remoteCandidates.length; i++) { CandidateStats remoteCandidate = remoteCandidates[i]; if (remoteCandidate.getId() == activeRemoteCandidateId) { // this is the active remote candidate if (remoteCandidate.getIsRelayed()) { // check the relay server IP String relayServerIPAddress = remoteCandidate.getIPAddress(); } } } });
connection.getStats().then(function(stats) { var transport = stats.getStreams()[0].getTransport(); if (transport) { var localCandidates = transport.getLocalCandidates(); var remoteCandidates = transport.getRemoteCandidates(); var activeCandidatePair = transport.getActiveCandidatePair(); var activeLocalCandidateId = activeCandidatePair.getLocalCandidateId(); var activeRemoteCandidateId = activeCandidatePair.getRemoteCandidateId(); for (var i = 0; i < localCandidates.length; i++) { var localCandidate = localCandidates[i]; if (localCandidate.getId() == activeLocalCandidateId) { // this is the active local candidate // check the protocol - UDP or TCP var localCandidateProtocol = localCandidate.getProtocol(); if (localCandidate.getIsRelayed()) { // check the relay server IP var relayServerIPAddress = localCandidate.getIPAddress(); } } } for (var i = 0; i < remoteCandidates.length; i++) { var remoteCandidate = remoteCandidates[i]; if (remoteCandidate.getId() == activeRemoteCandidateId) { // this is the active remote candidate if (remoteCandidate.getIsRelayed()) { // check the relay server IP var relayServerIPAddress = remoteCandidate.getIPAddress(); } } } } });
connection!.getStats().then(resolveActionBlock: { (stats) in let statistics = stats as! FMIceLinkConnectionStats? let stream = statistics?.streams()[0] as! FMIceLinkStreamStats? let transport = stream?.transport() if (transport != nil) { let localCandidates = transport?.localCandidates() let remoteCandidates = transport?.remoteCandidates() let activeCandidatePair = transport?.activeCandidatePair() let activeLocalCandidateId = activeCandidatePair?.localCandidateId() let activeRemoteCandidateId = activeCandidatePair?.remoteCandidateId() for i in stride(from: 0, to: (localCandidates?.count)!-1, by: 1) { let localCandidate = localCandidates?[i] as! FMIceLinkCandidateStats? if (localCandidate?.id() == activeLocalCandidateId) { // this is the active local candidate // check the protocol let localCandidateProtocol = localCandidate?.protocol() if (localCandidate?.isRelayed())! { // check the relay server IP let relayServerIPAddress = localCandidate?.ipAddress() } } } for i in stride(from: 0, to: (remoteCandidates?.count)!-1, by: 1) { let remoteCandidate = remoteCandidates?[i] as! FMIceLinkCandidateStats? if (remoteCandidate?.id() == activeRemoteCandidateId) { // this is the active remote candidate if (remoteCandidate?.isRelayed())! { // check the relay server IP let relayServerIPAddress = remoteCandidate?.ipAddress() } } } } });
You can call the getStats
function on any active Connection
. For example, one way to do so would be to wire up an event to call getStats
once the Connection
state transitions to Connected
, and the unwire the event when the Connection state transitions to Closed
(or Failed
). Your event could be triggered by some UI element (like a button click), or fired on a Timer, whatever meets your use case.