From c3fd70a4b01b0664b67ce3f087ce82c78ef18ed9 Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Mon, 9 Mar 2026 13:48:32 -0700 Subject: [PATCH 1/4] feat: usage page components to view the input/output tokens and cache read/write tokens --- .../UsagePage/components/UsagePageView.tsx | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx index 8b0d5ffac0..60d10bde08 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx @@ -404,6 +404,10 @@ const UsagePage: React.FC = ({ teams, organizations }) => { aggregatedMetadata.total_successful_requests += pageData.metadata.total_successful_requests || 0; aggregatedMetadata.total_failed_requests += pageData.metadata.total_failed_requests || 0; aggregatedMetadata.total_tokens += pageData.metadata.total_tokens || 0; + aggregatedMetadata.total_prompt_tokens += pageData.metadata.total_prompt_tokens || 0; + aggregatedMetadata.total_completion_tokens += pageData.metadata.total_completion_tokens || 0; + aggregatedMetadata.total_cache_read_input_tokens += pageData.metadata.total_cache_read_input_tokens || 0; + aggregatedMetadata.total_cache_creation_input_tokens += pageData.metadata.total_cache_creation_input_tokens || 0; } } @@ -646,6 +650,38 @@ const UsagePage: React.FC = ({ teams, organizations }) => { + + + Token Breakdown + + + Input Tokens + + {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} + + + + Output Tokens + + {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} + + + + Cache Read Tokens + + {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} + + + + Cache Write Tokens + + {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} + + + + + + {/* Daily Spend Chart */} From af7609d856d51fe589b3f57764636185bab39d67 Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Mon, 9 Mar 2026 14:06:53 -0700 Subject: [PATCH 2/4] fix: putting new cards in the same place as the current ones, fixing spacing --- .../UsagePage/components/UsagePageView.tsx | 72 ++++++++++--------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx index 60d10bde08..1de28e3de3 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx @@ -630,12 +630,6 @@ const UsagePage: React.FC = ({ teams, organizations }) => { {userSpendData.metadata?.total_failed_requests?.toLocaleString() || 0} - - Total Tokens - - {userSpendData.metadata?.total_tokens?.toLocaleString() || 0} - - Average Cost per Request @@ -646,39 +640,47 @@ const UsagePage: React.FC = ({ teams, organizations }) => { )} - - - - - - - Token Breakdown - - Input Tokens - - {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} - - - - Output Tokens - - {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} - - - - Cache Read Tokens - - {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} - - - - Cache Write Tokens - - {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} + Total Tokens + + {userSpendData.metadata?.total_tokens?.toLocaleString() || 0} +
+
+ + Input Tokens + + {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} + + +
+
+ + Output Tokens + + {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} + + +
+
+ + Cache Read Tokens + + {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} + + +
+
+ + Cache Write Tokens + + {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} + + +
+
From 7e1c860ffe509f6ffe190d03e9261ef1c8fd3db3 Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Wed, 11 Mar 2026 16:52:25 -0700 Subject: [PATCH 3/4] fix: make token breakdown cards click-to-expand on Total Tokens card --- .../components/UsagePageView.test.tsx | 2 + .../UsagePage/components/UsagePageView.tsx | 85 +++++++++++-------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.test.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.test.tsx index 410d751017..b9fe1687e6 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.test.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.test.tsx @@ -249,6 +249,8 @@ vi.mock("@ant-design/icons", async () => { CalendarOutlined: Icon, InfoCircleOutlined: Icon, UserOutlined: Icon, + DownOutlined: Icon, + RightOutlined: Icon, LoadingOutlined, }; }); diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx index 1de28e3de3..9f3fec67aa 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx @@ -6,7 +6,7 @@ * Works at 1m+ spend logs, by querying an aggregate table instead. */ -import { InfoCircleOutlined, LoadingOutlined } from "@ant-design/icons"; +import { DownOutlined, InfoCircleOutlined, LoadingOutlined, RightOutlined } from "@ant-design/icons"; import { BarChart, Card, @@ -148,6 +148,7 @@ const UsagePage: React.FC = ({ teams, organizations }) => { const [showCredentialBanner, setShowCredentialBanner] = useState(true); const [topKeysLimit, setTopKeysLimit] = useState(5); const [topModelsLimit, setTopModelsLimit] = useState(5); + const [showTokenBreakdown, setShowTokenBreakdown] = useState(false); const getAllTags = async () => { if (!accessToken) { return; @@ -640,47 +641,59 @@ const UsagePage: React.FC = ({ teams, organizations }) => { )} - - Total Tokens + setShowTokenBreakdown(!showTokenBreakdown)} + > +
+ Total Tokens + {showTokenBreakdown ? ( + + ) : ( + + )} +
{userSpendData.metadata?.total_tokens?.toLocaleString() || 0}
-
-
- - Input Tokens - - {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} - - + {showTokenBreakdown && ( +
+
+ + Input Tokens + + {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} + + +
+
+ + Output Tokens + + {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} + + +
+
+ + Cache Read Tokens + + {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} + + +
+
+ + Cache Write Tokens + + {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} + + +
-
- - Output Tokens - - {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} - - -
-
- - Cache Read Tokens - - {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} - - -
-
- - Cache Write Tokens - - {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} - - -
-
+ )} From 62343b477c8cf9bec6c7d6e0eb7ea4fdb685953d Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Wed, 11 Mar 2026 17:20:38 -0700 Subject: [PATCH 4/4] fix: use Grid layout for token cards and guard against NaN in paginated aggregation --- .../UsagePage/components/UsagePageView.tsx | 78 +++++++++---------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx index 9f3fec67aa..62088983bc 100644 --- a/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx +++ b/ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx @@ -400,15 +400,15 @@ const UsagePage: React.FC = ({ teams, organizations }) => { const pageData = await userDailyActivityCall(accessToken, startTime, endTime, page, effectiveUserId); allResults.push(...pageData.results); if (pageData.metadata) { - aggregatedMetadata.total_spend += pageData.metadata.total_spend || 0; - aggregatedMetadata.total_api_requests += pageData.metadata.total_api_requests || 0; - aggregatedMetadata.total_successful_requests += pageData.metadata.total_successful_requests || 0; - aggregatedMetadata.total_failed_requests += pageData.metadata.total_failed_requests || 0; - aggregatedMetadata.total_tokens += pageData.metadata.total_tokens || 0; - aggregatedMetadata.total_prompt_tokens += pageData.metadata.total_prompt_tokens || 0; - aggregatedMetadata.total_completion_tokens += pageData.metadata.total_completion_tokens || 0; - aggregatedMetadata.total_cache_read_input_tokens += pageData.metadata.total_cache_read_input_tokens || 0; - aggregatedMetadata.total_cache_creation_input_tokens += pageData.metadata.total_cache_creation_input_tokens || 0; + aggregatedMetadata.total_spend = (aggregatedMetadata.total_spend || 0) + (pageData.metadata.total_spend || 0); + aggregatedMetadata.total_api_requests = (aggregatedMetadata.total_api_requests || 0) + (pageData.metadata.total_api_requests || 0); + aggregatedMetadata.total_successful_requests = (aggregatedMetadata.total_successful_requests || 0) + (pageData.metadata.total_successful_requests || 0); + aggregatedMetadata.total_failed_requests = (aggregatedMetadata.total_failed_requests || 0) + (pageData.metadata.total_failed_requests || 0); + aggregatedMetadata.total_tokens = (aggregatedMetadata.total_tokens || 0) + (pageData.metadata.total_tokens || 0); + aggregatedMetadata.total_prompt_tokens = (aggregatedMetadata.total_prompt_tokens || 0) + (pageData.metadata.total_prompt_tokens || 0); + aggregatedMetadata.total_completion_tokens = (aggregatedMetadata.total_completion_tokens || 0) + (pageData.metadata.total_completion_tokens || 0); + aggregatedMetadata.total_cache_read_input_tokens = (aggregatedMetadata.total_cache_read_input_tokens || 0) + (pageData.metadata.total_cache_read_input_tokens || 0); + aggregatedMetadata.total_cache_creation_input_tokens = (aggregatedMetadata.total_cache_creation_input_tokens || 0) + (pageData.metadata.total_cache_creation_input_tokens || 0); } } @@ -659,40 +659,32 @@ const UsagePage: React.FC = ({ teams, organizations }) => { {showTokenBreakdown && ( -
-
- - Input Tokens - - {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} - - -
-
- - Output Tokens - - {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} - - -
-
- - Cache Read Tokens - - {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} - - -
-
- - Cache Write Tokens - - {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} - - -
-
+ + + Input Tokens + + {userSpendData.metadata?.total_prompt_tokens?.toLocaleString() || 0} + + + + Output Tokens + + {userSpendData.metadata?.total_completion_tokens?.toLocaleString() || 0} + + + + Cache Read Tokens + + {userSpendData.metadata?.total_cache_read_input_tokens?.toLocaleString() || 0} + + + + Cache Write Tokens + + {userSpendData.metadata?.total_cache_creation_input_tokens?.toLocaleString() || 0} + + + )}