Skip to content

Commit 14fffc2

Browse files
author
Krish Dholakia
authored
Merge pull request #24432 from BerriAI/krrishdholakia/project-id-tracking
feat(proxy): add project_alias tracking in callbacks
2 parents 742e176 + 26d162c commit 14fffc2

File tree

11 files changed

+403
-212
lines changed

11 files changed

+403
-212
lines changed

litellm/litellm_core_utils/litellm_logging.py

Lines changed: 147 additions & 139 deletions
Large diffs are not rendered by default.

litellm/proxy/_types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,6 +2416,7 @@ class LiteLLM_VerificationTokenView(LiteLLM_VerificationToken):
24162416
organization_metadata: Optional[dict] = None
24172417

24182418
# Project Params
2419+
project_alias: Optional[str] = None
24192420
project_metadata: Optional[dict] = None
24202421

24212422
# Time stamps
@@ -3228,6 +3229,7 @@ class SpendLogsMetadata(TypedDict):
32283229
user_api_key_alias: Optional[str]
32293230
user_api_key_team_id: Optional[str]
32303231
user_api_key_project_id: Optional[str]
3232+
user_api_key_project_alias: Optional[str]
32313233
user_api_key_org_id: Optional[str]
32323234
user_api_key_user_id: Optional[str]
32333235
user_api_key_team_alias: Optional[str]

litellm/proxy/auth/user_api_key_auth.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ async def _user_api_key_auth_builder( # noqa: PLR0915
836836
)
837837
if _jwt_project_obj is not None:
838838
valid_token.project_metadata = _jwt_project_obj.metadata
839+
valid_token.project_alias = _jwt_project_obj.project_alias
839840

840841
# run through common checks
841842
_ = await common_checks(
@@ -1431,6 +1432,7 @@ async def _user_api_key_auth_builder( # noqa: PLR0915
14311432
)
14321433
if _project_obj is not None:
14331434
valid_token.project_metadata = _project_obj.metadata
1435+
valid_token.project_alias = _project_obj.project_alias
14341436

14351437
global_proxy_spend = None
14361438
if (
@@ -1888,6 +1890,7 @@ async def _run_post_custom_auth_checks(
18881890
)
18891891
if _project_obj is not None:
18901892
valid_token.project_metadata = _project_obj.metadata
1893+
valid_token.project_alias = _project_obj.project_alias
18911894

18921895
if general_settings.get("custom_auth_run_common_checks", False):
18931896
_ = await common_checks(

litellm/proxy/db/create_views.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ async def create_missing_views(db: _db): # noqa: PLR0915
2727
await db.execute_raw(
2828
"""
2929
CREATE VIEW "LiteLLM_VerificationTokenView" AS
30-
SELECT
31-
v.*,
32-
t.spend AS team_spend,
33-
t.max_budget AS team_max_budget,
34-
t.tpm_limit AS team_tpm_limit,
35-
t.rpm_limit AS team_rpm_limit
30+
SELECT
31+
v.*,
32+
t.spend AS team_spend,
33+
t.max_budget AS team_max_budget,
34+
t.tpm_limit AS team_tpm_limit,
35+
t.rpm_limit AS team_rpm_limit,
36+
p.project_alias AS project_alias
3637
FROM "LiteLLM_VerificationToken" v
37-
LEFT JOIN "LiteLLM_TeamTable" t ON v.team_id = t.team_id;
38+
LEFT JOIN "LiteLLM_TeamTable" t ON v.team_id = t.team_id
39+
LEFT JOIN "LiteLLM_ProjectTable" p ON v.project_id = p.project_id;
3840
"""
3941
)
4042

litellm/proxy/hooks/proxy_track_cost_callback.py

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@
1818
log_db_metrics,
1919
)
2020
from litellm.proxy.auth.route_checks import RouteChecks
21+
from litellm.proxy.litellm_pre_call_utils import LiteLLMProxyRequestSetup
2122
from litellm.proxy.utils import ProxyUpdateSpend
22-
from litellm.types.utils import (
23-
StandardLoggingPayload,
24-
StandardLoggingUserAPIKeyMetadata,
25-
)
23+
from litellm.types.utils import StandardLoggingPayload
2624
from litellm.utils import get_end_user_id_for_cost_tracking
2725

2826

@@ -51,25 +49,8 @@ async def async_post_call_failure_hook(
5149
from litellm.proxy.proxy_server import proxy_logging_obj
5250

5351
_metadata = dict(
54-
StandardLoggingUserAPIKeyMetadata(
55-
user_api_key_hash=user_api_key_dict.api_key,
56-
user_api_key_alias=user_api_key_dict.key_alias,
57-
user_api_key_spend=user_api_key_dict.spend,
58-
user_api_key_max_budget=user_api_key_dict.max_budget,
59-
user_api_key_budget_reset_at=(
60-
user_api_key_dict.budget_reset_at.isoformat()
61-
if user_api_key_dict.budget_reset_at
62-
else None
63-
),
64-
user_api_key_user_email=user_api_key_dict.user_email,
65-
user_api_key_user_id=user_api_key_dict.user_id,
66-
user_api_key_team_id=user_api_key_dict.team_id,
67-
user_api_key_org_id=user_api_key_dict.org_id,
68-
user_api_key_project_id=user_api_key_dict.project_id,
69-
user_api_key_team_alias=user_api_key_dict.team_alias,
70-
user_api_key_end_user_id=user_api_key_dict.end_user_id,
71-
user_api_key_request_route=user_api_key_dict.request_route,
72-
user_api_key_auth_metadata=user_api_key_dict.metadata,
52+
LiteLLMProxyRequestSetup.get_sanitized_user_information_from_key(
53+
user_api_key_dict=user_api_key_dict
7354
)
7455
)
7556
_metadata["user_api_key"] = user_api_key_dict.api_key

litellm/proxy/litellm_pre_call_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ def get_sanitized_user_information_from_key(
658658
user_api_key_max_budget=user_api_key_dict.max_budget,
659659
user_api_key_team_id=user_api_key_dict.team_id,
660660
user_api_key_project_id=user_api_key_dict.project_id,
661+
user_api_key_project_alias=user_api_key_dict.project_alias,
661662
user_api_key_user_id=user_api_key_dict.user_id,
662663
user_api_key_org_id=user_api_key_dict.org_id,
663664
user_api_key_team_alias=user_api_key_dict.team_alias,

litellm/proxy/pass_through_endpoints/pass_through_endpoints.py

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@
5555
_read_request_body,
5656
_safe_get_request_headers,
5757
)
58+
from litellm.proxy.litellm_pre_call_utils import LiteLLMProxyRequestSetup
5859
from litellm.proxy.utils import get_server_root_path, normalize_route_for_root_path
5960
from litellm.secret_managers.main import get_secret_str
6061
from litellm.types.llms.custom_http import httpxSpecialProvider
6162
from litellm.types.passthrough_endpoints.pass_through_endpoints import (
6263
EndpointType,
6364
PassthroughStandardLoggingPayload,
6465
)
65-
from litellm.types.utils import StandardLoggingUserAPIKeyMetadata
6666

6767
from .streaming_handler import PassThroughStreamingHandler
6868
from .success_handler import PassThroughEndpointLogging
@@ -502,25 +502,8 @@ def _init_kwargs_for_pass_through_endpoint(
502502
litellm_params_in_body[k] = _parsed_body.pop(k, None)
503503

504504
_metadata = dict(
505-
StandardLoggingUserAPIKeyMetadata(
506-
user_api_key_hash=user_api_key_dict.api_key,
507-
user_api_key_alias=user_api_key_dict.key_alias,
508-
user_api_key_user_email=user_api_key_dict.user_email,
509-
user_api_key_user_id=user_api_key_dict.user_id,
510-
user_api_key_team_id=user_api_key_dict.team_id,
511-
user_api_key_org_id=user_api_key_dict.org_id,
512-
user_api_key_project_id=user_api_key_dict.project_id,
513-
user_api_key_team_alias=user_api_key_dict.team_alias,
514-
user_api_key_end_user_id=user_api_key_dict.end_user_id,
515-
user_api_key_request_route=user_api_key_dict.request_route,
516-
user_api_key_spend=user_api_key_dict.spend,
517-
user_api_key_max_budget=user_api_key_dict.max_budget,
518-
user_api_key_budget_reset_at=(
519-
user_api_key_dict.budget_reset_at.isoformat()
520-
if user_api_key_dict.budget_reset_at
521-
else None
522-
),
523-
user_api_key_auth_metadata=user_api_key_dict.metadata,
505+
LiteLLMProxyRequestSetup.get_sanitized_user_information_from_key(
506+
user_api_key_dict=user_api_key_dict
524507
)
525508
)
526509

litellm/proxy/utils.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,9 +1898,9 @@ async def _handle_logging_proxy_only_error(
18981898
normalized_call_type = CallTypes.aembedding.value
18991899
if normalized_call_type is not None:
19001900
litellm_logging_obj.call_type = normalized_call_type
1901-
litellm_logging_obj.model_call_details["call_type"] = (
1902-
normalized_call_type
1903-
)
1901+
litellm_logging_obj.model_call_details[
1902+
"call_type"
1903+
] = normalized_call_type
19041904
# Pass-through endpoints are logged via the callback loop's
19051905
# async_post_call_failure_hook — skip pre_call and failure handlers.
19061906
if litellm_logging_obj.call_type == CallTypes.pass_through.value:
@@ -2498,7 +2498,8 @@ async def check_view_exists(self):
24982498
required_view = "LiteLLM_VerificationTokenView"
24992499
expected_views_str = ", ".join(f"'{view}'" for view in expected_views)
25002500
pg_schema = os.getenv("DATABASE_SCHEMA", "public")
2501-
ret = await self.db.query_raw(f"""
2501+
ret = await self.db.query_raw(
2502+
f"""
25022503
WITH existing_views AS (
25032504
SELECT viewname
25042505
FROM pg_views
@@ -2510,7 +2511,8 @@ async def check_view_exists(self):
25102511
(SELECT COUNT(*) FROM existing_views) AS view_count,
25112512
ARRAY_AGG(viewname) AS view_names
25122513
FROM existing_views
2513-
""")
2514+
"""
2515+
)
25142516
expected_total_views = len(expected_views)
25152517
if ret[0]["view_count"] == expected_total_views:
25162518
verbose_proxy_logger.info("All necessary views exist!")
@@ -2519,7 +2521,8 @@ async def check_view_exists(self):
25192521
## check if required view exists ##
25202522
if ret[0]["view_names"] and required_view not in ret[0]["view_names"]:
25212523
await self.health_check() # make sure we can connect to db
2522-
await self.db.execute_raw("""
2524+
await self.db.execute_raw(
2525+
"""
25232526
CREATE VIEW "LiteLLM_VerificationTokenView" AS
25242527
SELECT
25252528
v.*,
@@ -2529,7 +2532,8 @@ async def check_view_exists(self):
25292532
t.rpm_limit AS team_rpm_limit
25302533
FROM "LiteLLM_VerificationToken" v
25312534
LEFT JOIN "LiteLLM_TeamTable" t ON v.team_id = t.team_id;
2532-
""")
2535+
"""
2536+
)
25332537

25342538
verbose_proxy_logger.info(
25352539
"LiteLLM_VerificationTokenView Created in DB!"
@@ -2964,6 +2968,7 @@ async def get_data( # noqa: PLR0915
29642968
t.members_with_roles AS team_members_with_roles,
29652969
t.object_permission_id AS team_object_permission_id,
29662970
t.organization_id as org_id,
2971+
p.project_alias AS project_alias,
29672972
tm.spend AS team_member_spend,
29682973
m.aliases AS team_model_aliases,
29692974
-- Added comma to separate b.* columns
@@ -2981,6 +2986,7 @@ async def get_data( # noqa: PLR0915
29812986
LEFT JOIN "LiteLLM_TeamMembership" AS tm ON v.team_id = tm.team_id AND tm.user_id = v.user_id
29822987
LEFT JOIN "LiteLLM_ModelTable" m ON t.model_id = m.id
29832988
LEFT JOIN "LiteLLM_BudgetTable" AS b ON v.budget_id = b.budget_id
2989+
LEFT JOIN "LiteLLM_ProjectTable" AS p ON v.project_id = p.project_id
29842990
LEFT JOIN "LiteLLM_OrganizationTable" AS o ON v.organization_id = o.organization_id
29852991
LEFT JOIN "LiteLLM_BudgetTable" AS b2 ON o.budget_id = b2.budget_id
29862992
WHERE v.token = '{token}'

litellm/types/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,7 @@ class StandardLoggingUserAPIKeyMetadata(TypedDict):
24882488
user_api_key_org_id: Optional[str]
24892489
user_api_key_team_id: Optional[str]
24902490
user_api_key_project_id: Optional[str]
2491+
user_api_key_project_alias: Optional[str]
24912492
user_api_key_user_id: Optional[str]
24922493
user_api_key_user_email: Optional[str]
24932494
user_api_key_team_alias: Optional[str]

0 commit comments

Comments
 (0)