feat(proxy-logs): record per-attempt upstream timing on proxy log rows - #14892
Merged
diegosouzapw merged 5 commits intoSep 28, 2026
Merged
diegosouzapw merged 5 commits into
diegosouzapw merged 5 commits into
Conversation
maxmad64bis
force-pushed
the
fix/attempt-timing-columns
branch
4 times, most recently
from
September 26, 2026 16:10
168ed9e to
d243e67
Compare
maxmad64bis
marked this pull request as ready for review
September 26, 2026 16:36
maxmad64bis
force-pushed
the
fix/attempt-timing-columns
branch
2 times, most recently
from
September 28, 2026 13:52
78f393a to
d756127
Compare
maxmad64bis
force-pushed
the
fix/attempt-timing-columns
branch
from
September 28, 2026 16:41
d756127 to
e89b35b
Compare
…nd keep response identity - The first-chunk body envelope and its deferred row patch now run only with PROXY_LOG_FIRST_CHUNK_TIMING=true; off by default the upstream Response passes through untouched and only headers_ms is recorded. - The enveloped Response keeps url/redirected/type, as tlsClient.ts does. - Reuse sanitizeTimingMs instead of a duplicated journal helper. - Drop ensureProxyLogsColumns from the per-flush path (it already runs at init).
diegosouzapw
merged commit Sep 28, 2026
8d7e2e4
into
diegosouzapw:release/v3.8.51
10 of 16 checks passed
diegosouzapw
added a commit
that referenced
this pull request
Sep 29, 2026
…ync init cycle #14892 made src/lib/db/proxyLogs.ts import sanitizeTimingMs from upstreamStatusCapture.ts, which reaches usage/migrations (top-level await) through providerRequestLogging. Every DB module importing proxyLogs became async and the esbuild MCP bundle deadlocked on import again. The helper moves to a zero-import leaf; upstreamStatusCapture re-exports it.
diegosouzapw
added a commit
that referenced
this pull request
Sep 29, 2026
…leak, MCP bundle deadlocks, sidebar keys, flush-empty-retry, proxy-status and pack-policy tests (#14820) Fixes the reds still present on the tip: client-abort listener leak (#14342 vs #12406), MCP bundle deadlock (quotaCache init cycle via the quotaCacheState leaf, plus the new #14892 proxyLogs -> upstreamStatusCapture -> usage/migrations cycle via the zero-import timingMs leaf), sidebar Model catalog keys, and the stale flush-empty-retry / proxy-status / pack-policy tests. Combo pre-content retry and zh-TW glossary were already fixed on the tip and dropped. Merged tree: 102/102 focused incl. mcp-bundle-startup (red on the tip), typecheck:core clean, open-sse typecheck 0, check:cycles OK, file-size OK.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Long requests could not separate upstream queue wait from generation time: no stored row said when the response headers or the first useful chunk arrived. Each attempt row now records both durations from send start (
headers_ms,first_chunk_ms, nullable, migration 194), measured on the raw upstream body before any translation, and the proxy log detail shows them as "Headers after" and "First chunk after" (a dash when unknown, never 0). The queue/generation split is readable from the row and on screen without replaying logs.Related Issues
Validation
npm run lint— ESLint on the touched files is cleanTests Added Or Updated
tests/unit/proxy-logs-attempt-timing.test.ts(new, 9 cases): column defaults and deferred update, sanitization, bounded pending registry (settle and flood), lazy body envelope (no stamp before the downstream read, status/headers kept, null settle on empty, failed or missing bodies).tests/unit/proxy-logger-observed-fields.test.tsx(1 new case): the detail view shows both durations, and a dash when they are unknown.Coverage Notes
open-sse/utils/upstreamStatusCapture.ts(capture wrapper):proxy-logs-attempt-timing.test.ts(lazy body envelope, settle on empty or failed bodies).src/lib/db/(migration 194, columns, deferred update),src/lib/proxyLogger.tsandsrc/sse/handlers/proxyJournal.ts: the same file (column defaults, deferred update, sanitization, bounded pending registry).src/shared/components/ProxyLogDetail.tsx:proxy-logger-observed-fields.test.tsx.Reviewer Notes
README.md,AGENTS.mdandllm.txt. Those counts are left untouched on purpose: per the maintainer's note on fix(proxies): steer selector to members without recent refusals #14804 they only move on the release train.no-unused-varssuppression forProxyLogDetail.tsx(already unused at the base) is pruned so ESLint stays clean on that file.mutation-test-coverage --strictfails the same way on the release base; no file of this PR is involved.Maintainer rework (merge-batch 2026-09-28)
first_chunk_msrow patch are now opt-in viaPROXY_LOG_FIRST_CHUNK_TIMING(default off, documented in.env.exampleanddocs/reference/ENVIRONMENT.md). With it off the upstreamResponsepasses through untouched (same object) and onlyheaders_msis recorded; the journal registers no pending link.Responsenow keepsurl,redirectedandtypefrom the upstream response (same approach astlsClient.ts).sanitizeAttemptTiming; the journal reusessanitizeTimingMs.ensureProxyLogsColumnsfrom the per-flush path (it already runs at init).false/0) returns the same Response unwrapped; flag off registers no deferred patch in the journal (control with flag on). They fail on the previous head (3/12) and pass now (12/12).