Files
http-latency-prober/CHANGELOG.md
Jan Novak 9a69ba946f Add URL-level concurrency (-c flag, Step 7)
Probe multiple URLs in parallel with a bounded worker pool; the N samples
of each URL remain sequential to preserve accurate min/avg/max statistics.
Default auto-concurrency is min(numURLs, 8); -c 1 restores serial mode.
Output is always buffered and printed in original input order. Verified
clean with go test -race.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 01:33:03 +02:00

102 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All completed features are logged here in reverse-chronological order.
---
## 2026-07-01 01:23 — Concurrency (Go, Step 7)
- Added `-c`/`--concurrency` flag: max URLs probed in parallel (0 = auto)
- Default auto-concurrency: `min(numURLs, 8)` — scales with workload, caps at 8
- Parallelism is **across URLs only**; the N samples of each URL stay sequential
to preserve the accuracy of per-URL min/avg/max statistics
- Output buffered and printed in original input order (deterministic for both
text and JSON), exit-code accumulation unchanged
- Implementation: semaphore channel + `sync.WaitGroup`, each goroutine writes
only its own indexed result slot — verified clean with `go test -race`
- Added `make go-test-race` target to the Makefile
- 3 new tests: `TestRunConcurrentOrder`, `TestConcurrentWorstCode`,
`TestConcurrentJSONOrder`
- Updated runtime estimates in `docs/custom-usage-examples.md`
- User doc: `docs/usage/step-7-concurrency.md`
---
## 2026-07-01 01:05 — Root Makefile
- Namespaced targets: `go-build`, `go-run`, `go-test`, `go-test-verbose`, `go-check`, `go-cover`, `go-fmt`, `go-vet`, `go-tidy`, `go-install`, `go-lint`, `go-clean`
- Umbrella targets (`build`, `test`, `check`, `fmt`, `vet`, `clean`, `all`) delegate to Go now; `py-*` will slot in during the Python port
- `help` is the default target; auto-generated from `##` comments
- `go-run` accepts `ARGS=` for passing flags, `go-lint` guards for `golangci-lint`
- `.gitignore` updated with coverage artifacts
---
## 2026-07-01 00:49 — Integration tests (Go, Step 6)
- Extracted `run(args, stdout, stderr) int` from `main()` to make the CLI testable in-process
- Fixed TLS classification bug: `TLSHandshakeDone` fires with the error on cert rejection, so `tlsErr` is now captured and checked before the stale `tlsStart.IsZero()` guard
- `run_test.go`: 14 in-process tests covering exit codes 06, multi-URL, sampling, and JSON structure assertions
- `cli_test.go`: `TestMain` builds the real binary; 3 subprocess smoke tests exercise the actual `os.Exit` path
- All test servers use `httptest` + stdlib; `.invalid` TLD for deterministic DNS failures; no external network dependency
---
## 2026-07-01 00:38 — Failure handling (Go, Step 5)
- Classified network failures into `dns` / `connect` / `timeout` / `tls` with distinct exit codes (25)
- Partial timing preserved up to the failure point (e.g. DNS phase shown on NXDOMAIN)
- `--timeout` flag (default 10s) applied via `context.WithTimeout`
- `--fail` flag: HTTP status ≥ 400 → exit code 6 (curl-style)
- `-n` sampling continues on network failure; aggregates successes, reports fail count + cause
- JSON output extended with `succeeded`, `failed`, `errors[]` fields
- Highest exit code across all URLs/failure types is used as the process exit
---
## 2026-07-01 00:08 — JSON output flag (Go, Step 4)
- `--json` flag emits a JSON array with one entry per URL
- Schema always uses min/avg/max shape (consistent regardless of `-n`)
- Phases absent from the request (e.g. TLS on HTTP) are omitted from the JSON object
- Failed URLs are excluded from JSON output and reported to stderr
- Text output unchanged and remains the default
---
## 2026-07-01 00:08 — Multiple URLs + sampling (Go, Step 3)
- `-n`/`--count` flag repeats each URL N times and reports min/avg/max per phase
- `probe.Summarize` aggregates a slice of Results into per-phase PhaseStats
- Multi-sample output shows an aligned min/avg/max table with a header row
- Single-sample output (n=1) is unchanged from Step 2
---
## 2026-07-01 00:08 — Per-phase breakdown (Go, Step 2)
- Instrumented requests with `net/http/httptrace.ClientTrace`
- DNS lookup, TCP connect, TLS handshake, Server/TTFB, Transfer, Total phases
- TLS row omitted automatically for plain `http://` URLs
- Aligned text output with separator before Total
---
## 2026-07-01 00:08 — Simple total latency (Go, Step 1)
- `probe.Measure` performs an HTTP GET and records wall-clock total time
- `main.go` prints URL, HTTP status code, and total duration for each URL
- Exits with code 1 if any URL fails
- Multiple URLs accepted as positional arguments
---
## 2026-07-01 00:08 — Project scaffold (Go, Step 0)
- Created project structure: `go/`, `python/`, `docs/plans/`, `docs/usage/`
- Initialised Go module `latprobe` (`go/go.mod`)
- Minimal `go/main.go` that prints usage and exits cleanly when no URL is given
- Stub `go/internal/probe/probe.go` defining the `Result` type and `Measure` signature
- Foundation files: `README.md`, `CLAUDE.md`, `CHANGELOG.md`
- Saved initial plan to `docs/plans/2026-07-01-00-08-go-latency-tool.md`