Add probe.Summarize to aggregate N Results into per-phase min/avg/max stats. Wire up -n/--count flag in main to repeat each URL N times and display an aligned three-column table. Single-sample output (n=1) is unchanged. URLs are grouped with a blank line between them. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
package probe
|
|
|
|
import "time"
|
|
|
|
// PhaseStats holds min/avg/max for a phase across N samples.
|
|
type PhaseStats struct {
|
|
Min, Avg, Max time.Duration
|
|
Present bool
|
|
}
|
|
|
|
// Aggregate holds per-phase statistics over a set of Results.
|
|
type Aggregate struct {
|
|
URL string
|
|
Count int
|
|
StatusCode int
|
|
DNS PhaseStats
|
|
Connect PhaseStats
|
|
TLS PhaseStats
|
|
TTFB PhaseStats
|
|
Transfer PhaseStats
|
|
Total PhaseStats
|
|
}
|
|
|
|
// Summarize computes min/avg/max per phase from a slice of Results.
|
|
func Summarize(results []Result) Aggregate {
|
|
a := Aggregate{Count: len(results)}
|
|
if len(results) == 0 {
|
|
return a
|
|
}
|
|
a.URL = results[0].URL
|
|
a.StatusCode = results[len(results)-1].StatusCode
|
|
|
|
a.DNS = phaseStats(results, func(r Result) Phase { return r.DNS })
|
|
a.Connect = phaseStats(results, func(r Result) Phase { return r.Connect })
|
|
a.TLS = phaseStats(results, func(r Result) Phase { return r.TLS })
|
|
a.TTFB = phaseStats(results, func(r Result) Phase { return r.TTFB })
|
|
a.Transfer = phaseStats(results, func(r Result) Phase { return r.Transfer })
|
|
a.Total = phaseStats(results, func(r Result) Phase { return r.Total })
|
|
|
|
return a
|
|
}
|
|
|
|
func phaseStats(results []Result, get func(Result) Phase) PhaseStats {
|
|
var durations []time.Duration
|
|
for _, r := range results {
|
|
if p := get(r); p.Present {
|
|
durations = append(durations, p.Duration)
|
|
}
|
|
}
|
|
if len(durations) == 0 {
|
|
return PhaseStats{}
|
|
}
|
|
|
|
min, max := durations[0], durations[0]
|
|
var sum time.Duration
|
|
for _, d := range durations {
|
|
if d < min {
|
|
min = d
|
|
}
|
|
if d > max {
|
|
max = d
|
|
}
|
|
sum += d
|
|
}
|
|
return PhaseStats{
|
|
Min: min,
|
|
Avg: sum / time.Duration(len(durations)),
|
|
Max: max,
|
|
Present: true,
|
|
}
|
|
}
|