package main import ( "flag" "fmt" "os" "strings" "time" "latprobe/internal/probe" ) const usageText = `latprobe — measure per-phase HTTP request latency Usage: latprobe [flags] [url ...] Flags: -n, --count int Number of requests per URL (default 1) --json Output results as JSON instead of text -h, --help Show this help Examples: latprobe https://example.com latprobe -n 5 https://example.com https://www.google.com latprobe --json https://example.com | jq . ` func main() { count := flag.Int("count", 1, "number of requests per URL") flag.IntVar(count, "n", 1, "number of requests per URL (shorthand)") jsonOut := flag.Bool("json", false, "output results as JSON") flag.Usage = func() { fmt.Fprint(os.Stderr, usageText) } flag.Parse() urls := flag.Args() if len(urls) == 0 { fmt.Fprint(os.Stderr, usageText) os.Exit(1) } // --json parsed but not yet functional (wired in Step 4). _ = jsonOut failed := false for i, url := range urls { if i > 0 { fmt.Println() } results := make([]probe.Result, 0, *count) for j := 0; j < *count; j++ { r := probe.Measure(url) if r.Err != nil { fmt.Fprintf(os.Stderr, "error %s (sample %d/%d): %v\n", url, j+1, *count, r.Err) failed = true break } results = append(results, r) } if len(results) == 0 { continue } if *count == 1 { printResult(results[0]) } else { printAggregate(probe.Summarize(results)) } } if failed { os.Exit(1) } } // ── single-sample output ────────────────────────────────────────────────────── func printResult(r probe.Result) { fmt.Printf("%s (%d)\n", r.URL, r.StatusCode) phases := []struct { label string p probe.Phase }{ {"DNS lookup ", r.DNS}, {"TCP connect ", r.Connect}, {"TLS handshake ", r.TLS}, {"Server (TTFB) ", r.TTFB}, {"Transfer ", r.Transfer}, } for _, ph := range phases { if ph.p.Present { fmt.Printf(" %s : %8.2f ms\n", ph.label, ms(ph.p.Duration)) } } fmt.Println(" " + strings.Repeat("─", 29)) fmt.Printf(" %s : %8.2f ms\n", "Total ", ms(r.Total.Duration)) } // ── multi-sample output ─────────────────────────────────────────────────────── func printAggregate(a probe.Aggregate) { fmt.Printf("%s (%d, %d samples)\n", a.URL, a.StatusCode, a.Count) fmt.Printf(" %-14s %9s %9s %9s\n", "", "min", "avg", "max") phases := []struct { label string p probe.PhaseStats }{ {"DNS lookup ", a.DNS}, {"TCP connect ", a.Connect}, {"TLS handshake ", a.TLS}, {"Server (TTFB) ", a.TTFB}, {"Transfer ", a.Transfer}, } for _, ph := range phases { if ph.p.Present { fmt.Printf(" %s : %6.2f ms %6.2f ms %6.2f ms\n", ph.label, ms(ph.p.Min), ms(ph.p.Avg), ms(ph.p.Max)) } } fmt.Println(" " + strings.Repeat("─", 49)) fmt.Printf(" %s : %6.2f ms %6.2f ms %6.2f ms\n", "Total ", ms(a.Total.Min), ms(a.Total.Avg), ms(a.Total.Max)) } func ms(d time.Duration) float64 { return float64(d.Microseconds()) / 1000 }