Each listener now tracks chain setup latency independently via a
dict[str, LatencyTracker] on Metrics. The global aggregate stays for
summary output. /status embeds per-listener latency on each listener
entry; /metrics includes a listener_latency map keyed by host:port.
Add RateTracker (rolling deque, events/sec) and LatencyTracker (circular
buffer, p50/p95/p99 in ms) to the Metrics class. Both are recorded in
_handle_client and exposed via summary(), to_dict(), /status, and /metrics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each listener binds to its own port with an independent chain.
The "pool" keyword in a chain appends a random alive proxy from
the shared pool; multiple pool entries = multiple hops.
:1080 -> Tor only (0 pool hops)
:1081 -> Tor + 1 pool proxy
:1082 -> Tor + 2 pool proxies
Shared resources (ProxyPool, Tor, metrics, semaphore, API) are
reused across listeners. FirstHopPool is shared per unique first
hop. Backward compatible: old listen/chain format still works.
29 tests covering request parsing, JSON response format, all GET/POST
handlers with mock context, 404/405 error routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>