Files
http-latency-prober/README.md
Jan Novak a588eb3b0e feat(go): step 1 — total wall-clock latency per URL
probe.Measure performs an HTTP GET and records total elapsed time from
request start to body fully read. main.go prints URL, status code, and
total for each positional URL argument, exiting 1 on any failure.

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

118 lines
3.0 KiB
Markdown

# latprobe — Website Latency Probe
A command-line tool that measures the latency of one or more websites, with a
**full per-request phase breakdown** — DNS resolution, TCP connect, TLS
handshake, server processing (time-to-first-byte), and content transfer.
Not just a ping: `latprobe` shows you _where_ the time goes.
## Why
A single total request time hides the root cause of slowness. Is it DNS? A slow
TLS negotiation? A laggy server? `latprobe` breaks the request into its
constituent phases so the bottleneck is immediately obvious.
## Implementations
| Language | Status | Location |
|----------|-----------|------------|
| Go | In progress | `go/` |
| Python | Planned | `python/` |
Both implementations produce identical CLI behaviour and output formats.
---
## Usage (Go)
```
latprobe [flags] <url> [url ...]
Flags:
-n, --count int Number of requests per URL (default 1)
--json Output results as JSON instead of text
Examples:
latprobe https://example.com
latprobe -n 5 https://example.com https://www.google.com
latprobe --json https://example.com | jq .
```
---
## Output
### Text (default)
```
https://example.com
DNS lookup : 12.34 ms
TCP connect : 8.91 ms
TLS handshake : 45.20 ms
Server (TTFB) : 78.56 ms
Transfer : 2.10 ms
─────────────────────────
Total : 147.11 ms
```
With `-n 5` (min / avg / max columns):
```
https://example.com (5 samples)
min avg max
DNS lookup : 10.1ms 12.3ms 15.7ms
TCP connect : 7.8ms 9.0ms 11.2ms
...
```
### JSON (`--json`)
```json
{
"url": "https://example.com",
"samples": 1,
"phases": {
"dns": { "ms": 12.34 },
"connect": { "ms": 8.91 },
"tls": { "ms": 45.20 },
"ttfb": { "ms": 78.56 },
"transfer": { "ms": 2.10 },
"total": { "ms": 147.11 }
}
}
```
---
## Implementation Roadmap
### Go
| Step | Feature | Status |
|------|---------|--------|
| 0 | Project scaffold — directory structure, `go.mod`, minimal binary | ✅ Done |
| 1 | Simple total latency — single URL, wall-clock time | ✅ Done |
| 2 | Per-phase breakdown — DNS, TCP, TLS, TTFB, transfer (`net/http/httptrace`) | ⬜ Pending |
| 3 | Multiple URLs + `--count`/`-n` — min/avg/max aggregates | ⬜ Pending |
| 4 | `--json` output flag | ⬜ Pending |
### Python
Begins after the Go implementation is approved. Will mirror the same CLI and
output format. Timed using low-level socket hooks (DNS via `socket.getaddrinfo`,
connection timings via custom socket wrap or `httpx`/`urllib3` hooks).
---
## Development Environment
- Go 1.26.4 / darwin arm64
- Python 3.14.6
- No external dependencies (Go uses stdlib only; Python TBD at port time)
## Project Conventions
See [CLAUDE.md](CLAUDE.md) for the development conventions followed in this project:
- Plans saved to `docs/plans/` with timestamped filenames
- Completed features logged in `CHANGELOG.md` with timestamps
- Per-feature user docs in `docs/usage/`