forked from phoenix/litellm-mirror
fix(usage.tsx): show key spend per day
This commit is contained in:
parent
43da22ae13
commit
d1d4568dc5
1 changed files with 97 additions and 32 deletions
|
@ -1,9 +1,9 @@
|
||||||
import { BarChart, Card, Title } from "@tremor/react";
|
import { BarChart, Card, Title } from "@tremor/react";
|
||||||
|
|
||||||
import React, { useState, useEffect } from "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 { userSpendLogsCall } from "./networking";
|
||||||
import { AreaChart, Flex, Switch, Subtitle } from "@tremor/react";
|
import { start } from "repl";
|
||||||
|
|
||||||
interface UsagePageProps {
|
interface UsagePageProps {
|
||||||
accessToken: string | null;
|
accessToken: string | null;
|
||||||
|
@ -12,12 +12,65 @@ interface UsagePageProps {
|
||||||
userID: string | null;
|
userID: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataType = {
|
type CustomTooltipTypeBar = {
|
||||||
api_key: string;
|
payload: any;
|
||||||
startTime: string;
|
active: boolean | undefined;
|
||||||
_sum: {
|
label: any;
|
||||||
spend: number;
|
};
|
||||||
};
|
|
||||||
|
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 (
|
||||||
|
<div className="w-56 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown">
|
||||||
|
{date}
|
||||||
|
{topEntries.map(([key, value]) => (
|
||||||
|
<div key={key} className="flex flex-1 space-x-10">
|
||||||
|
<div className="p-2">
|
||||||
|
<p className="text-tremor-content">
|
||||||
|
Token: {key.substring(0, 4)}{" "}
|
||||||
|
<span className="font-medium text-tremor-content-emphasis">
|
||||||
|
Spend: {value}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="w-56 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown">
|
||||||
|
// {payload.map((category: any, idx: number) => {
|
||||||
|
// <div key={idx} className="flex flex-1 space-x-2.5">
|
||||||
|
// <div
|
||||||
|
// className={`flex w-1 flex-col bg-${category.color}-500 rounded`}
|
||||||
|
// />
|
||||||
|
// <div className="space-y-1">
|
||||||
|
// <p className="text-tremor-content">{category.dataKey}</p>
|
||||||
|
// <p className="font-medium text-tremor-content-emphasis">
|
||||||
|
// {category.value} bpm
|
||||||
|
// </p>
|
||||||
|
// </div>
|
||||||
|
// </div>;
|
||||||
|
// })}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
};
|
};
|
||||||
|
|
||||||
const UsagePage: React.FC<UsagePageProps> = ({
|
const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
|
@ -28,6 +81,7 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const [keySpendData, setKeySpendData] = useState<any[]>([]);
|
const [keySpendData, setKeySpendData] = useState<any[]>([]);
|
||||||
|
const [keyCategories, setKeyCategories] = useState<string[]>([]);
|
||||||
|
|
||||||
const firstDay = new Date(
|
const firstDay = new Date(
|
||||||
currentDate.getFullYear(),
|
currentDate.getFullYear(),
|
||||||
|
@ -63,32 +117,42 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (accessToken && token && userRole && userID) {
|
if (accessToken && token && userRole && userID) {
|
||||||
const cachedKeySpendData = localStorage.getItem("keySpendData");
|
const fetchData = async () => {
|
||||||
if (cachedKeySpendData) {
|
try {
|
||||||
setKeySpendData(JSON.parse(cachedKeySpendData));
|
const response = await userSpendLogsCall(
|
||||||
} else {
|
accessToken,
|
||||||
const fetchData = async () => {
|
token,
|
||||||
try {
|
userRole,
|
||||||
const response = await userSpendLogsCall(
|
userID,
|
||||||
accessToken,
|
startTime,
|
||||||
token,
|
endTime
|
||||||
userRole,
|
);
|
||||||
userID,
|
|
||||||
startTime,
|
const uniqueKeys: Set<string> = new Set();
|
||||||
endTime
|
|
||||||
);
|
response.forEach((item: any) => {
|
||||||
setKeySpendData(response);
|
Object.keys(item).forEach((key) => {
|
||||||
localStorage.setItem("keySpendData", JSON.stringify(response));
|
if (key !== "spend" && key !== "startTime") {
|
||||||
} catch (error) {
|
uniqueKeys.add(key);
|
||||||
console.error("There was an error fetching the data", error);
|
}
|
||||||
// Optionally, update your UI to reflect the error state here as well
|
});
|
||||||
}
|
});
|
||||||
};
|
let uniqueKeysList = Array.from(uniqueKeys);
|
||||||
fetchData();
|
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]);
|
}, [accessToken, token, userRole, userID]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "100%" }}>
|
<div style={{ width: "100%" }}>
|
||||||
<Grid numItems={1} className="gap-0 p-10 h-[75vh] w-full">
|
<Grid numItems={1} className="gap-0 p-10 h-[75vh] w-full">
|
||||||
|
@ -103,6 +167,7 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
valueFormatter={valueFormatter}
|
valueFormatter={valueFormatter}
|
||||||
yAxisWidth={100}
|
yAxisWidth={100}
|
||||||
tickGap={5}
|
tickGap={5}
|
||||||
|
customTooltip={customTooltip}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue