forked from phoenix/litellm-mirror
Merge pull request #3624 from BerriAI/litellm_ui_cleanup_2
[UI] Filter Tag Spend by Date + Show Bar Chart
This commit is contained in:
commit
067749805b
5 changed files with 73 additions and 43 deletions
|
@ -1,6 +1,7 @@
|
||||||
# Enterprise Proxy Util Endpoints
|
# Enterprise Proxy Util Endpoints
|
||||||
from litellm._logging import verbose_logger
|
from litellm._logging import verbose_logger
|
||||||
import collections
|
import collections
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
async def get_spend_by_tags(start_date=None, end_date=None, prisma_client=None):
|
async def get_spend_by_tags(start_date=None, end_date=None, prisma_client=None):
|
||||||
|
@ -18,19 +19,26 @@ async def get_spend_by_tags(start_date=None, end_date=None, prisma_client=None):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
async def ui_get_spend_by_tags(start_date=None, end_date=None, prisma_client=None):
|
async def ui_get_spend_by_tags(start_date: str, end_date: str, prisma_client):
|
||||||
response = await prisma_client.db.query_raw(
|
|
||||||
"""
|
sql_query = """
|
||||||
SELECT
|
SELECT
|
||||||
jsonb_array_elements_text(request_tags) AS individual_request_tag,
|
jsonb_array_elements_text(request_tags) AS individual_request_tag,
|
||||||
DATE(s."startTime") AS spend_date,
|
DATE(s."startTime") AS spend_date,
|
||||||
COUNT(*) AS log_count,
|
COUNT(*) AS log_count,
|
||||||
SUM(spend) AS total_spend
|
SUM(spend) AS total_spend
|
||||||
FROM "LiteLLM_SpendLogs" s
|
FROM "LiteLLM_SpendLogs" s
|
||||||
WHERE s."startTime" >= current_date - interval '30 days'
|
WHERE
|
||||||
|
DATE(s."startTime") >= $1::date
|
||||||
|
AND DATE(s."startTime") <= $2::date
|
||||||
GROUP BY individual_request_tag, spend_date
|
GROUP BY individual_request_tag, spend_date
|
||||||
ORDER BY spend_date;
|
ORDER BY spend_date
|
||||||
"""
|
LIMIT 100;
|
||||||
|
"""
|
||||||
|
response = await prisma_client.db.query_raw(
|
||||||
|
sql_query,
|
||||||
|
start_date,
|
||||||
|
end_date,
|
||||||
)
|
)
|
||||||
|
|
||||||
# print("tags - spend")
|
# print("tags - spend")
|
||||||
|
@ -49,15 +57,18 @@ async def ui_get_spend_by_tags(start_date=None, end_date=None, prisma_client=Non
|
||||||
# convert to ui format
|
# convert to ui format
|
||||||
ui_tags = []
|
ui_tags = []
|
||||||
for tag in sorted_tags:
|
for tag in sorted_tags:
|
||||||
|
current_spend = tag[1]
|
||||||
|
if current_spend is not None and isinstance(current_spend, float):
|
||||||
|
current_spend = round(current_spend, 4)
|
||||||
ui_tags.append(
|
ui_tags.append(
|
||||||
{
|
{
|
||||||
"name": tag[0],
|
"name": tag[0],
|
||||||
"value": tag[1],
|
"spend": current_spend,
|
||||||
"log_count": total_requests_per_tag[tag[0]],
|
"log_count": total_requests_per_tag[tag[0]],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return {"top_10_tags": ui_tags}
|
return {"spend_per_tag": ui_tags}
|
||||||
|
|
||||||
|
|
||||||
async def view_spend_logs_from_clickhouse(
|
async def view_spend_logs_from_clickhouse(
|
||||||
|
|
|
@ -5563,6 +5563,13 @@ async def global_view_spend_tags(
|
||||||
f"Database not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keys"
|
f"Database not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if end_date is None or start_date is None:
|
||||||
|
raise ProxyException(
|
||||||
|
message="Please provide start_date and end_date",
|
||||||
|
type="bad_request",
|
||||||
|
param=None,
|
||||||
|
code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
response = await ui_get_spend_by_tags(
|
response = await ui_get_spend_by_tags(
|
||||||
start_date=start_date, end_date=end_date, prisma_client=prisma_client
|
start_date=start_date, end_date=end_date, prisma_client=prisma_client
|
||||||
)
|
)
|
||||||
|
|
|
@ -655,11 +655,20 @@ export const teamSpendLogsCall = async (accessToken: String) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const tagsSpendLogsCall = async (accessToken: String) => {
|
export const tagsSpendLogsCall = async (
|
||||||
|
accessToken: String,
|
||||||
|
startTime: String | undefined,
|
||||||
|
endTime: String | undefined
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const url = proxyBaseUrl
|
let url = proxyBaseUrl
|
||||||
? `${proxyBaseUrl}/global/spend/tags`
|
? `${proxyBaseUrl}/global/spend/tags`
|
||||||
: `/global/spend/tags`;
|
: `/global/spend/tags`;
|
||||||
|
|
||||||
|
if (startTime && endTime) {
|
||||||
|
url = `${url}?start_date=${startTime}&end_date=${endTime}`
|
||||||
|
}
|
||||||
|
|
||||||
console.log("in tagsSpendLogsCall:", url);
|
console.log("in tagsSpendLogsCall:", url);
|
||||||
const response = await fetch(`${url}`, {
|
const response = await fetch(`${url}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
@ -129,7 +129,7 @@ const Team: React.FC<TeamProps> = ({
|
||||||
name="team_alias"
|
name="team_alias"
|
||||||
rules={[{ required: true, message: "Please input a team name" }]}
|
rules={[{ required: true, message: "Please input a team name" }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<TextInput />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="Models" name="models">
|
<Form.Item label="Models" name="models">
|
||||||
<Select2
|
<Select2
|
||||||
|
|
|
@ -153,6 +153,19 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
console.log("End user data updated successfully", newTopUserData);
|
console.log("End user data updated successfully", newTopUserData);
|
||||||
setTopUsers(newTopUserData);
|
setTopUsers(newTopUserData);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateTagSpendData = async (startTime: Date | undefined, endTime: Date | undefined) => {
|
||||||
|
if (!startTime || !endTime || !accessToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let top_tags = await tagsSpendLogsCall(accessToken, startTime.toISOString(), endTime.toISOString());
|
||||||
|
setTopTagsData(top_tags.spend_per_tag);
|
||||||
|
console.log("Tag spend data updated successfully");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(date: Date) {
|
function formatDate(date: Date) {
|
||||||
|
@ -218,8 +231,8 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
setTotalSpendPerTeam(total_spend_per_team);
|
setTotalSpendPerTeam(total_spend_per_team);
|
||||||
|
|
||||||
//get top tags
|
//get top tags
|
||||||
const top_tags = await tagsSpendLogsCall(accessToken);
|
const top_tags = await tagsSpendLogsCall(accessToken, dateValue.from?.toISOString(), dateValue.to?.toISOString());
|
||||||
setTopTagsData(top_tags.top_10_tags);
|
setTopTagsData(top_tags.spend_per_tag);
|
||||||
|
|
||||||
// get spend per end-user
|
// get spend per end-user
|
||||||
let spend_user_call = await adminTopEndUsersCall(accessToken, null, undefined, undefined);
|
let spend_user_call = await adminTopEndUsersCall(accessToken, null, undefined, undefined);
|
||||||
|
@ -459,38 +472,28 @@ const UsagePage: React.FC<UsagePageProps> = ({
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<Grid numItems={2} className="gap-2 h-[75vh] w-full mb-4">
|
<Grid numItems={2} className="gap-2 h-[75vh] w-full mb-4">
|
||||||
<Col numColSpan={2}>
|
<Col numColSpan={2}>
|
||||||
|
<DateRangePicker
|
||||||
|
className="mb-4"
|
||||||
|
enableSelect={true}
|
||||||
|
value={dateValue}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setDateValue(value);
|
||||||
|
updateTagSpendData(value.from, value.to); // Call updateModelMetrics with the new date range
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<Title>Spend Per Tag - Last 30 Days</Title>
|
<Title>Spend Per Tag</Title>
|
||||||
<Text>Get Started Tracking cost per tag <a href="https://docs.litellm.ai/docs/proxy/enterprise#tracking-spend-for-custom-tags" target="_blank">here</a></Text>
|
<Text>Get Started Tracking cost per tag <a className="text-blue-500" href="https://docs.litellm.ai/docs/proxy/enterprise#tracking-spend-for-custom-tags" target="_blank">here</a></Text>
|
||||||
<Table>
|
<BarChart
|
||||||
<TableHead>
|
className="h-72"
|
||||||
<TableRow>
|
data={topTagsData}
|
||||||
<TableHeaderCell>Tag</TableHeaderCell>
|
index="name"
|
||||||
<TableHeaderCell>Spend</TableHeaderCell>
|
categories={["spend"]}
|
||||||
<TableHeaderCell>Requests</TableHeaderCell>
|
colors={["blue"]}
|
||||||
</TableRow>
|
>
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
</BarChart>
|
||||||
{topTagsData.map((tag) => (
|
|
||||||
<TableRow key={tag.name}>
|
|
||||||
<TableCell>{tag.name}</TableCell>
|
|
||||||
<TableCell>{tag.value}</TableCell>
|
|
||||||
<TableCell>{tag.log_count}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
{/* <BarChart
|
|
||||||
className="h-72"
|
|
||||||
data={teamSpendData}
|
|
||||||
showLegend={true}
|
|
||||||
index="date"
|
|
||||||
categories={uniqueTeamIds}
|
|
||||||
yAxisWidth={80}
|
|
||||||
|
|
||||||
stack={true}
|
|
||||||
/> */}
|
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col numColSpan={2}>
|
<Col numColSpan={2}>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue