5
5
"errors"
6
6
"fmt"
7
7
"io"
8
- "math"
9
8
"net/http"
10
9
"net/netip"
11
10
"strings"
@@ -36,48 +35,42 @@ type pingSummary struct {
36
35
Min * time.Duration `table:"min"`
37
36
Avg * time.Duration `table:"avg"`
38
37
Max * time.Duration `table:"max"`
39
- StdDev * time.Duration `table:"stddev"`
38
+ Variance * time.Duration `table:"variance"`
39
+ latencySum float64
40
+ runningAvg float64
41
+ m2 float64
40
42
}
41
43
42
- func buildSummary (wsname string , r []* ipnstate.PingResult ) * pingSummary {
43
- out := pingSummary {
44
- Workspace : wsname ,
44
+ func (s * pingSummary ) addResult (r * ipnstate.PingResult ) {
45
+ s .Total ++
46
+ if r .Err != "" {
47
+ return
45
48
}
46
- totalLatency := 0.0
47
- latencies := make ([]float64 , 0 , len (r ))
48
- for _ , pong := range r {
49
- out .Total ++
50
- if pong .Err == "" {
51
- out .Successful ++
52
- latencies = append (latencies , pong .LatencySeconds )
53
- totalLatency += pong .LatencySeconds
54
- }
49
+ s .Successful ++
50
+ if s .Min == nil || r .LatencySeconds < s .Min .Seconds () {
51
+ s .Min = ptr .Ref (time .Duration (r .LatencySeconds * float64 (time .Second )))
55
52
}
56
- if out .Successful > 0 {
57
- minLatency := latencies [0 ]
58
- maxLatency := latencies [0 ]
59
- varianceSum := 0.0
60
- avgLatency := totalLatency / float64 (out .Successful )
61
- for _ , l := range latencies {
62
- if l < minLatency {
63
- minLatency = l
64
- }
65
- if l > maxLatency {
66
- maxLatency = l
67
- }
68
- varianceSum += (l - avgLatency ) * (l - avgLatency )
69
- }
70
- stddev := math .Sqrt (varianceSum / float64 (out .Successful ))
71
- out .StdDev = ptr .Ref (time .Duration (stddev * float64 (time .Second )))
72
- out .Avg = ptr .Ref (time .Duration (avgLatency * float64 (time .Second )))
73
- out .Max = ptr .Ref (time .Duration (maxLatency * float64 (time .Second )))
74
- out .Min = ptr .Ref (time .Duration (minLatency * float64 (time .Second )))
53
+ if s .Max == nil || r .LatencySeconds > s .Min .Seconds () {
54
+ s .Max = ptr .Ref (time .Duration (r .LatencySeconds * float64 (time .Second )))
75
55
}
76
- return & out
56
+ s .latencySum += r .LatencySeconds
57
+
58
+ d := r .LatencySeconds - s .runningAvg
59
+ s .runningAvg += d / float64 (s .Successful )
60
+ d2 := r .LatencySeconds - s .runningAvg
61
+ s .m2 += d * d2
77
62
}
78
63
79
- func (p * pingSummary ) Write (w io.Writer ) {
80
- out , err := cliui .DisplayTable ([]* pingSummary {p }, "" , nil )
64
+ // Write finalizes the summary and writes it
65
+ func (s * pingSummary ) Write (wsname string , w io.Writer ) {
66
+ s .Workspace = wsname
67
+ if s .Successful > 0 {
68
+ s .Avg = ptr .Ref (time .Duration (s .latencySum / float64 (s .Successful ) * float64 (time .Second )))
69
+ }
70
+ if s .Successful > 1 {
71
+ s .Variance = ptr .Ref (time .Duration ((s .m2 / float64 (s .Successful - 1 )) * float64 (time .Second )))
72
+ }
73
+ out , err := cliui .DisplayTable ([]* pingSummary {s }, "" , nil )
81
74
if err != nil {
82
75
_ , _ = fmt .Fprintf (w , "Failed to display ping summary: %v\n " , err )
83
76
return
@@ -194,10 +187,9 @@ func (r *RootCmd) ping() *serpent.Command {
194
187
}
195
188
196
189
connDiags .Write (inv .Stdout )
197
-
190
+ results := & pingSummary {}
198
191
n := 0
199
192
start := time .Now ()
200
- results := make ([]* ipnstate.PingResult , 0 )
201
193
pingLoop:
202
194
for {
203
195
if n > 0 {
@@ -208,7 +200,7 @@ func (r *RootCmd) ping() *serpent.Command {
208
200
ctx , cancel := context .WithTimeout (ctx , pingTimeout )
209
201
dur , p2p , pong , err := conn .Ping (ctx )
210
202
cancel ()
211
- results = append ( results , pong )
203
+ results . addResult ( pong )
212
204
if err != nil {
213
205
if xerrors .Is (err , context .DeadlineExceeded ) {
214
206
_ , _ = fmt .Fprintf (inv .Stdout , "ping to %q timed out \n " , workspaceName )
@@ -274,14 +266,7 @@ func (r *RootCmd) ping() *serpent.Command {
274
266
}
275
267
}
276
268
277
- if didP2p {
278
- _ , _ = fmt .Fprintf (inv .Stdout , "✔ You are connected directly (p2p)\n " )
279
- } else {
280
- _ , _ = fmt .Fprintf (inv .Stdout , "❗ You are connected via a DERP relay, not directly (p2p)\n %s#common-problems-with-direct-connections\n " , connDiags .TroubleshootingURL )
281
- }
282
-
283
- summary := buildSummary (workspaceName , results )
284
- summary .Write (inv .Stdout )
269
+ results .Write (workspaceName , inv .Stdout )
285
270
286
271
return nil
287
272
},
0 commit comments