feat(spend): raise /spend/logs/v2 page_size cap to 1000 - #33994
Merged
yuneng-berri merged 2 commits intoJul 20, 2026
Merged
Conversation
Clients exporting large spend-log ranges were forced into 100-row pages, which meant a bounded COUNT plus an increasingly deep OFFSET scan per request. Larger pages reduce both the request count and the cumulative OFFSET cost for the same result set. The handler already excludes the heavy JSON columns (messages, response, proxy_server_request) from the paginated SELECT and bounds the COUNT via SPEND_LOGS_PAGINATION_COUNT_CAP, so per-row cost does not grow with page size. 1000 matches the ceiling already used by the user and user-agent analytics list endpoints.
…itellm_/ticket-implementation-review-409e1d
Contributor
Greptile SummaryRaises the
Confidence Score: 5/5Safe to merge — the change is additive only, widening an existing bound without touching handler logic. The diff is a single-line cap increase with no logic changes. Both routes share the same handler and the new limit is validated end-to-end by a well-designed test that uses a 1200-row mock so pagination is genuinely exercised. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/proxy/spend_tracking/spend_management_endpoints.py | Single-line change: raises the page_size FastAPI query constraint from le=100 to le=1000 for the shared ui_view_spend_logs handler (covers both /spend/logs/v2 and /spend/logs/ui). No handler logic changes. |
| tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py | Adds test_ui_view_spend_logs_page_size_upper_bound parametrized over page_size=1000 (expects 200 + 1000 rows) and page_size=1001 (expects 422). Mock generates 1200 rows so the pagination limit is genuinely exercised by the mock's slice logic. |
Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
yuneng-berri
enabled auto-merge
July 20, 2026 17:22
tin-berri
approved these changes
Jul 20, 2026
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.
Relevant issues
Linear ticket
Resolves LIT-4558
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Captured against a live proxy on
localhost:4001backed by a real Postgres with ~247kLiteLLM_SpendLogsrowsBefore, at
067c9bbc96After, at
b7e7fab741A real chat completion through the proxy, then retrieval of that exact row inside a 1000-row page:
Boundary sweep, at
b7e7fab741Pagination equivalence, at
b7e7fab741The strongest regression check: the same 2000 rows fetched as 2 pages of 1000 against 20 pages of 100
Filters still narrow correctly at the new ceiling (
status_filter=successatpage_size=1000returned 1000 rows, allsuccess), and/spend/logs/uistill enriches every row withsession_total_countat its usual page sizeType
🆕 New Feature
Changes
/spend/logs/v2and/spend/logs/uicappedpage_sizeat 100, so a client exporting a large window had to issue a request per 100 rows. This raises the ceiling to 1000The cap is the only thing that moves. Every request that was valid before stays valid and takes the same path, since widening a bound is strictly permissive
Larger pages should reduce load for a bulk export rather than add to it. Each request runs one bounded
COUNTwhose cost is fixed bySPEND_LOGS_PAGINATION_COUNT_CAPregardless of page size, so pulling 10k rows drops from 100 of those probes to 10, and the cumulativeOFFSETwalked across the export shrinks by the same factor. Per-row cost does not grow either; the paginatedSELECTalready excludesmessages,response, andproxy_server_request, which are the columns that can reach hundreds of KB per row1000 rather than 2000 because a 1000-row page serialises to roughly 4.3 MB, and that work is synchronous. 1000 captures nearly all of the round-trip reduction while leaving headroom under concurrent readers;
/v1/user/listand the user-agent analytics endpoints already use the same 1000 ceilingThe 10k pagination count cap from #31825 is deliberately untouched. It bounds the count probe to a fixed number of rows so the query cost stays flat on very large tables, and it never limited how deep a client can page; a request at offset 39000 still returns a full page today
Final Attestation