mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-25 10:44:24 +00:00
UI (new_usage.tsx): Report 'total_tokens' + report success/failure calls (#9675)
* feat(internal_user_endpoints.py): return 'total_tokens' in `/user/daily/analytics` * test(test_internal_user_endpoints.py): add unit test to assert spend metrics and dailyspend metadata always report the same fields * build(schema.prisma): record success + failure calls to daily user table allows understanding why model requests might exceed provider requests (e.g. user hit rate limit error) * fix(internal_user_endpoints.py): report success / failure requests in API * fix(proxy/utils.py): default to success status can be missing or none at times for successful requests * feat(new_usage.tsx): show success/failure calls on UI * style(new_usage.tsx): ui cleanup * fix: fix linting error * fix: fix linting error * feat(litellm-proxy-extras/): add new migration files
This commit is contained in:
parent
f2a7edaddc
commit
62ad84fb64
16 changed files with 240 additions and 137 deletions
|
@ -10,7 +10,17 @@ import traceback
|
|||
from datetime import datetime, timedelta
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Union, overload
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Literal,
|
||||
Optional,
|
||||
Union,
|
||||
cast,
|
||||
overload,
|
||||
)
|
||||
|
||||
from litellm.proxy._types import (
|
||||
DB_CONNECTION_ERROR_TYPES,
|
||||
|
@ -18,6 +28,7 @@ from litellm.proxy._types import (
|
|||
DailyUserSpendTransaction,
|
||||
ProxyErrorTypes,
|
||||
ProxyException,
|
||||
SpendLogsMetadata,
|
||||
SpendLogsPayload,
|
||||
)
|
||||
from litellm.types.guardrails import GuardrailEventHooks
|
||||
|
@ -1145,6 +1156,41 @@ class PrismaClient:
|
|||
) # Client to connect to Prisma db
|
||||
verbose_proxy_logger.debug("Success - Created Prisma Client")
|
||||
|
||||
def get_request_status(
|
||||
self, payload: Union[dict, SpendLogsPayload]
|
||||
) -> Literal["success", "failure"]:
|
||||
"""
|
||||
Determine if a request was successful or failed based on payload metadata.
|
||||
|
||||
Args:
|
||||
payload (Union[dict, SpendLogsPayload]): Request payload containing metadata
|
||||
|
||||
Returns:
|
||||
Literal["success", "failure"]: Request status
|
||||
"""
|
||||
try:
|
||||
# Get metadata and convert to dict if it's a JSON string
|
||||
payload_metadata: Union[Dict, SpendLogsMetadata, str] = payload.get(
|
||||
"metadata", {}
|
||||
)
|
||||
if isinstance(payload_metadata, str):
|
||||
payload_metadata_json: Union[Dict, SpendLogsMetadata] = cast(
|
||||
Dict, json.loads(payload_metadata)
|
||||
)
|
||||
else:
|
||||
payload_metadata_json = payload_metadata
|
||||
|
||||
# Check status in metadata dict
|
||||
return (
|
||||
"failure"
|
||||
if payload_metadata_json.get("status") == "failure"
|
||||
else "success"
|
||||
)
|
||||
|
||||
except (json.JSONDecodeError, AttributeError):
|
||||
# Default to success if metadata parsing fails
|
||||
return "success"
|
||||
|
||||
def add_spend_log_transaction_to_daily_user_transaction(
|
||||
self, payload: Union[dict, SpendLogsPayload]
|
||||
):
|
||||
|
@ -1156,12 +1202,15 @@ class PrismaClient:
|
|||
If key exists, update the transaction with the new spend and usage
|
||||
"""
|
||||
expected_keys = ["user", "startTime", "api_key", "model", "custom_llm_provider"]
|
||||
|
||||
if not all(key in payload for key in expected_keys):
|
||||
verbose_proxy_logger.debug(
|
||||
f"Missing expected keys: {expected_keys}, in payload, skipping from daily_user_spend_transactions"
|
||||
)
|
||||
return
|
||||
|
||||
request_status = self.get_request_status(payload)
|
||||
verbose_proxy_logger.info(f"Logged request status: {request_status}")
|
||||
if isinstance(payload["startTime"], datetime):
|
||||
start_time = payload["startTime"].isoformat()
|
||||
date = start_time.split("T")[0]
|
||||
|
@ -1174,6 +1223,7 @@ class PrismaClient:
|
|||
return
|
||||
try:
|
||||
daily_transaction_key = f"{payload['user']}_{date}_{payload['api_key']}_{payload['model']}_{payload['custom_llm_provider']}"
|
||||
|
||||
if daily_transaction_key in self.daily_user_spend_transactions:
|
||||
daily_transaction = self.daily_user_spend_transactions[
|
||||
daily_transaction_key
|
||||
|
@ -1182,6 +1232,11 @@ class PrismaClient:
|
|||
daily_transaction["prompt_tokens"] += payload["prompt_tokens"]
|
||||
daily_transaction["completion_tokens"] += payload["completion_tokens"]
|
||||
daily_transaction["api_requests"] += 1
|
||||
|
||||
if request_status == "success":
|
||||
daily_transaction["successful_requests"] += 1
|
||||
else:
|
||||
daily_transaction["failed_requests"] += 1
|
||||
else:
|
||||
daily_transaction = DailyUserSpendTransaction(
|
||||
user_id=payload["user"],
|
||||
|
@ -1194,6 +1249,8 @@ class PrismaClient:
|
|||
completion_tokens=payload["completion_tokens"],
|
||||
spend=payload["spend"],
|
||||
api_requests=1,
|
||||
successful_requests=1 if request_status == "success" else 0,
|
||||
failed_requests=1 if request_status != "success" else 0,
|
||||
)
|
||||
|
||||
self.daily_user_spend_transactions[
|
||||
|
@ -2603,6 +2660,12 @@ class ProxyUpdateSpend:
|
|||
],
|
||||
"spend": transaction["spend"],
|
||||
"api_requests": transaction["api_requests"],
|
||||
"successful_requests": transaction[
|
||||
"successful_requests"
|
||||
],
|
||||
"failed_requests": transaction[
|
||||
"failed_requests"
|
||||
],
|
||||
},
|
||||
"update": {
|
||||
"prompt_tokens": {
|
||||
|
@ -2617,6 +2680,14 @@ class ProxyUpdateSpend:
|
|||
"api_requests": {
|
||||
"increment": transaction["api_requests"]
|
||||
},
|
||||
"successful_requests": {
|
||||
"increment": transaction[
|
||||
"successful_requests"
|
||||
]
|
||||
},
|
||||
"failed_requests": {
|
||||
"increment": transaction["failed_requests"]
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue