mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
refactor(ui): derive drilldown validity and drop Map mutation in bucket grouping
The drilldown now self-dismisses when refetched activity has no failures for its call_type, instead of holding a selection the chart no longer shows. groupErrorBuckets is rewritten as pure filter/map/sort over the already-grouped SQL rows.
This commit is contained in:
parent
0de0e1cef6
commit
a5c81e525b
3 changed files with 45 additions and 17 deletions
|
|
@ -24,21 +24,18 @@ export type ErrorCodeDatum = {
|
|||
};
|
||||
|
||||
export const groupErrorBuckets = (buckets: readonly CacheActivityErrorBucket[], callType: string): ErrorCodeDatum[] => {
|
||||
const byCode = new Map<string, Map<string, number>>();
|
||||
for (const bucket of buckets) {
|
||||
if (bucket.call_type !== callType) continue;
|
||||
const classes = byCode.get(bucket.error_code) ?? new Map<string, number>();
|
||||
classes.set(bucket.error_class, (classes.get(bucket.error_class) ?? 0) + bucket.count);
|
||||
byCode.set(bucket.error_code, classes);
|
||||
}
|
||||
return [...byCode.entries()]
|
||||
.map(([errorCode, classes]) => ({
|
||||
error_code: errorCode,
|
||||
[FAILED_REQUESTS_SERIES]: [...classes.values()].reduce((total, count) => total + count, 0),
|
||||
classes: [...classes.entries()]
|
||||
.map(([errorClass, count]) => ({ error_class: errorClass, count }))
|
||||
.sort((a, b) => b.count - a.count),
|
||||
}))
|
||||
const rows = buckets.filter((bucket) => bucket.call_type === callType);
|
||||
return [...new Set(rows.map((row) => row.error_code))]
|
||||
.map((errorCode) => {
|
||||
const codeRows = rows.filter((row) => row.error_code === errorCode);
|
||||
return {
|
||||
error_code: errorCode,
|
||||
[FAILED_REQUESTS_SERIES]: codeRows.reduce((total, row) => total + row.count, 0),
|
||||
classes: codeRows
|
||||
.map((row) => ({ error_class: row.error_class, count: row.count }))
|
||||
.sort((a, b) => b.count - a.count),
|
||||
};
|
||||
})
|
||||
.sort((a, b) => b[FAILED_REQUESTS_SERIES] - a[FAILED_REQUESTS_SERIES]);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -211,6 +211,31 @@ describe("CacheDashboard cache analytics charts", () => {
|
|||
expect(screen.queryByText(/Failed requests by error code/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("dismisses an open drilldown when refetched data no longer has failures for that call_type", async () => {
|
||||
const { rerender } = renderDashboard();
|
||||
const { requestsCard } = await findChartCards();
|
||||
|
||||
const redBar = Array.from(requestsCard.querySelectorAll(".recharts-bar")).find((bar) =>
|
||||
bar.querySelector("path.recharts-rectangle")?.getAttribute("fill")?.includes("red"),
|
||||
);
|
||||
fireEvent.click(redBar!.querySelectorAll("path.recharts-rectangle")[0]);
|
||||
expect(screen.getByText("Failed requests by error code: acompletion")).toBeInTheDocument();
|
||||
|
||||
useCacheActivity.mockReturnValue({
|
||||
data: {
|
||||
...cacheActivity,
|
||||
groups: cacheActivity.groups.map((group) =>
|
||||
group.call_type === "acompletion" ? { ...group, failed_requests: 0 } : group,
|
||||
),
|
||||
error_breakdown: cacheActivity.error_breakdown.filter((bucket) => bucket.call_type !== "acompletion"),
|
||||
},
|
||||
refetch: vi.fn(),
|
||||
});
|
||||
rerender(<CacheDashboard accessToken="sk-test" token="tok" userRole="Admin" userID="u1" premiumUser={false} />);
|
||||
|
||||
expect(screen.queryByText(/Failed requests by error code/)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("formats y-axis ticks with compact notation", async () => {
|
||||
renderDashboard();
|
||||
const { requestsCard, tokensCard } = await findChartCards();
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ const formatDateWithoutTZ = (date: Date | undefined) => {
|
|||
return date.toISOString().split("T")[0];
|
||||
};
|
||||
|
||||
const resolveDrilldownCallType = (selected: string | null, groups: readonly CacheActivityGroup[]): string | null =>
|
||||
selected !== null && groups.some((group) => group.call_type === selected && group.failed_requests > 0)
|
||||
? selected
|
||||
: null;
|
||||
|
||||
function valueFormatterNumbers(number: number) {
|
||||
const formatter = new Intl.NumberFormat("en-US", {
|
||||
maximumFractionDigits: 0,
|
||||
|
|
@ -98,6 +103,7 @@ const CacheDashboard: React.FC<CachePageProps> = ({ accessToken, token, userRole
|
|||
const uniqueApiKeys = activity?.filter_options.key_aliases ?? [];
|
||||
const uniqueModels = activity?.filter_options.models ?? [];
|
||||
const chartData = (activity?.groups ?? []).map(toChartDatum);
|
||||
const activeDrilldownCallType = resolveDrilldownCallType(errorDrilldownCallType, activity?.groups ?? []);
|
||||
|
||||
const handleRefreshClick = () => {
|
||||
refetch();
|
||||
|
|
@ -298,9 +304,9 @@ const CacheDashboard: React.FC<CachePageProps> = ({ accessToken, token, userRole
|
|||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{errorDrilldownCallType !== null && (
|
||||
{activeDrilldownCallType !== null && (
|
||||
<ErrorDrilldownCard
|
||||
callType={errorDrilldownCallType}
|
||||
callType={activeDrilldownCallType}
|
||||
buckets={activity?.error_breakdown ?? []}
|
||||
valueFormatter={valueFormatterNumbers}
|
||||
onClose={() => setErrorDrilldownCallType(null)}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue