refactor(ai-gateway): fold request logging into rewriteModelResponse - #4755
Conversation
Combine handleRequestLogging and rewriteModelResponse so the event stream is only processed once. handleRequestLogging now returns a capture handle instead of reading a cloned response; rewriteModelResponse accepts the capture and records the upstream body while rewriting it. When request logging is enabled the rewrite pipeline now runs for everyone so the body is captured in the same pass. processUsage is unchanged. Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe incremental commit resolves the previously flagged capture-hang risk by settling Files Reviewed (1 file)
Previous Review Summaries (4 snapshots, latest commit cf5cd24)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit cf5cd24)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe incremental change removes the try/catch that used to settle the request-log capture on unexpected Overview
Issue Details (click to expand)WARNING
Files Reviewed (3 files)
Fix these issues in Kilo Cloud Previous review (commit fd68f42)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental change moves request-log capture creation from the deleted Files Reviewed (4 files)
Previous review (commit dfd96c5)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental change since the last review is a pure formatting update (Prettier line-wrapping of Files Reviewed (4 files)
Previous review (commit ca00505)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed the single-pass request-logging/response-rewrite refactor across all four changed files; the Files Reviewed (4 files)
Reviewed by claude-sonnet-5 · Input: 22 · Output: 3.9K · Cached: 447.6K Review guidance: REVIEW.md from base branch |
Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
handleRequestLogging is folded into rewriteModelResponse: the wrapper creates the request log capture itself from the logging params, so the route makes a single call. Paths where the upstream response is replaced by a readable error use logUnrewrittenResponse. The KILO_ORGANIZATION_ID check in the skip condition is removed since the Kilo organization always has request logging enabled and therefore always gets a capture. Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
…d wrapper try/catch - Rename RequestLogging to RequestLoggingParams. - Remove comments that just restate the code. - Remove the try/catch around the rewrite dispatch: it only guarded against unexpected throws from the JSON body read, which cannot happen in practice. - Fix jest.mock not being hoisted in rewriteModelResponse.test.ts: use the global jest instead of the @jest/globals import, matching the other test files. Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
readResponseText rethrows errors that are not recognized abort/timeout errors. Settle the capture before rethrowing so the after() callback awaiting it does not hang and the request is still logged without a response body. Addresses Kilobot review. Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
Resolve conflicts with the squash-merged #4755 by keeping the branch content, which already contains those changes plus this feature. Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
What
Combines request logging and response rewriting so the upstream event stream is only processed once, and removes
handleRequestLoggingas a separate step.Previously, when both request logging and response rewriting were active, the stream was consumed twice: once by
handleRequestLogging(reading a cloned response via.text()) and once byrewriteModelResponse(parsing and rewriting SSE events).Now:
handleRequestLogging.tsis deleted. Its logic (opt-in check,api_request_loginsert fromafter()) lives inrewriteModelResponse.ts, which creates aRequestLogCapturefrom the passedRequestLoggingParamsand records the raw upstream body while rewriting: the raw text for JSON responses, the raw decoded chunks for SSE streams.organizationId !== KILO_ORGANIZATION_IDcheck in the skip condition is removed as redundant: the Kilo organization always has logging enabled and therefore always gets a capture.cancel()), JSON read errors, and beforereadResponseTextrethrows unrecognized errors — so theafter()callback awaiting it can never hang and the request is always logged (withresponse_body_read_errorwhen the body is unavailable, preserving previous semantics).makeErrorReadableare logged vialogUnrewrittenResponse, which reads the body once on that path.processUsageis unchanged.Tests
Added coverage in
rewriteModelResponse.test.tsfor body capture on JSON and SSE paths, empty bodies, stream read errors, JSON read errors, stream cancellation, and forced processing when request logging is enabled.route.test.tsnow asserts the Vercel request ID is passed through torewriteModelResponse's logging params.