diff --git a/ui/litellm-dashboard/src/components/usage.tsx b/ui/litellm-dashboard/src/components/usage.tsx index 5908ef10d..221fbdda3 100644 --- a/ui/litellm-dashboard/src/components/usage.tsx +++ b/ui/litellm-dashboard/src/components/usage.tsx @@ -1,9 +1,9 @@ import { BarChart, Card, Title } from "@tremor/react"; import React, { useState, useEffect } from "react"; -import { Grid, Col, Text } from "@tremor/react"; +import { Grid, Col, Text, LineChart } from "@tremor/react"; import { userSpendLogsCall } from "./networking"; -import { AreaChart, Flex, Switch, Subtitle } from "@tremor/react"; +import { start } from "repl"; interface UsagePageProps { accessToken: string | null; @@ -12,12 +12,65 @@ interface UsagePageProps { userID: string | null; } -type DataType = { - api_key: string; - startTime: string; - _sum: { - spend: number; - }; +type CustomTooltipTypeBar = { + payload: any; + active: boolean | undefined; + label: any; +}; + +const customTooltip = (props: CustomTooltipTypeBar) => { + const { payload, active } = props; + if (!active || !payload) return null; + + const value = payload[0].payload; + const date = value["startTime"]; + + // Convert the object into an array of key-value pairs + const entries: [string, number][] = Object.entries(value) + .filter(([key]) => key !== "spend" && key !== "startTime") + .map(([key, value]) => [key, value as number]); // Type assertion to specify the value as number + + // Sort the array based on the float value in descending order + entries.sort((a, b) => b[1] - a[1]); + + // Get the top 5 key-value pairs + const topEntries = entries.slice(0, 5); + + return ( +
+ {date} + {topEntries.map(([key, value]) => ( +
+
+

+ Token: {key.substring(0, 4)}{" "} + + Spend: {value} + +

+
+
+ ))} +
+ ); + + // return ( + //
+ // {payload.map((category: any, idx: number) => { + //
+ //
+ //
+ //

{category.dataKey}

+ //

+ // {category.value} bpm + //

+ //
+ //
; + // })} + //
+ // ); }; const UsagePage: React.FC = ({ @@ -28,6 +81,7 @@ const UsagePage: React.FC = ({ }) => { const currentDate = new Date(); const [keySpendData, setKeySpendData] = useState([]); + const [keyCategories, setKeyCategories] = useState([]); const firstDay = new Date( currentDate.getFullYear(), @@ -63,32 +117,42 @@ const UsagePage: React.FC = ({ useEffect(() => { if (accessToken && token && userRole && userID) { - const cachedKeySpendData = localStorage.getItem("keySpendData"); - if (cachedKeySpendData) { - setKeySpendData(JSON.parse(cachedKeySpendData)); - } else { - const fetchData = async () => { - try { - const response = await userSpendLogsCall( - accessToken, - token, - userRole, - userID, - startTime, - endTime - ); - setKeySpendData(response); - localStorage.setItem("keySpendData", JSON.stringify(response)); - } catch (error) { - console.error("There was an error fetching the data", error); - // Optionally, update your UI to reflect the error state here as well - } - }; - fetchData(); - } + const fetchData = async () => { + try { + const response = await userSpendLogsCall( + accessToken, + token, + userRole, + userID, + startTime, + endTime + ); + + const uniqueKeys: Set = new Set(); + + response.forEach((item: any) => { + Object.keys(item).forEach((key) => { + if (key !== "spend" && key !== "startTime") { + uniqueKeys.add(key); + } + }); + }); + let uniqueKeysList = Array.from(uniqueKeys); + setKeyCategories(uniqueKeysList); + setKeySpendData(response); + // localStorage.setItem("keySpendData", JSON.stringify(response)); + // localStorage.setItem( + // "keyCategories", + // JSON.stringify(uniqueKeysList) + // ); + } catch (error) { + console.error("There was an error fetching the data", error); + // Optionally, update your UI to reflect the error state here as well + } + }; + fetchData(); } }, [accessToken, token, userRole, userID]); - return (
@@ -103,6 +167,7 @@ const UsagePage: React.FC = ({ valueFormatter={valueFormatter} yAxisWidth={100} tickGap={5} + customTooltip={customTooltip} />