feat(py): step 3 — full latprobe package with --verbose flag
Adds the complete Python port of the Go latprobe tool plus diagnostic verbose output that the Go version does not yet have. Package (python/latprobe/): - probe.py: raw-socket HTTP timing with CertInfo/VerboseDetail dataclasses; TTFB loop accumulates to \r\n\r\n so headers are parseable without changing t_first_byte semantics; captures resolved IP, TLS version/cipher/bits, verified cert (via getpeercert()), and all response headers when verbose=True - aggregate.py: summarize() → per-phase min/avg/max PhaseStats - cli.py: injectable run(args,stdout,stderr)->int; argparse with injected streams; ThreadPoolExecutor concurrency across URLs; four text-rendering branches; JSON output; worst-exit-code accumulation; -v/--verbose flag appends IP/TLS/cert/header block after every timing table; JSON extended with "verbose" object (omitted when flag absent) - duration.py: parse Go-style duration strings (10s, 500ms, 2m, bare seconds) - Exit codes: 0 ok, 1 usage, 2 dns, 3 connect, 4 timeout, 5 tls, 6 http≥400 Tests: - test_probe.py: 18 hermetic tests (success, 404, DNS/connect/timeout/scheme failures, partial-phase invariants, verbose detail fields) - test_cli.py: 38 hermetic tests (usage errors, single/aggregate/failure text, worst-code, --fail, JSON schema/ordering/grouping, verbose text and JSON) - test_integration.py: 45 tests against live internet services (badssl.com for TLS errors, real cert/IP/header validation in verbose mode) Makefile: PYTHONPATH fix, fnmatch pattern test_[!i]*.py to exclude integration tests from py-test, new py-test-integration target Docs: docs/usage/py-latprobe.md, python/configs/usage-latprobe.md (runnable reference with captured output), plans for both the package and verbose feature Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
46
CHANGELOG.md
46
CHANGELOG.md
@@ -4,6 +4,52 @@ All completed features are logged here in reverse-chronological order.
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-01 12:55 — `--verbose` / `-v` flag for `latprobe` (Python)
|
||||
|
||||
- `-v`/`--verbose` flag added to the `latprobe` CLI
|
||||
- `probe.py`: new `CertInfo` + `VerboseDetail` dataclasses; `Options.verbose`;
|
||||
`Result.detail`; TTFB loop now accumulates until `\r\n\r\n` (unchanged TTFB
|
||||
semantics — `t_first_byte` stamped on first `recv()`, not when headers complete);
|
||||
captures resolved IP (from `getaddrinfo`), TLS version/cipher/bits
|
||||
(from `sock.version()`/`sock.cipher()`), verified cert (from `getpeercert()`),
|
||||
and all response headers
|
||||
- `cli.py`: verbose text block appended after timing rows in all four output
|
||||
branches (single, aggregate, all-failed, mixed); `_VERBOSE_HEADERS` priority
|
||||
list controls which headers appear in text mode; JSON `"verbose"` object
|
||||
includes all parsed headers, full cert fields, TLS metadata; `"verbose"` key
|
||||
omitted when flag is absent
|
||||
- 9 new hermetic probe tests, 15 new CLI tests covering verbose text and JSON
|
||||
across success, connect-fail, and DNS-fail scenarios
|
||||
- 15 new integration tests for real TLS cert fields (CN, expiry, issuer),
|
||||
IP format, TLS version string, header presence, and verbose text/JSON output
|
||||
- `python/configs/usage-latprobe.md`: runnable reference with real output for
|
||||
all features including verbose and `--verbose --json`
|
||||
- `docs/usage/py-latprobe.md`: updated with `--verbose` flag and examples
|
||||
- Plan: `docs/plans/2026-07-01-12-55-py-latprobe-verbose.md`
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-01 12:23 — Full `latprobe` Python package (Python, Step 3)
|
||||
|
||||
- `python/latprobe/` package: full port of the Go CLI, runnable as `python -m latprobe`
|
||||
- `probe.py`: raw-socket HTTP measurement with `Options(timeout)` parameter; mirrors
|
||||
`phases.py` technique; partial phases preserved on failure
|
||||
- `aggregate.py`: `summarize(List[Result]) -> Aggregate` with per-phase `PhaseStats(min_ms, avg_ms, max_ms)`
|
||||
- `duration.py`: parses Go-style duration strings (`10s`, `500ms`, `2m`, bare seconds)
|
||||
- `cli.py`: injectable `run(args, stdout, stderr) -> int`; argparse with injected streams
|
||||
(`_Parser` subclass); `ThreadPoolExecutor` concurrency across URLs; four text-rendering
|
||||
branches (single, aggregate, all-failed, mixed); JSON output; worst-exit-code accumulation
|
||||
- Exit codes: 0 ok, 1 usage, 2 dns, 3 connect, 4 timeout, 5 tls, 6 http≥400 (`--fail`)
|
||||
- `python/tests/test_probe.py`: 9 tests — success, 404, DNS fail, connect refused, TTFB
|
||||
timeout, bad scheme, partial phase invariants; uses `http.server` + daemon threads
|
||||
- `python/tests/test_cli.py`: 23 tests — drives `cli.run()` in-process; covers usage
|
||||
errors, single/aggregate text, failure exit codes, worst-code, `--fail`, JSON schema,
|
||||
JSON ordering, JSON error grouping
|
||||
- Makefile `py-test`: added `PYTHONPATH=$(PY_DIR)`, removed `|| true`
|
||||
- User doc: `docs/usage/py-latprobe.md`
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-01 12:04 — Per-phase latency measurement (Python, Step 2)
|
||||
|
||||
- `python/phases.py`: self-contained script; hand-drives raw sockets to time
|
||||
|
||||
Reference in New Issue
Block a user