litellm/tests/unit/proxy/spend_tracking
shrey-berri 9c4096d0e3 fix(spend): read only the newest rows for the session view page (LIT-8513)
The session view grouped every row in the date window to show 50
sessions and count them, so each page read the whole window. Read the
newest rows that match the filters instead, group those, and keep only
sessions that are complete in what was read: a session whose last
activity is newer than the oldest row read has every row in the read.

The first read is cap + offset + page size + 2 rows, and at most
2 x cap + 2 for a page past the cap, so a huge page number cannot
overflow the read's LIMIT. It grows 8x, then 64x, then reads
everything, only while the page or the count is not settled; a read that does not settle is discarded, so results are the
same as before and the count still stops at 10,000. Ascending order
still reads every row in one query.

On a busy key, where few long sessions fill the newest rows, a read
that the last read's rows per session say cannot hold enough sessions
is skipped. An offset page's read that holds no session of the page
hands its sessions to the next read, which reads only the rows at or
below that read's oldest row, up to the rest of its budget. So a deep
page reads each row about once instead of re-reading the newest rows
at every step: the last page of a key with 2,000 sessions of 50 rows
read about 307-313k rows before and about 195-205k now, against 205k
for grouping every row.

A descending cursor page reads from the cursor's startTime down and
drops sessions that also have a newer row. When the sessions after the
cursor do not pass the cap, the window's count is read separately from
the newest rows, starting at the first read size that the last read's
rows per session say can pass the cap, so an unindexed filter such as
key_alias or status does not pay a full scan per step.

The status filter keeps or drops whole sessions, so the newer-row probe
skips it for sessions already on the page. The representative fetch
checks it again on just those sessions, since a row written after the
page read can change a session's outcome; as before, such a session is
dropped from the page.
Its subquery gets the date window as literals: Prisma reuses prepared
statements, and from the 6th run Postgres plans a $N window as tiny,
which turned the subquery into a ~2 min nested loop. The literal is
built only from a UTC datetime; anything else raises.
2026-10-28 10:25:19 -07:00
..
__init__.py ci: move tests/proxy_unit_tests to tests/unit/proxy and run the proxy-db shards from litellm-tests (#42903) 2026-09-24 22:59:11 +00:00
test_background_interaction_settlement.py fix(interactions): keep background interaction bills through crashes, late restarts, and deployment keys (#45743) 2026-10-16 12:00:08 +00:00
test_baseline_accounting.py fix(router): preserve native baseline identity and accounting (#44960) 2026-10-07 11:00:31 -07:00
test_budget_reservation.py refactor(types): replace Any with proven types in 137 files (#44478) 2026-10-05 11:01:45 -07:00
test_budget_reservation_redis_failure.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_carried_budget_state.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_cloudzero_endpoints.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_compression_savings.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_input_tokens.py fix(responses)!: round-trip Anthropic compaction blocks as compaction items (#46754) 2026-10-21 08:50:19 +00:00
test_key_metadata_recovery.py fix: cap cold MCP schema workers at usable CPUs and deflake wall-clock unit tests (#45791) 2026-10-15 00:47:59 -07:00
test_ptu_feature_flag.py feat(proxy): split Azure PTU deployments across teams with per-team PTU ceilings and PTU-hour reporting (#43043) 2026-10-15 18:44:30 +00:00
test_ptu_flat_cost_rollup.py feat(proxy): split Azure PTU deployments across teams with per-team PTU ceilings and PTU-hour reporting (#43043) 2026-10-15 18:44:30 +00:00
test_savings.py perf(savings): read deployment pricing from the router's cached model info (#47400) 2026-10-19 17:07:00 -07:00
test_search_api_logging.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
test_spend_capture_rate.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_spend_counter_batch.py fix(proxy)!: stop update_cache from resurrecting evicted auth cache entries (#46997) 2026-10-20 17:09:53 +00:00
test_spend_event.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_spend_event_producer.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_spend_log_error_logger.py test(proxy): move middleware, spend_tracking, pass_through, common_utils and root proxy tests into tests/unit/proxy (#44015) 2026-10-01 18:23:31 +00:00
test_spend_management_endpoints.py fix(spend): read only the newest rows for the session view page (LIT-8513) 2026-10-28 10:25:19 -07:00
test_spend_query_optimization.py fix(spend): read only the newest rows for the session view page (LIT-8513) 2026-10-28 10:25:19 -07:00
test_spend_tracking_utils.py fix(responses)!: round-trip Anthropic compaction blocks as compaction items (#46754) 2026-10-21 08:50:19 +00:00