diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index b2cc68776e..ce4de2d146 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -260,6 +260,10 @@ class NewTeamRequest(LiteLLMBase): models: list = [] +class GlobalEndUsersSpend(LiteLLMBase): + api_key: Optional[str] = None + + class TeamMemberAddRequest(LiteLLMBase): team_id: str member: Member diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index ecc689c7d3..1b33c7efd8 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -4146,7 +4146,7 @@ async def global_spend_keys( tags=["Budget & Spend Tracking"], dependencies=[Depends(user_api_key_auth)], ) -async def global_spend_end_users(): +async def global_spend_end_users(data: GlobalEndUsersSpend): """ [BETA] This is a beta endpoint. It will change. @@ -4156,9 +4156,26 @@ async def global_spend_end_users(): if prisma_client is None: raise HTTPException(status_code=500, detail={"error": "No db connected"}) - sql_query = f"""SELECT * FROM "Last30dTopEndUsersSpend";""" - response = await prisma_client.db.query_raw(query=sql_query) + if data.api_key is None: + sql_query = f"""SELECT * FROM "Last30dTopEndUsersSpend";""" + + response = await prisma_client.db.query_raw(query=sql_query) + else: + """ + Gets the top 100 end-users for a given api key + """ + current_date = datetime.now() + past_date = current_date - timedelta(days=30) + response = await prisma_client.db.litellm_spendlogs.group_by( # type: ignore + by=["end_user"], + where={ + "AND": [{"startTime": {"gte": past_date}}, {"api_key": data.api_key}] + }, + sum={"spend": True}, + order={"_sum": {"spend": "desc"}}, # type: ignore + take=100, + ) return response diff --git a/ui/litellm-dashboard/src/components/view_users.tsx b/ui/litellm-dashboard/src/components/view_users.tsx index 00329e206e..5b2b5f6def 100644 --- a/ui/litellm-dashboard/src/components/view_users.tsx +++ b/ui/litellm-dashboard/src/components/view_users.tsx @@ -10,17 +10,21 @@ import { TableCell, TableBody, Tab, + Text, TabGroup, TabList, TabPanels, Metric, Grid, TabPanel, + Select, + SelectItem, } from "@tremor/react"; import { userInfoCall, adminTopEndUsersCall } from "./networking"; import { Badge, BadgeDelta, Button } from "@tremor/react"; import RequestAccess from "./request_model_access"; import CreateUser from "./create_user_button"; +import Paragraph from "antd/es/skeleton/Paragraph"; interface ViewUserDashboardProps { accessToken: string | null; @@ -166,6 +170,17 @@ const ViewUserDashboard: React.FC = ({ +
+
+
+ Key + +
+