Files
http-latency-prober/go/internal/probe/aggregate.go
Jan Novak 8ec926bbcd feat(go): step 3 — multiple URLs and -n sampling with min/avg/max
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>
2026-07-01 00:29:36 +02:00

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,
}
}