mirror of
https://github.com/netbirdio/ice.git
synced 2026-05-22 17:10:58 -07:00
Add ability to get selected candidate pair stats (#735)
It is useful to have stats from just the selected pair as a lightweight option where a lot of agents are running, for example, an SFU. lint Switch udp_mux_test to use sha256 instead of sha1 (#733) Minor change to this test to stop using sha1 and remove the linter exceptions. Co-authored-by: Daniel Kessler <dkess@google.com> Update module golang.org/x/net to v0.29.0 Generated by renovateBot Update module github.com/pion/dtls/v3 to v3.0.3 Generated by renovateBot
This commit is contained in:
@@ -54,6 +54,56 @@ func (a *Agent) GetCandidatePairsStats() []CandidatePairStats {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSelectedCandidatePairStats returns a candidate pair stats for selected candidate pair.
|
||||
// Returns false if there is no selected pair
|
||||
func (a *Agent) GetSelectedCandidatePairStats() (CandidatePairStats, bool) {
|
||||
isAvailable := false
|
||||
var res CandidatePairStats
|
||||
err := a.loop.Run(a.loop, func(_ context.Context) {
|
||||
sp := a.getSelectedPair()
|
||||
if sp == nil {
|
||||
return
|
||||
}
|
||||
|
||||
isAvailable = true
|
||||
res = CandidatePairStats{
|
||||
Timestamp: time.Now(),
|
||||
LocalCandidateID: sp.Local.ID(),
|
||||
RemoteCandidateID: sp.Remote.ID(),
|
||||
State: sp.state,
|
||||
Nominated: sp.nominated,
|
||||
// PacketsSent uint32
|
||||
// PacketsReceived uint32
|
||||
// BytesSent uint64
|
||||
// BytesReceived uint64
|
||||
// LastPacketSentTimestamp time.Time
|
||||
// LastPacketReceivedTimestamp time.Time
|
||||
// FirstRequestTimestamp time.Time
|
||||
// LastRequestTimestamp time.Time
|
||||
// LastResponseTimestamp time.Time
|
||||
TotalRoundTripTime: sp.TotalRoundTripTime(),
|
||||
CurrentRoundTripTime: sp.CurrentRoundTripTime(),
|
||||
// AvailableOutgoingBitrate float64
|
||||
// AvailableIncomingBitrate float64
|
||||
// CircuitBreakerTriggerCount uint32
|
||||
// RequestsReceived uint64
|
||||
// RequestsSent uint64
|
||||
ResponsesReceived: sp.ResponsesReceived(),
|
||||
// ResponsesSent uint64
|
||||
// RetransmissionsReceived uint64
|
||||
// RetransmissionsSent uint64
|
||||
// ConsentRequestsSent uint64
|
||||
// ConsentExpiredTimestamp time.Time
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("Failed to get selected candidate pair stats: %v", err)
|
||||
return CandidatePairStats{}, false
|
||||
}
|
||||
|
||||
return res, isAvailable
|
||||
}
|
||||
|
||||
// GetLocalCandidatesStats returns a list of local candidates stats
|
||||
func (a *Agent) GetLocalCandidatesStats() []CandidateStats {
|
||||
var res []CandidateStats
|
||||
|
||||
+84
-1
@@ -635,7 +635,7 @@ func TestInvalidGather(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestCandidatePairStats(t *testing.T) {
|
||||
func TestCandidatePairsStats(t *testing.T) {
|
||||
defer test.CheckRoutines(t)()
|
||||
|
||||
// Avoid deadlocks?
|
||||
@@ -789,6 +789,89 @@ func TestCandidatePairStats(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectedCandidatePairStats(t *testing.T) {
|
||||
defer test.CheckRoutines(t)()
|
||||
|
||||
// Avoid deadlocks?
|
||||
defer test.TimeOut(1 * time.Second).Stop()
|
||||
|
||||
a, err := NewAgent(&AgentConfig{})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create agent: %s", err)
|
||||
}
|
||||
defer func() {
|
||||
require.NoError(t, a.Close())
|
||||
}()
|
||||
|
||||
hostConfig := &CandidateHostConfig{
|
||||
Network: "udp",
|
||||
Address: "192.168.1.1",
|
||||
Port: 19216,
|
||||
Component: 1,
|
||||
}
|
||||
hostLocal, err := NewCandidateHost(hostConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct local host candidate: %s", err)
|
||||
}
|
||||
|
||||
srflxConfig := &CandidateServerReflexiveConfig{
|
||||
Network: "udp",
|
||||
Address: "10.10.10.2",
|
||||
Port: 19218,
|
||||
Component: 1,
|
||||
RelAddr: "4.3.2.1",
|
||||
RelPort: 43212,
|
||||
}
|
||||
srflxRemote, err := NewCandidateServerReflexive(srflxConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct remote srflx candidate: %s", err)
|
||||
}
|
||||
|
||||
// no selected pair, should return not available
|
||||
_, ok := a.GetSelectedCandidatePairStats()
|
||||
require.False(t, ok)
|
||||
|
||||
// add pair and populate some RTT stats
|
||||
p := a.findPair(hostLocal, srflxRemote)
|
||||
if p == nil {
|
||||
a.addPair(hostLocal, srflxRemote)
|
||||
p = a.findPair(hostLocal, srflxRemote)
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
p.UpdateRoundTripTime(time.Duration(i+1) * time.Second)
|
||||
}
|
||||
|
||||
// set the pair as selected
|
||||
a.setSelectedPair(p)
|
||||
|
||||
stats, ok := a.GetSelectedCandidatePairStats()
|
||||
require.True(t, ok)
|
||||
|
||||
if stats.LocalCandidateID != hostLocal.ID() {
|
||||
t.Fatal("invalid local candidate id")
|
||||
}
|
||||
if stats.RemoteCandidateID != srflxRemote.ID() {
|
||||
t.Fatal("invalid remote candidate id")
|
||||
}
|
||||
|
||||
expectedCurrentRoundTripTime := time.Duration(10) * time.Second
|
||||
if stats.CurrentRoundTripTime != expectedCurrentRoundTripTime.Seconds() {
|
||||
t.Fatalf("expected current round trip time to be %f, it is %f instead",
|
||||
expectedCurrentRoundTripTime.Seconds(), stats.CurrentRoundTripTime)
|
||||
}
|
||||
|
||||
expectedTotalRoundTripTime := time.Duration(55) * time.Second
|
||||
if stats.TotalRoundTripTime != expectedTotalRoundTripTime.Seconds() {
|
||||
t.Fatalf("expected total round trip time to be %f, it is %f instead",
|
||||
expectedTotalRoundTripTime.Seconds(), stats.TotalRoundTripTime)
|
||||
}
|
||||
|
||||
if stats.ResponsesReceived != 10 {
|
||||
t.Fatalf("expected responses received to be 10, it is %d instead",
|
||||
stats.ResponsesReceived)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLocalCandidateStats(t *testing.T) {
|
||||
defer test.CheckRoutines(t)()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user