mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
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>
This commit is contained in:
parent
481a403090
commit
ba75a588c9
4 changed files with 43 additions and 6 deletions
|
|
@ -155,16 +155,16 @@ describe("ModelInsightsView", () => {
|
|||
render(<ModelInsightsView accessToken="token" />);
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ export default function ModelInsightsView({ accessToken }: { accessToken: string
|
|||
</CardHeader>
|
||||
<CardContent>
|
||||
<ChartContainer config={chartConfig} className="h-[380px] w-full aspect-auto">
|
||||
<BarChart data={series} margin={{ left: 8, right: 8 }} barCategoryGap={2}>
|
||||
<BarChart data={series} margin={{ left: 8, right: 8 }} barCategoryGap="15%" maxBarSize={64}>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis dataKey="date" tickLine={false} axisLine={false} minTickGap={48} />
|
||||
<YAxis
|
||||
|
|
|
|||
|
|
@ -57,6 +57,37 @@ describe("buildSeries", () => {
|
|||
{ 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", () => {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export type Granularity = "day" | "week";
|
|||
|
||||
const DAY_MS = 86_400_000;
|
||||
const BUCKET_DAYS: Record<Granularity, number> = { day: 1, week: 7 };
|
||||
const MIN_VISIBLE_BUCKETS: Record<Granularity, number> = { 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) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue