diff --git a/litellm/proxy/_lazy_openapi_snapshot.json b/litellm/proxy/_lazy_openapi_snapshot.json index 71dbf0da239..d1f58f09b91 100644 --- a/litellm/proxy/_lazy_openapi_snapshot.json +++ b/litellm/proxy/_lazy_openapi_snapshot.json @@ -3095,6 +3095,18 @@ "title": "Has More", "type": "boolean" }, + "next_cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Opaque cursor for the next page of api_keys; None when every key is loaded", + "title": "Next Cursor" + }, "page": { "default": 1, "title": "Page", diff --git a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx index 4ae73c28823..8277cd2df1f 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/EntityUsage/EntityUsage.tsx @@ -168,13 +168,15 @@ const EntityUsage: React.FC = ({ const spendData = loadedPages?.base === spendDataBase ? loadedPages.merged : spendDataBase; const apiKeyTruncation = getApiKeyTruncation(spendData.metadata?.api_key_limit, spendData.metadata?.total_api_keys); + const keyPageWindow = + accessToken && startTime && endTime ? { accessToken, startTime, endTime } : null; const loadMoreKeys = - aggregatedFetchFn && accessToken && startTime && endTime && spendData.metadata?.next_cursor + aggregatedFetchFn && keyPageWindow && spendData.metadata?.next_cursor ? () => teamDailyActivityAggregatedCall( - accessToken, - startTime, - endTime, + keyPageWindow.accessToken, + keyPageWindow.startTime, + keyPageWindow.endTime, Array.isArray(entityFilterArg) ? entityFilterArg : null, spendData.metadata?.next_cursor ?? null, ).then((page: EntitySpendData) => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsagePageView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsagePageView.tsx index c8f08c3918a..3cb4a361e77 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsagePageView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsagePageView.tsx @@ -440,13 +440,17 @@ const UsagePage: React.FC = ({ teams, organizations }) => { ); const keyMetrics = useMemo(() => processActivityData(userSpendData, "api_keys", teams), [userSpendData, teams]); const aggregatedCursor = activeAggregated?.metadata?.next_cursor; + const keyPageWindow = useMemo( + () => (accessToken && startTime && endTime ? { accessToken, startTime, endTime } : null), + [accessToken, startTime, endTime], + ); const loadMoreKeys = useCallback(() => { - if (!accessToken || !startTime || !endTime || !aggregatedCursor) return Promise.resolve(); + if (!keyPageWindow || !aggregatedCursor) return Promise.resolve(); const rangeKey = currentAggregatedRangeKey; return userDailyActivityAggregatedCall( - accessToken, - startTime, - endTime, + keyPageWindow.accessToken, + keyPageWindow.startTime, + keyPageWindow.endTime, effectiveUserId, false, null, @@ -456,7 +460,7 @@ const UsagePage: React.FC = ({ teams, organizations }) => { prev && prev.rangeKey === rangeKey ? { rangeKey, value: mergeKeyPage(prev.value, page) } : prev, ); }); - }, [accessToken, startTime, endTime, effectiveUserId, aggregatedCursor, currentAggregatedRangeKey]); + }, [keyPageWindow, effectiveUserId, aggregatedCursor, currentAggregatedRangeKey]); const searchKeys = useCallback( (q: string) => { if (!accessToken || !startTime || !endTime) return Promise.resolve({});