Skip to content

fix(ui): stop Request Logs page from overflowing horizontally and size its columns - #31426

Merged
yuneng-berri merged 8 commits into
litellm_internal_stagingfrom
litellm_/cranky-hamilton-21b5d0
Jun 30, 2026
Merged

fix(ui): stop Request Logs page from overflowing horizontally and size its columns#31426
yuneng-berri merged 8 commits into
litellm_internal_stagingfrom
litellm_/cranky-hamilton-21b5d0

Conversation

@yuneng-berri

@yuneng-berri yuneng-berri commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Relevant issues

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

This is a UI layout change, so the proof is visual. Against a running proxy with the dashboard (screenshots to follow):

  1. Start the proxy: python litellm/proxy/proxy_cli.py --config litellm/proxy/dev_config.yaml --detailed_debug --reload
  2. Open http://localhost:4000/ui/?page=logs and stay on the Request Logs tab
  3. Confirm the table scrolls horizontally inside its own card and the page itself no longer overflows sideways
  4. Confirm the columns are sensibly sized: Request ID and Key Hash are tighter, Duration and TTFT are narrow, and Key Alias reads wider than Key Hash
  5. Spot-check a few other dashboard pages (Usage, Keys) to confirm nothing else shifted

Type

🐛 Bug Fix

Changes

The Request Logs page pushed the whole page past the viewport horizontally. The cause was the app shell flex layout, not the table itself. <main className="flex-1"> is a flex item, and flex items default to min-width: auto, which means they refuse to shrink below their content's intrinsic width. The logs table is intrinsically about 2300px across its sixteen whitespace-nowrap columns, so main grew to that width and dragged the page with it. The table's own overflow-x-auto wrapper never got the chance to scroll because its ancestor simply expanded instead

Adding min-w-0 to main lets it shrink to the available width, at which point the existing overflow-x-auto wrapper engages and the table scrolls inside its card. This is the canonical fix for a flex child that won't shrink, and it applies to every dashboard page rather than just logs. Also dropping the max-w-screen class on the logs container; it is not a real Tailwind utility (the scale is max-w-screen-sm and friends), so it was a silent no-op that read like an intended viewport cap

On top of the overflow fix, the spend-logs columns now declare explicit pixel widths so the table is legible rather than letting auto-layout distribute space arbitrarily. The shared DataTable derives the table's min-width from react-table's getCenterTotalSize(), so it stretches to fill a wide card but scrolls once the columns no longer fit, and it applies per-column widths to each header and body cell. This sizing only kicks in when columns actually declare a size; the other DataTable consumers (pass-through settings, MCP toolsets, Usage Top Keys / Top Models) declare none and keep their existing fluid layout untouched. With the widths in place, Request ID and Key Hash are trimmed by about 30% (Key Hash now narrower than the more useful Key Alias) and Duration and TTFT shrink to fit their short numeric values

view_logs/table.test.tsx pins the sizing contract: when columns declare sizes the table takes a min-width equal to their total and every header / body cell takes its column width, and when they do not the cells stay unsized and the table keeps its fluid layout. The min-width assertion was mutation-checked by switching it back to a hard width and confirming the test fails

image

…rflowing

Tremor's Table forwards className to a wrapper div rather than the inner table element, so the table-fixed class never reached the table and it stayed table-layout: auto. Across 16 whitespace-nowrap columns that expanded the table far past the viewport

Give each spend-logs column an explicit pixel size and drive the table width from getCenterTotalSize(), matching the Virtual Keys table. The shared DataTable applies this only when columns declare sizes, so the other consumers keep their existing fluid layout
@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes horizontal overflow in the Request Logs table by giving each of the 16 spend-log columns an explicit pixel size and driving the table width from react-table's getCenterTotalSize(), mirroring the approach already used by the Virtual Keys table. The DataTable component preserves its existing fluid w-full layout for all other consumers (pass-through settings, MCP toolsets, Usage views) that do not declare column sizes.

  • columns.tsx: Adds a size (90–200 px) to every spend-log column.
  • table.tsx: Adds a hasExplicitColumnSizes gate; when true, sets a pixel width on the table element, each th, and each td, and applies [&_table]:table-fixed so fixed layout actually reaches the inner <table> element (Tremor's Table forwards className to a wrapper div).
  • table.test.tsx: New tests pin both layout paths — pixel widths when columns declare sizes, fluid layout otherwise.

Confidence Score: 4/5

Safe to merge; this is a UI-only layout change with no backend impact and good test coverage of both layout paths.

The fix is well-scoped and backward-compatible. The hasExplicitColumnSizes gate uses some() rather than every(), which could silently activate the fixed-width layout if a future consumer adds size to only some of its columns — the unsized columns would receive react-table's 150 px default without any warning. This is unlikely to surface today but is worth tightening before other callers are added.

table.tsx — specifically the some() vs every() distinction on line 44.

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/components/view_logs/columns.tsx Adds explicit pixel size to all 16 spend-log columns, enabling the new fixed-width layout path in DataTable.
ui/litellm-dashboard/src/components/view_logs/table.tsx Introduces hasExplicitColumnSizes gate to drive pixel-width layout (table width, per-column th/td widths) when columns declare sizes; backward-compatible path preserved for unsized consumers. Minor concern: some() means one column with a size triggers the entire sized layout for all columns, silently assigning 150 px to unsized peers.
ui/litellm-dashboard/src/components/view_logs/table.test.tsx New test file covering both layout paths; verifies pixel widths propagate to table, headers, and cells when sized, and that unsized columns keep the fluid layout. Coverage is solid for the happy paths.

Reviews (1): Last reviewed commit: "Merge branch 'litellm_internal_staging' ..." | Re-trigger Greptile

enableSorting = false,
}: DataTableProps<TData, TValue>) {
const supportsExpansion = !!(renderSubComponent || renderChildRows) && !!getRowCanExpand;
const hasExplicitColumnSizes = columns.some((column) => column.size !== undefined);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 some() means the sized layout is activated as soon as even one column carries a size, silently assigning react-table's default 150 px to every peer that doesn't declare one. A future caller that adds a single size to a DataTable column will unknowingly trigger the fixed layout across the whole table. Using every() makes the activation intent explicit and avoids this footgun.

Suggested change
const hasExplicitColumnSizes = columns.some((column) => column.size !== undefined);
const hasExplicitColumnSizes = columns.every((column) => column.size !== undefined);

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

… of overflowing

The Request Logs page pushed the whole page past the viewport horizontally. The cause was the app shell flex layout: <main className="flex-1"> is a flex item, and flex items default to min-width: auto, so they refuse to shrink below their content's intrinsic width. The logs table is intrinsically ~2300px across its 16 nowrap columns, so main grew to that width and dragged the page with it; the table's own overflow-x-auto wrapper never got the chance to scroll

Add min-w-0 to main so it can shrink to the available width, at which point the existing overflow-x-auto wrapper engages and the table scrolls inside its card. This applies to every dashboard page, not just logs

Also drop the dead max-w-screen class on the logs container (not a real Tailwind utility, so it was a no-op), and revert the earlier column-sizing attempt which targeted table-layout rather than the actual containment problem
@yuneng-berri yuneng-berri changed the title fix(ui): size Request Logs table columns so it scrolls instead of overflowing fix(ui): let dashboard main pane shrink so wide tables scroll instead of overflowing Jun 27, 2026
…ense ones

Now that the page-overflow bug is fixed by letting the main pane shrink, bring back per-column sizing purely to control widths. Columns declare explicit pixel sizes and the table derives its min-width from getCenterTotalSize(), so it stretches to fill a wide card but scrolls once the columns no longer fit. The shared DataTable applies this only when columns declare sizes, leaving the other consumers on their existing fluid layout

Trim the columns that were eating horizontal space without earning it: Request ID and Key Hash drop ~30% (Key Hash now narrower than Key Alias, which is the more useful of the two), and Duration and TTFT shrink to fit their short numeric values
@yuneng-berri yuneng-berri changed the title fix(ui): let dashboard main pane shrink so wide tables scroll instead of overflowing fix(ui): stop Request Logs page from overflowing horizontally and size its columns Jun 27, 2026
The explicit 90px/80px sizes were too narrow for the Duration (s) and
TTFT (s) headers once the sort arrows were factored in, cramping the
header labels. Dropping the size lets these two columns fall back to the
default width like before
Drop the explicit size on Request ID so it falls back to the default
width like the other reverted columns. Narrow Session ID from 160px to
120px since its truncated value needs less room
@yuneng-berri
yuneng-berri enabled auto-merge June 30, 2026 04:39
@yuneng-berri
yuneng-berri merged commit f8a2ea7 into litellm_internal_staging Jun 30, 2026
124 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_/cranky-hamilton-21b5d0 branch June 30, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants