🤖 Browsers expose per-request phase timings (DNS / connect / TLS / TTFB / download) via Resource Timing. For a server-side client this is observability gold, and fáith already has the stats/conn-tracker scaffolding to hang it on.
The constraint is what reqwest exposes: total time, connection reuse, and remote address are easy; phase boundaries (DNS vs connect vs TLS) are not, without upstream hooks. Even the partial version is most of the practical value:
response.timing = {
start, // request accepted
sent, // request handed to the connection
firstByte, // response headers received
end, // body fully consumed (settled late, like trailers)
reusedConnection: bool,
protocol: "HTTP/2.0",
}
Middleware-level timestamps get start/firstByte; body-stream completion gets end. Worth designing the shape against the PerformanceResourceTiming names where they map, so it feels familiar.
The per-protocol path-time EWMA from #45's follow-on records origin-level aggregates of the same measurements — the two should share the instrumentation point.
🤖 Browsers expose per-request phase timings (DNS / connect / TLS / TTFB / download) via Resource Timing. For a server-side client this is observability gold, and fáith already has the stats/conn-tracker scaffolding to hang it on.
The constraint is what reqwest exposes: total time, connection reuse, and remote address are easy; phase boundaries (DNS vs connect vs TLS) are not, without upstream hooks. Even the partial version is most of the practical value:
Middleware-level timestamps get
start/firstByte; body-stream completion getsend. Worth designing the shape against the PerformanceResourceTiming names where they map, so it feels familiar.The per-protocol path-time EWMA from #45's follow-on records origin-level aggregates of the same measurements — the two should share the instrumentation point.