mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-27 03:34:10 +00:00
fix: return end user top spend
This commit is contained in:
parent
7f2e12cd10
commit
e643eb11fe
2 changed files with 80 additions and 44 deletions
|
@ -601,7 +601,7 @@ class PrismaClient:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sql_query = """
|
sql_query = """
|
||||||
CREATE VIEW "Last30dTopEndUsersSpend" AS
|
CREATE VIEW "Last30dTopEndUsersSpend" AS
|
||||||
SELECT end_user, SUM(spend) AS total_spend
|
SELECT end_user, COUNT(*) AS total_events, SUM(spend) AS total_spend
|
||||||
FROM "LiteLLM_SpendLogs"
|
FROM "LiteLLM_SpendLogs"
|
||||||
WHERE end_user <> '' AND end_user <> user
|
WHERE end_user <> '' AND end_user <> user
|
||||||
AND "startTime" >= CURRENT_DATE - INTERVAL '30 days'
|
AND "startTime" >= CURRENT_DATE - INTERVAL '30 days'
|
||||||
|
|
|
@ -5,16 +5,19 @@ import {
|
||||||
Subtitle,
|
Subtitle,
|
||||||
Table,
|
Table,
|
||||||
TableHead,
|
TableHead,
|
||||||
|
TableHeaderCell,
|
||||||
TableRow,
|
TableRow,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableBody,
|
TableBody,
|
||||||
Tab,
|
Tab,
|
||||||
TabGroup,
|
TabGroup,
|
||||||
TabList,
|
TabList,
|
||||||
|
TabPanels,
|
||||||
Metric,
|
Metric,
|
||||||
Grid,
|
Grid,
|
||||||
|
TabPanel,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { userInfoCall } from "./networking";
|
import { userInfoCall, adminTopEndUsersCall } from "./networking";
|
||||||
import { Badge, BadgeDelta, Button } from "@tremor/react";
|
import { Badge, BadgeDelta, Button } from "@tremor/react";
|
||||||
import RequestAccess from "./request_model_access";
|
import RequestAccess from "./request_model_access";
|
||||||
import CreateUser from "./create_user_button";
|
import CreateUser from "./create_user_button";
|
||||||
|
@ -33,6 +36,7 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
userID,
|
userID,
|
||||||
}) => {
|
}) => {
|
||||||
const [userData, setUserData] = useState<null | any[]>(null);
|
const [userData, setUserData] = useState<null | any[]>(null);
|
||||||
|
const [endUsers, setEndUsers] = useState<null | any[]>(null);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const defaultPageSize = 25;
|
const defaultPageSize = 25;
|
||||||
|
|
||||||
|
@ -56,9 +60,26 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (accessToken && token && userRole && userID) {
|
if (accessToken && token && userRole && userID && !userData) {
|
||||||
fetchData();
|
fetchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchEndUserSpend = async () => {
|
||||||
|
try {
|
||||||
|
const topEndUsers = await adminTopEndUsersCall(accessToken);
|
||||||
|
console.log("user data response:", topEndUsers);
|
||||||
|
setEndUsers(topEndUsers);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("There was an error fetching the model data", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (
|
||||||
|
userRole &&
|
||||||
|
(userRole == "Admin" || userRole == "Admin Viewer") &&
|
||||||
|
!endUsers
|
||||||
|
) {
|
||||||
|
fetchEndUserSpend();
|
||||||
|
}
|
||||||
}, [accessToken, token, userRole, userID]);
|
}, [accessToken, token, userRole, userID]);
|
||||||
|
|
||||||
if (!userData) {
|
if (!userData) {
|
||||||
|
@ -105,53 +126,68 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
<div style={{ width: "100%" }}>
|
<div style={{ width: "100%" }}>
|
||||||
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
||||||
<CreateUser userID={userID} accessToken={accessToken} />
|
<CreateUser userID={userID} accessToken={accessToken} />
|
||||||
<Card>
|
<Card className="w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4">
|
||||||
<TabGroup>
|
<TabGroup>
|
||||||
<TabList variant="line" defaultValue="1">
|
<TabList variant="line" defaultValue="1">
|
||||||
<Tab value="1">Key Owners</Tab>
|
<Tab value="1">Key Owners</Tab>
|
||||||
<Tab value="2">End-Users</Tab>
|
<Tab value="2">End-Users</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
|
<TabPanels>
|
||||||
|
<TabPanel>
|
||||||
|
<Table className="mt-5">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableHeaderCell>User ID</TableHeaderCell>
|
||||||
|
<TableHeaderCell>User Role</TableHeaderCell>
|
||||||
|
<TableHeaderCell>User Models</TableHeaderCell>
|
||||||
|
<TableHeaderCell>User Spend ($ USD)</TableHeaderCell>
|
||||||
|
<TableHeaderCell>User Max Budget ($ USD)</TableHeaderCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{userData.map((user: any) => (
|
||||||
|
<TableRow key={user.user_id}>
|
||||||
|
<TableCell>{user.user_id}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{user.user_role ? user.user_role : "app_owner"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{user.models && user.models.length > 0
|
||||||
|
? user.models
|
||||||
|
: "All Models"}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{user.spend ? user.spend : 0}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{user.max_budget ? user.max_budget : "Unlimited"}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableHeaderCell>End User</TableHeaderCell>
|
||||||
|
<TableHeaderCell>Spend</TableHeaderCell>
|
||||||
|
<TableHeaderCell>Total Events</TableHeaderCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
|
||||||
|
<TableBody>
|
||||||
|
{endUsers?.map((user: any, index: number) => (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell>{user.end_user}</TableCell>
|
||||||
|
<TableCell>{user.total_spend}</TableCell>
|
||||||
|
<TableCell>{user.total_events}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TabPanel>
|
||||||
|
</TabPanels>
|
||||||
</TabGroup>
|
</TabGroup>
|
||||||
<Table className="mt-5">
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>
|
|
||||||
<Title>User ID </Title>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<Title>User Role</Title>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<Title>User Models</Title>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<Title>User Spend ($ USD)</Title>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<Title>User Max Budget ($ USD)</Title>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{userData.map((user: any) => (
|
|
||||||
<TableRow key={user.user_id}>
|
|
||||||
<TableCell>{user.user_id}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{user.user_role ? user.user_role : "app_owner"}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{user.models && user.models.length > 0
|
|
||||||
? user.models
|
|
||||||
: "All Models"}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>{user.spend ? user.spend : 0}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{user.max_budget ? user.max_budget : "Unlimited"}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</Card>
|
</Card>
|
||||||
{renderPagination()}
|
{renderPagination()}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue