Goal
The HAR's `timings.wait` after #(downstream-timings PR) measures server-side processing only — time from request received by go-proxy to first response byte sent. The true client-perceived wait includes the network RTT in both directions:
```
true_wait = RTT/2 (client → proxy)
+ server_processing (the new ClientWaitMs)
+ RTT/2 (first response byte ← proxy)
```
On LAN / loopback the RTTs are negligible and `server_wait ≈ true_wait`. On wifi / cellular / shaped paths the RTT can dominate, and a HAR that under-reports wait makes the network look healthier than it is to anyone reading it.
Approach
Option A: server-side via `TCP_INFO` (preferred)
Linux exposes the kernel's smoothed RTT estimator per established TCP connection via `getsockopt(TCP_INFO)`. Go can reach it through `net.TCPConn.SyscallConn().Control`. Sample on every request from the connection associated with that `*http.Request`, store on the `NetworkLogEntry` as `ClientRTTMs`. Map into HAR as:
- Add `ClientRTTMs` to `NetworkLogEntry`.
- Augment `_extensions.upstream` with a sibling `_extensions.client_rtt` block carrying `{rtt_ms, samples_seen}`.
- The HAR's main `timings.wait` stays as server processing for compatibility with viewers, but the extension block tells you "true wait ≈ wait + rtt_ms".
Cost: ~50 lines of `syscall` plumbing in the proxy handler. No client work.
Option B: client-reported RTT
Player samples `URLSessionTaskMetrics` (Apple) / OkHttp `EventListener.connectStart→connectEnd` (Android), POSTs the latest RTT in the existing heartbeat. More accurate (real client→server measurement, not kernel estimate), but more code on three platforms.
Recommendation
Land Option A first as the cheap baseline. Option B can layer on later if Option A's smoothed-RTT estimate proves too lossy under packet loss / heavy shaping.
Out of scope
Estimated points: 5
Goal
The HAR's `timings.wait` after #(downstream-timings PR) measures server-side processing only — time from request received by go-proxy to first response byte sent. The true client-perceived wait includes the network RTT in both directions:
```
true_wait = RTT/2 (client → proxy)
+ server_processing (the new ClientWaitMs)
+ RTT/2 (first response byte ← proxy)
```
On LAN / loopback the RTTs are negligible and `server_wait ≈ true_wait`. On wifi / cellular / shaped paths the RTT can dominate, and a HAR that under-reports wait makes the network look healthier than it is to anyone reading it.
Approach
Option A: server-side via `TCP_INFO` (preferred)
Linux exposes the kernel's smoothed RTT estimator per established TCP connection via `getsockopt(TCP_INFO)`. Go can reach it through `net.TCPConn.SyscallConn().Control`. Sample on every request from the connection associated with that `*http.Request`, store on the `NetworkLogEntry` as `ClientRTTMs`. Map into HAR as:
Cost: ~50 lines of `syscall` plumbing in the proxy handler. No client work.
Option B: client-reported RTT
Player samples `URLSessionTaskMetrics` (Apple) / OkHttp `EventListener.connectStart→connectEnd` (Android), POSTs the latest RTT in the existing heartbeat. More accurate (real client→server measurement, not kernel estimate), but more code on three platforms.
Recommendation
Land Option A first as the cheap baseline. Option B can layer on later if Option A's smoothed-RTT estimate proves too lossy under packet loss / heavy shaping.
Out of scope
Estimated points: 5