# 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 | ⬜ Pending |
| 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/`
