fix(usage.tsx): make separate call for top api keys

This commit is contained in:
Krrish Dholakia 2024-02-28 15:37:48 -08:00
parent f7a2d3faef
commit d9862520bc
3 changed files with 178 additions and 40 deletions

View file

@ -4054,7 +4054,7 @@ async def view_spend_logs(
) )
async def global_spend_logs(): async def global_spend_logs():
""" """
[BETA] This is a beta endpoint. [BETA] This is a beta endpoint. It will change.
Use this to get global spend (spend per day for last 30d). Admin-only endpoint Use this to get global spend (spend per day for last 30d). Admin-only endpoint
@ -4069,6 +4069,61 @@ async def global_spend_logs():
return response return response
@router.get(
"/global/spend/keys",
tags=["Budget & Spend Tracking"],
dependencies=[Depends(user_api_key_auth)],
)
async def global_spend_keys(
limit: int = fastapi.Query(
default=None,
description="Number of keys to get. Will return Top 'n' keys.",
)
):
"""
[BETA] This is a beta endpoint. It will change.
Use this to get the top 'n' keys with the highest spend, ordered by spend.
"""
global prisma_client
if prisma_client is None:
raise HTTPException(status_code=500, detail={"error": "No db connected"})
sql_query = f"""SELECT * FROM "Last30dKeysBySpend" LIMIT {limit};"""
response = await prisma_client.db.query_raw(query=sql_query)
return response
@router.get(
"/global/spend/models",
tags=["Budget & Spend Tracking"],
dependencies=[Depends(user_api_key_auth)],
)
async def global_spend_models(
limit: int = fastapi.Query(
default=None,
description="Number of models to get. Will return Top 'n' models.",
)
):
"""
[BETA] This is a beta endpoint. It will change.
Use this to get the top 'n' keys with the highest spend, ordered by spend.
"""
global prisma_client
if prisma_client is None:
raise HTTPException(status_code=500, detail={"error": "No db connected"})
sql_query = f"""SELECT * FROM "Last30dModelsBySpend" LIMIT {limit};"""
response = await prisma_client.db.query_raw(query=sql_query)
return response
@router.get( @router.get(
"/daily_metrics", "/daily_metrics",
summary="Get daily spend metrics", summary="Get daily spend metrics",
@ -4085,7 +4140,11 @@ async def view_daily_metrics(
description="Time till which to view key spend", description="Time till which to view key spend",
), ),
): ):
""" """ """
[BETA] This is a beta endpoint. It might change without notice.
Please give feedback - https://github.com/BerriAI/litellm/issues
"""
try: try:
if os.getenv("CLICKHOUSE_HOST") is not None: if os.getenv("CLICKHOUSE_HOST") is not None:
# gettting spend logs from clickhouse # gettting spend logs from clickhouse

View file

@ -314,10 +314,6 @@ export const userSpendLogsCall = async (
) => { ) => {
try { try {
console.log(`user role in spend logs call: ${userRole}`); console.log(`user role in spend logs call: ${userRole}`);
if (userRole == "Admin") {
return await adminSpendLogsCall(accessToken);
}
let url = proxyBaseUrl ? `${proxyBaseUrl}/spend/logs` : `/spend/logs`; let url = proxyBaseUrl ? `${proxyBaseUrl}/spend/logs` : `/spend/logs`;
if (userRole == "App Owner") { if (userRole == "App Owner") {
url = `${url}/?user_id=${userID}&start_date=${startTime}&end_date=${endTime}`; url = `${url}/?user_id=${userID}&start_date=${startTime}&end_date=${endTime}`;
@ -378,6 +374,66 @@ export const adminSpendLogsCall = async (accessToken: String) => {
} }
}; };
export const adminTopKeysCall = async (accessToken: String) => {
try {
let url = proxyBaseUrl
? `${proxyBaseUrl}/global/spend/keys?limit=5`
: `/global/spend/keys?limit=5`;
message.info("Making spend keys request");
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const errorData = await response.text();
message.error(errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log(data);
message.success("Spend Logs received");
return data;
} catch (error) {
console.error("Failed to create key:", error);
throw error;
}
};
export const adminTopModelsCall = async (accessToken: String) => {
try {
let url = proxyBaseUrl
? `${proxyBaseUrl}/global/spend/models?limit=5`
: `/global/spend/models?limit=5`;
message.info("Making spend models request");
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const errorData = await response.text();
message.error(errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log(data);
message.success("Spend Logs received");
return data;
} catch (error) {
console.error("Failed to create key:", error);
throw error;
}
};
export const keyInfoCall = async (accessToken: String, keys: String[]) => { export const keyInfoCall = async (accessToken: String, keys: String[]) => {
try { try {
let url = proxyBaseUrl ? `${proxyBaseUrl}/v2/key/info` : `/v2/key/info`; let url = proxyBaseUrl ? `${proxyBaseUrl}/v2/key/info` : `/v2/key/info`;

View file

@ -6,6 +6,8 @@ import {
userSpendLogsCall, userSpendLogsCall,
keyInfoCall, keyInfoCall,
adminSpendLogsCall, adminSpendLogsCall,
adminTopKeysCall,
adminTopModelsCall,
} from "./networking"; } from "./networking";
import { start } from "repl"; import { start } from "repl";
@ -168,6 +170,25 @@ const UsagePage: React.FC<UsagePageProps> = ({
if (accessToken && token && userRole && userID) { if (accessToken && token && userRole && userID) {
const fetchData = async () => { const fetchData = async () => {
try { try {
/**
* If user is Admin - query the global views endpoints
* If user is App Owner - use the normal spend logs call
*/
console.log(`user role: ${userRole}`);
if (userRole == "Admin") {
const overall_spend = await adminSpendLogsCall(accessToken);
setKeySpendData(overall_spend);
const top_keys = await adminTopKeysCall(accessToken);
const filtered_keys = top_keys.map((k: any) => ({
key: (k["key_name"] || k["key_alias"] || k["api_key"]).substring(
0,
7
),
spend: k["total_spend"],
}));
setTopKeys(filtered_keys);
const top_models = await adminTopModelsCall(accessToken);
} else if (userRole == "App Owner") {
await userSpendLogsCall( await userSpendLogsCall(
accessToken, accessToken,
token, token,
@ -186,22 +207,24 @@ const UsagePage: React.FC<UsagePageProps> = ({
let topApiKeys = response.top_api_keys; let topApiKeys = response.top_api_keys;
setTopKeys(topApiKeys); setTopKeys(topApiKeys);
} else { } else {
// const topKeysResponse = await keyInfoCall( const topKeysResponse = await keyInfoCall(
// accessToken, accessToken,
// getTopKeys(response) getTopKeys(response)
// ); );
// const filtered_keys = topKeysResponse["info"].map((k: any) => ({ const filtered_keys = topKeysResponse["info"].map((k: any) => ({
// key: (k["key_name"] || k["key_alias"] || k["token"]).substring( key: (
// 0, k["key_name"] ||
// 7 k["key_alias"] ||
// ), k["token"]
// spend: k["spend"], ).substring(0, 7),
// })); spend: k["spend"],
// setTopKeys(filtered_keys); }));
// setTopUsers(getTopUsers(response)); setTopKeys(filtered_keys);
setTopUsers(getTopUsers(response));
setKeySpendData(response); setKeySpendData(response);
} }
}); });
}
} catch (error) { } catch (error) {
console.error("There was an error fetching the data", error); console.error("There was an error fetching the data", error);
// Optionally, update your UI to reflect the error state here as well // Optionally, update your UI to reflect the error state here as well