From ba75a588c9274b5330ae8de12f5cd0ce3849db03 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 21:25:58 +0000 Subject: [PATCH] fix(ui): make model leaderboard chart bars wide and readable (#44249) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com> --- .../_components/ModelInsightsView.test.tsx | 8 ++--- .../_components/ModelInsightsView.tsx | 2 +- .../_components/modelInsightsData.test.ts | 31 +++++++++++++++++++ .../_components/modelInsightsData.ts | 8 ++++- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.test.tsx index 36443e90b63..37d265c4e35 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.test.tsx @@ -155,16 +155,16 @@ describe("ModelInsightsView", () => { render(); await screen.findByText("fast-chat"); const chart = screen.getByTestId("usage-chart"); - const days = (Date.parse(response.end_date) - Date.parse(response.start_date)) / 86_400_000 + 1; expect(screen.getByRole("tab", { name: "Daily" })).toHaveAttribute("aria-selected", "true"); - expect(chart).toHaveAttribute("data-buckets", String(days)); + expect(chart).toHaveAttribute("data-buckets", "30"); + expect(chart).toHaveAttribute("data-first", "2026-08-30"); expect(screen.getByText("Daily tokens across your gateway")).toBeInTheDocument(); await userEvent.click(screen.getByRole("tab", { name: "Weekly" })); - expect(chart).toHaveAttribute("data-buckets", String(Math.ceil(days / 7))); - expect(chart).toHaveAttribute("data-first", response.start_date); + expect(chart).toHaveAttribute("data-buckets", "12"); + expect(chart).toHaveAttribute("data-first", "2026-07-13"); expect(screen.getByText("Weekly tokens across your gateway")).toBeInTheDocument(); }); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.tsx index 312c469903d..c946e8aabe0 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/ModelInsightsView.tsx @@ -257,7 +257,7 @@ export default function ModelInsightsView({ accessToken }: { accessToken: string - + { { date: "2026-01-03", a: 10 }, ]); }); + + it("starts the chart at the first bucket with usage so bars stay wide on a long range", () => { + const rows = [row({ date: "2026-03-10", requests: 1 }), row({ date: "2026-03-20", requests: 2 })]; + const daily = buildSeries(rows, ["a"], "requests", { start: "2025-03-21", end: "2026-03-20", granularity: "day" }); + expect(daily[0]).toEqual({ date: "2026-02-19", a: 0 }); + expect(daily).toHaveLength(30); + expect(daily.at(-1)).toEqual({ date: "2026-03-20", a: 2 }); + + const early = [row({ date: "2025-12-01", requests: 1 }), ...rows]; + const fromFirstUse = buildSeries(early, ["a"], "requests", { + start: "2025-03-21", + end: "2026-03-20", + granularity: "day", + }); + expect(fromFirstUse[0]).toEqual({ date: "2025-12-01", a: 1 }); + expect(fromFirstUse.at(-1)?.date).toBe("2026-03-20"); + }); + + it("keeps weekly buckets on the original grid when trimming idle weeks", () => { + const rows = [row({ date: "2026-03-20", requests: 3 })]; + const weekly = buildSeries(rows, ["a"], "requests", { + start: "2025-03-21", + end: "2026-03-20", + granularity: "week", + }); + expect(weekly).toHaveLength(12); + expect(weekly.map((week) => (Date.parse(String(week.date)) - Date.parse("2025-03-21")) % (7 * 86_400_000))).toEqual( + Array(12).fill(0), + ); + expect(weekly.at(-1)).toEqual({ date: "2026-03-20", a: 3 }); + }); }); describe("buildBucketTotals", () => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/modelInsightsData.ts b/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/modelInsightsData.ts index e4e83d24362..0e1a5fa7aac 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/modelInsightsData.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/model-insights/_components/modelInsightsData.ts @@ -37,6 +37,7 @@ export type Granularity = "day" | "week"; const DAY_MS = 86_400_000; const BUCKET_DAYS: Record = { day: 1, week: 7 }; +const MIN_VISIBLE_BUCKETS: Record = { day: 30, week: 12 }; export const metricValue = (row: Usage, metric: Metric) => { if (metric === "requests") return row.requests; @@ -85,7 +86,12 @@ export const buildSeries = (rows: DailyMetric[], models: string[], metric: Metri const bucket = buckets[Math.floor((toDay(row.date) - origin) / bucketMs)]; if (bucket) bucket[row.model_group] = Number(bucket[row.model_group] ?? 0) + metricValue(row, metric); } - return buckets; + const firstActive = buckets.findIndex((bucket) => models.some((model) => Number(bucket[model]) > 0)); + const visibleFrom = Math.min( + firstActive === -1 ? buckets.length : firstActive, + buckets.length - MIN_VISIBLE_BUCKETS[window.granularity], + ); + return buckets.slice(Math.max(0, visibleFrom)); }; export const buildBucketTotals = (totals: DailyTotal[], metric: Metric, window: SeriesWindow) => {