diff --git a/docs/my-website/docs/proxy/cost_tracking.md b/docs/my-website/docs/proxy/cost_tracking.md
index de1a63a4c32..b63fab1067e 100644
--- a/docs/my-website/docs/proxy/cost_tracking.md
+++ b/docs/my-website/docs/proxy/cost_tracking.md
@@ -138,14 +138,22 @@ Navigate to the Usage Tab on the LiteLLM UI (found on https://your-proxy-endpoin
## API Endpoints to get Spend
-#### Getting Spend Reports - To Charge Other Teams, API Keys
+#### Getting Spend Reports - To Charge Other Teams, Customers
-Use the `/global/spend/report` endpoint to get daily spend per team, with a breakdown of spend per API Key, Model
+Use the `/global/spend/report` endpoint to get daily spend report per
+- team
+- customer [this is `user` passed to `/chat/completions` request](#how-to-track-spend-with-litellm)
+
+
+
+
##### Example Request
+👉 Key Change: Specify `group_by=team`
+
```shell
-curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end_date=2024-06-30' \
+curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end_date=2024-06-30&group_by=team' \
-H 'Authorization: Bearer sk-1234'
```
@@ -254,6 +262,69 @@ Output from script
```
+
+
+
+
+
+
+
+
+
+##### Example Request
+
+👉 Key Change: Specify `group_by=customer`
+
+
+```shell
+curl -X GET 'http://localhost:4000/global/spend/report?start_date=2024-04-01&end_date=2024-06-30&group_by=customer' \
+ -H 'Authorization: Bearer sk-1234'
+```
+
+##### Example Response
+
+
+```shell
+[
+ {
+ "group_by_day": "2024-04-30T00:00:00+00:00",
+ "customers": [
+ {
+ "customer": "palantir",
+ "total_spend": 0.0015265,
+ "metadata": [ # see the spend by unique(key + model)
+ {
+ "model": "gpt-4",
+ "spend": 0.00123,
+ "total_tokens": 28,
+ "api_key": "88dc28.." # the hashed api key
+ },
+ {
+ "model": "gpt-4",
+ "spend": 0.00123,
+ "total_tokens": 28,
+ "api_key": "a73dc2.." # the hashed api key
+ },
+ {
+ "model": "chatgpt-v-2",
+ "spend": 0.000214,
+ "total_tokens": 122,
+ "api_key": "898c28.." # the hashed api key
+ },
+ {
+ "model": "gpt-3.5-turbo",
+ "spend": 0.0000825,
+ "total_tokens": 85,
+ "api_key": "84dc28.." # the hashed api key
+ }
+ ]
+ }
+ ]
+ }
+]
+```
+
+
diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py
index 40fca0c046e..6f782ba3084 100644
--- a/litellm/proxy/proxy_server.py
+++ b/litellm/proxy/proxy_server.py
@@ -7814,6 +7814,10 @@ async def get_global_spend_report(
default=None,
description="Time till which to view spend",
),
+ group_by: Optional[Literal["team", "customer"]] = fastapi.Query(
+ default="team",
+ description="Group spend by internal team or customer",
+ ),
):
"""
Get Daily Spend per Team, based on specific startTime and endTime. Per team, view usage by each key, model
@@ -7860,69 +7864,130 @@ async def get_global_spend_report(
f"Database not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keys"
)
- # first get data from spend logs -> SpendByModelApiKey
- # then read data from "SpendByModelApiKey" to format the response obj
- sql_query = """
+ if group_by == "team":
+ # first get data from spend logs -> SpendByModelApiKey
+ # then read data from "SpendByModelApiKey" to format the response obj
+ sql_query = """
- WITH SpendByModelApiKey AS (
- SELECT
- date_trunc('day', sl."startTime") AS group_by_day,
- COALESCE(tt.team_alias, 'Unassigned Team') AS team_name,
- sl.model,
- sl.api_key,
- SUM(sl.spend) AS model_api_spend,
- SUM(sl.total_tokens) AS model_api_tokens
- FROM
- "LiteLLM_SpendLogs" sl
- LEFT JOIN
- "LiteLLM_TeamTable" tt
- ON
- sl.team_id = tt.team_id
- WHERE
- sl."startTime" BETWEEN $1::date AND $2::date
- GROUP BY
- date_trunc('day', sl."startTime"),
- tt.team_alias,
- sl.model,
- sl.api_key
- )
+ WITH SpendByModelApiKey AS (
+ SELECT
+ date_trunc('day', sl."startTime") AS group_by_day,
+ COALESCE(tt.team_alias, 'Unassigned Team') AS team_name,
+ sl.model,
+ sl.api_key,
+ SUM(sl.spend) AS model_api_spend,
+ SUM(sl.total_tokens) AS model_api_tokens
+ FROM
+ "LiteLLM_SpendLogs" sl
+ LEFT JOIN
+ "LiteLLM_TeamTable" tt
+ ON
+ sl.team_id = tt.team_id
+ WHERE
+ sl."startTime" BETWEEN $1::date AND $2::date
+ GROUP BY
+ date_trunc('day', sl."startTime"),
+ tt.team_alias,
+ sl.model,
+ sl.api_key
+ )
+ SELECT
+ group_by_day,
+ jsonb_agg(jsonb_build_object(
+ 'team_name', team_name,
+ 'total_spend', total_spend,
+ 'metadata', metadata
+ )) AS teams
+ FROM (
+ SELECT
+ group_by_day,
+ team_name,
+ SUM(model_api_spend) AS total_spend,
+ jsonb_agg(jsonb_build_object(
+ 'model', model,
+ 'api_key', api_key,
+ 'spend', model_api_spend,
+ 'total_tokens', model_api_tokens
+ )) AS metadata
+ FROM
+ SpendByModelApiKey
+ GROUP BY
+ group_by_day,
+ team_name
+ ) AS aggregated
+ GROUP BY
+ group_by_day
+ ORDER BY
+ group_by_day;
+ """
+
+ db_response = await prisma_client.db.query_raw(
+ sql_query, start_date_obj, end_date_obj
+ )
+ if db_response is None:
+ return []
+
+ return db_response
+
+ elif group_by == "customer":
+ sql_query = """
+
+ WITH SpendByModelApiKey AS (
+ SELECT
+ date_trunc('day', sl."startTime") AS group_by_day,
+ sl.end_user AS customer,
+ sl.model,
+ sl.api_key,
+ SUM(sl.spend) AS model_api_spend,
+ SUM(sl.total_tokens) AS model_api_tokens
+ FROM
+ "LiteLLM_SpendLogs" sl
+ WHERE
+ sl."startTime" BETWEEN $1::date AND $2::date
+ GROUP BY
+ date_trunc('day', sl."startTime"),
+ customer,
+ sl.model,
+ sl.api_key
+ )
SELECT
group_by_day,
jsonb_agg(jsonb_build_object(
- 'team_name', team_name,
+ 'customer', customer,
'total_spend', total_spend,
'metadata', metadata
- )) AS teams
- FROM (
- SELECT
- group_by_day,
- team_name,
- SUM(model_api_spend) AS total_spend,
- jsonb_agg(jsonb_build_object(
- 'model', model,
- 'api_key', api_key,
- 'spend', model_api_spend,
- 'total_tokens', model_api_tokens
- )) AS metadata
- FROM
- SpendByModelApiKey
- GROUP BY
- group_by_day,
- team_name
- ) AS aggregated
+ )) AS customers
+ FROM
+ (
+ SELECT
+ group_by_day,
+ customer,
+ SUM(model_api_spend) AS total_spend,
+ jsonb_agg(jsonb_build_object(
+ 'model', model,
+ 'api_key', api_key,
+ 'spend', model_api_spend,
+ 'total_tokens', model_api_tokens
+ )) AS metadata
+ FROM
+ SpendByModelApiKey
+ GROUP BY
+ group_by_day,
+ customer
+ ) AS aggregated
GROUP BY
group_by_day
ORDER BY
group_by_day;
- """
+ """
- db_response = await prisma_client.db.query_raw(
- sql_query, start_date_obj, end_date_obj
- )
- if db_response is None:
- return []
+ db_response = await prisma_client.db.query_raw(
+ sql_query, start_date_obj, end_date_obj
+ )
+ if db_response is None:
+ return []
- return db_response
+ return db_response
except Exception as e:
raise HTTPException(