From b99d8ac38ee021b4a58b1fcfd4f4fbc1cf0c5b62 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Sat, 5 Sep 2026 14:27:08 -0700 Subject: [PATCH] refactor(ui): keep guardrail usage code under the inline-object-arg lint budget The staging merge pushed local/no-large-inline-object-arg to 567 against a 554 ceiling, and 15 of those hits came from this branch. useGuardrailsUsageDetail now takes the guardrail id positionally with the date window as its second argument, the usageUnits tests build CounterMath rows through a positional helper, and the overview fixture spreads a base row inside the array instead of calling a factory Claude-Session: https://claude.ai/code/session_01EX13mWex6RaBo9PYnkAtFW --- .../_components/GuardrailDetail.test.tsx | 8 ++-- .../_components/GuardrailDetail.tsx | 2 +- .../GuardrailsMonitorView.test.tsx | 3 +- .../_components/GuardrailsOverview.test.tsx | 20 +++++---- .../guardrails/useGuardrailsUsage.test.ts | 5 +-- .../hooks/guardrails/useGuardrailsUsage.ts | 10 ++--- .../GuardrailsMonitor/usageUnits.test.ts | 43 +++++++++---------- 7 files changed, 46 insertions(+), 45 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.test.tsx index 3d00e29245d..9f2a4c42228 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.test.tsx @@ -89,9 +89,8 @@ describe("GuardrailDetail", () => { it("should request the detail and the logs for the guardrail and date range", async () => { renderDetail(); - expect(mockUseGuardrailsUsageDetail).toHaveBeenCalledWith({ + expect(mockUseGuardrailsUsageDetail).toHaveBeenCalledWith("pii-detector", { accessToken: "test-token", - guardrailId: "pii-detector", startDate: "2026-07-01", endDate: "2026-07-24", }); @@ -166,7 +165,10 @@ describe("GuardrailDetail", () => { it("should not request anything without an access token", () => { mockUseGuardrailsUsageDetail.mockReturnValue(loaded(undefined)); renderDetail({ accessToken: null }); - expect(mockUseGuardrailsUsageDetail).toHaveBeenCalledWith(expect.objectContaining({ accessToken: null })); + expect(mockUseGuardrailsUsageDetail).toHaveBeenCalledWith( + "pii-detector", + expect.objectContaining({ accessToken: null }), + ); expect(mockGetGuardrailsUsageLogs).not.toHaveBeenCalled(); }); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.tsx index 1e82f1fee85..81c39258f67 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.tsx @@ -38,7 +38,7 @@ export function GuardrailDetail({ guardrailId, onBack, accessToken = null, start data: detailData, isLoading: detailLoading, error: detailError, - } = useGuardrailsUsageDetail({ accessToken, guardrailId, startDate, endDate }); + } = useGuardrailsUsageDetail(guardrailId, { accessToken, startDate, endDate }); const { data: logsData, isLoading: logsLoading } = useQuery({ queryKey: ["guardrails-usage-logs", guardrailId, logsPage, logsPageSize], queryFn: () => diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.test.tsx index e86b6fa53b6..df106fc38c3 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.test.tsx @@ -107,7 +107,8 @@ describe("GuardrailsMonitorView", () => { expect(await screen.findByRole("heading", { name: "PII Guard" })).toBeInTheDocument(); expect(mockUseGuardrailsUsageDetail).toHaveBeenCalledWith( - expect.objectContaining({ accessToken: "test-token", guardrailId: "gr-pii", startDate: expect.any(String) }), + "gr-pii", + expect.objectContaining({ accessToken: "test-token", startDate: expect.any(String) }), ); expect(screen.queryByRole("heading", { name: /Guardrails Monitor/i })).not.toBeInTheDocument(); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx index 959ed8b172e..ead5fc9f845 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.test.tsx @@ -20,7 +20,7 @@ vi.mock("./EvaluationSettingsModal", () => ({ EvaluationSettingsModal: ({ open }: { open: boolean }) => (open ?
Evaluation settings modal
: null), })); -const row = (overrides: Partial): GuardrailUsageOverviewRow => ({ +const baseRow: GuardrailUsageOverviewRow = { id: "guardrail", name: "Guardrail", type: "content_filter", @@ -34,20 +34,21 @@ const row = (overrides: Partial): GuardrailUsageOverv usageUnits: {}, cost: null, untrackedUsageUnits: {}, - ...overrides, -}); +}; const overview: GuardrailUsageOverview = { rows: [ - row({ + { + ...baseRow, id: "guardrail-low", name: "Low Failure Guardrail", requestsEvaluated: 1200, failRate: 2.5, avgLatency: 45, trend: "down", - }), - row({ + }, + { + ...baseRow, id: "guardrail-high", name: "High Failure Guardrail", provider: "Bedrock", @@ -58,8 +59,9 @@ const overview: GuardrailUsageOverview = { usageUnits: { contentPolicyUnits: 1000, sensitiveInformationPolicyUnits: 250 }, cost: 0.15, untrackedUsageUnits: { sensitiveInformationPolicyUnits: 250 }, - }), - row({ + }, + { + ...baseRow, id: "guardrail-free", name: "Free Bedrock Guardrail", provider: "Bedrock", @@ -67,7 +69,7 @@ const overview: GuardrailUsageOverview = { failRate: 0, usageUnits: { contentPolicyUnits: 40 }, cost: 0, - }), + }, ], chart: [], totalRequests: 1510, diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.test.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.test.ts index f0b2709484d..70fc874fb50 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.test.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.test.ts @@ -50,9 +50,8 @@ describe("useGuardrailsUsageDetail", () => { it("queries GET /guardrails/usage/detail/{guardrail_id} with the id as a path param", () => { renderHook(() => - useGuardrailsUsageDetail({ + useGuardrailsUsageDetail("bedrock-pii-mask", { accessToken: "sk", - guardrailId: "bedrock-pii-mask", startDate: "2026-09-01", endDate: "2026-09-04", }), @@ -73,7 +72,7 @@ describe("useGuardrailsUsageDetail", () => { it("stays disabled without a guardrail id", () => { renderHook(() => - useGuardrailsUsageDetail({ accessToken: "sk", guardrailId: "", startDate: "2026-09-01", endDate: "2026-09-04" }), + useGuardrailsUsageDetail("", { accessToken: "sk", startDate: "2026-09-01", endDate: "2026-09-04" }), ); expect(lastCall()[3].enabled).toBe(false); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.ts index dc7f58fbc8f..5569bdc8beb 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/guardrails/useGuardrailsUsage.ts @@ -24,12 +24,10 @@ export const useGuardrailsUsageOverview = ({ accessToken, startDate, endDate }: { enabled: Boolean(accessToken) }, ); -export const useGuardrailsUsageDetail = ({ - accessToken, - guardrailId, - startDate, - endDate, -}: GuardrailsUsageWindow & { guardrailId: string }) => +export const useGuardrailsUsageDetail = ( + guardrailId: string, + { accessToken, startDate, endDate }: GuardrailsUsageWindow, +) => $api.useQuery( "get", "/guardrails/usage/detail/{guardrail_id}", diff --git a/ui/litellm-dashboard/src/components/GuardrailsMonitor/usageUnits.test.ts b/ui/litellm-dashboard/src/components/GuardrailsMonitor/usageUnits.test.ts index 8e2baaaa3c5..dd5b564b49a 100644 --- a/ui/litellm-dashboard/src/components/GuardrailsMonitor/usageUnits.test.ts +++ b/ui/litellm-dashboard/src/components/GuardrailsMonitor/usageUnits.test.ts @@ -9,8 +9,16 @@ import { unitPrice, unitsMathRows, unpricedSummary, + type CounterMath, } from "./usageUnits"; +const counterOf = (counter: string, units: number, unpriced: number, cost: number | null): CounterMath => ({ + counter, + units, + unpriced, + cost, +}); + describe("formatCost", () => { it("renders a dash when nothing was priced", () => { expect(formatCost(null)).toBe("—"); @@ -66,15 +74,12 @@ describe("unpricedSummary", () => { describe("unitPrice", () => { it("backs the per-unit price out of the priced share only", () => { - expect(unitPrice({ counter: "contentPolicyUnits", units: 1200, unpriced: 200, cost: 0.15 })).toBeCloseTo( - 0.00015, - 10, - ); + expect(unitPrice(counterOf("contentPolicyUnits", 1200, 200, 0.15))).toBeCloseTo(0.00015, 10); }); it("is null when nothing was priced", () => { - expect(unitPrice({ counter: "someFutureCounter", units: 7, unpriced: 7, cost: null })).toBeNull(); - expect(unitPrice({ counter: "someFutureCounter", units: 7, unpriced: 7, cost: 0 })).toBeNull(); + expect(unitPrice(counterOf("someFutureCounter", 7, 7, null))).toBeNull(); + expect(unitPrice(counterOf("someFutureCounter", 7, 7, 0))).toBeNull(); }); }); @@ -93,7 +98,7 @@ describe("formatUnitPrice", () => { describe("counterMathRow", () => { it("shows units × price = cost for a fully priced counter", () => { - expect(counterMathRow({ counter: "contentPolicyUnits", units: 1000, unpriced: 0, cost: 0.15 })).toEqual({ + expect(counterMathRow(counterOf("contentPolicyUnits", 1000, 0, 0.15))).toEqual({ label: "Content Policy", parts: ["1,000", "× $0.00015", "= $0.1500"], note: null, @@ -101,20 +106,18 @@ describe("counterMathRow", () => { }); it("prices only the priced share and calls out the rest", () => { - expect(counterMathRow({ counter: "sensitiveInformationPolicyUnits", units: 8, unpriced: 2, cost: 0.0006 })).toEqual( - { - label: "Sensitive Information Policy", - parts: ["6", "× $0.0001", "= $0.0006"], - note: "2 unpriced units left out", - }, + expect(counterMathRow(counterOf("sensitiveInformationPolicyUnits", 8, 2, 0.0006))).toEqual({ + label: "Sensitive Information Policy", + parts: ["6", "× $0.0001", "= $0.0006"], + note: "2 unpriced units left out", + }); + expect(counterMathRow(counterOf("sensitiveInformationPolicyUnits", 8, 1, 0.0007)).note).toBe( + "1 unpriced unit left out", ); - expect( - counterMathRow({ counter: "sensitiveInformationPolicyUnits", units: 8, unpriced: 1, cost: 0.0007 }).note, - ).toBe("1 unpriced unit left out"); }); it("says so when a counter has no known price at all", () => { - expect(counterMathRow({ counter: "someFutureCounter", units: 7, unpriced: 7, cost: null })).toEqual({ + expect(counterMathRow(counterOf("someFutureCounter", 7, 7, null))).toEqual({ label: "Some Future Counter", parts: ["7", "× —", "= —"], note: "no known price, left out", @@ -122,11 +125,7 @@ describe("counterMathRow", () => { }); it("shows a free counter as × $0", () => { - expect(counterMathRow({ counter: "wordPolicyUnits", units: 2, unpriced: 0, cost: 0 }).parts).toEqual([ - "2", - "× $0", - "= $0.0000", - ]); + expect(counterMathRow(counterOf("wordPolicyUnits", 2, 0, 0)).parts).toEqual(["2", "× $0", "= $0.0000"]); }); });