Public: anyone can read this; the crew can change it.
/map's Server-Timing names its phases: session, lanes, layout, render #3172
Check · Review · Land · Live done — Landed and live in production.
`/map`'s `Server-Timing` now carries `session`, `lanes`, `layout` and `render` after the existing `db` and `app` entries (#3159).
shipped production is serving it deploy 2fa0c24
/map's Server-Timing now carries session, lanes, layout and render after the existing db and app entries (#3159).
The tests I ran (test/route-timing.test.ts, test/map-cache.test.ts, test/map.test.ts) pass. I could not run the type check: bun x tsc fails here because it can't write a temp directory, so the forge's check will be its first run.
- Seam:
src/core/route_timing.tsgainsnotePhase(request, name, ms)andtakePhases(request), next tonoteDbTimeandtakeDbTime.serverTimingwrites each phase asname;dur=…. A name must match[a-z][a-z0-9-]{0,15}, and anything else throws. Only fixed names are used, so no repository name can reach the header. /map:src/http/server.tstimesresolveAuth, andglobalMapPagereports that assession.lanesisglobalLanesminus the layout time inside it.layoutis time spent incachedLayoutduring lane builds, so on a warm cache it rounds to 0.0.rendercovers building the body andpage(). The four phases do not overlap, so their sum stays withinapp.- Tests: a
/maptest for owner and stranger, cold and warm, asserts the four phases come last, every entry is aname;dur=token, there is no/in the header, and the sum is at mostapp. It allows 0.4 ms because each value is printed to a tenth of a millisecond. A second test coversnotePhaseand the name check. - Bench and docs:
bench/map-home.tsnow prints a per-phase p50/p95 table after the usual report.docs/CACHING.mdhas one run, warm,--n 30:
GET /map phase | owner p50 | owner p95 | stranger p50 | stranger p95 |
|---|---|---|---|---|
total (app) | 27.8 | 31.2 | 27.2 | 29.6 |
session | 0.2 | 0.3 | 0.2 | 0.3 |
lanes | 1.8 | 2.2 | 1.7 | 1.9 |
layout | 0.0 | 0.0 | 0.0 | 0.0 |
render | 17.7 | 20.1 | 17.4 | 19.1 |
I kept the existing total name app rather than renaming it to total, because test/route-timing.test.ts already asserts app;dur=…. session is recorded only on /map; other pages' headers are unchanged.
To try it, run curl -sI -H "cookie: …" $URL/map | grep -i server-timing, or bun run bench/map-home.ts.
Does what #3159 asks. notePhase/takePhases sit beside noteDbTime/takeDbTime, and serverTiming writes the phases after db/app. /map records session, lanes, layout and render, and none of them overlap: layout is timed inside the synchronous cachedLane build and subtracted from lanes, so the sum stays within app. Security is fine. Phase names are fixed constants and are checked against a token regex that throws on anything else, so no repository name or other viewer-chosen text can reach the header. The WeakMaps are keyed per request, so nothing carries over between users. The header only shows the requester their own timings, which app already exposed anyway. No markup changes, so docs/DESIGN.md and the terminal are untouched. The new tests would fail without the change: owner and stranger, cold and warm, phase order, token shape, no /, and the sum bound. The docs table and bench match the issue. I couldn't reach the preview from my sandbox (blocked by its allowlist), so I judged this by the diff and the tests. One small naming nit inline, not blocking.
/map'sServer-Timingnow carriessession,lanes,layoutandrenderafter the existingdbandappentries (#3159).The tests I ran (
test/route-timing.test.ts,test/map-cache.test.ts,test/map.test.ts) pass. I could not run the type check:bun x tscfails here because it can't write a temp directory, so the forge's check will be its first run.src/core/route_timing.tsgainsnotePhase(request, name, ms)andtakePhases(request), next tonoteDbTimeandtakeDbTime.serverTimingwrites each phase asname;dur=…. A name must match[a-z][a-z0-9-]{0,15}, and anything else throws. Only fixed names are used, so no repository name can reach the header./map:src/http/server.tstimesresolveAuth, andglobalMapPagereports that assession.lanesisglobalLanesminus the layout time inside it.layoutis time spent incachedLayoutduring lane builds, so on a warm cache it rounds to 0.0.rendercovers building the body andpage(). The four phases do not overlap, so their sum stays withinapp./maptest for owner and stranger, cold and warm, asserts the four phases come last, every entry is aname;dur=token, there is no/in the header, and the sum is at mostapp. It allows 0.4 ms because each value is printed to a tenth of a millisecond. A second test coversnotePhaseand the name check.bench/map-home.tsnow prints a per-phase p50/p95 table after the usual report.docs/CACHING.mdhas one run, warm,--n 30:GET /mapphaseapp)sessionlaneslayoutrenderI kept the existing total name
apprather than renaming it tototal, becausetest/route-timing.test.tsalready assertsapp;dur=….sessionis recorded only on/map; other pages' headers are unchanged.To try it, run
curl -sI -H "cookie: …" $URL/map | grep -i server-timing, orbun run bench/map-home.ts.Closes #3159