fix(prometheus): resolve team spend/max_budget before constructing team object

Compute the DB-fallback spend and max_budget values up front instead of
mutating team_object after construction, so _assemble_team_object's
result does not depend on statement order. The auth-carried snapshot
path is unchanged.
This commit is contained in:
72004 2026-10-10 18:46:14 +05:00
parent dcd3dc6724
commit 578521d119
2 changed files with 18 additions and 18 deletions

View file

@ -4230,30 +4230,30 @@ class PrometheusLogger(CustomLogger):
max_budget=max_budget if max_budget is not None else carried.max_budget,
budget_reset_at=carried.budget_reset_at,
)
team_object: Final = LiteLLM_TeamTable(
team_id=team_id,
team_alias=team_alias,
spend=_total_team_spend,
max_budget=max_budget,
)
team_info: LiteLLM_TeamTable | None = None
try:
team_info: Final = await get_team_object(
team_info = await get_team_object(
team_id=team_id,
prisma_client=prisma_client,
user_api_key_cache=user_api_key_cache,
)
except Exception as e:
verbose_logger.debug("[Non-Blocking] Prometheus: Error getting team info: %s", e)
return team_object
if team_info:
team_object.budget_reset_at = team_info.budget_reset_at
if team_object.max_budget is None and team_info.max_budget is not None:
team_object.max_budget = team_info.max_budget
if spend is None and team_info.spend is not None:
team_object.spend = team_info.spend + response_cost
return team_object
# metadata spend of None means "unknown", not "nothing spent" -- fall back to the DB value
_base_spend: Final = (
spend if spend is not None else (team_info.spend if team_info and team_info.spend is not None else 0)
)
_resolved_max_budget: Final = (
max_budget if max_budget is not None else (team_info.max_budget if team_info else None)
)
return LiteLLM_TeamTable(
team_id=team_id,
team_alias=team_alias,
spend=_base_spend + response_cost,
max_budget=_resolved_max_budget,
budget_reset_at=team_info.budget_reset_at if team_info else None,
)
def _set_team_budget_metrics(
self,

View file

@ -356,7 +356,7 @@ async def test_assemble_team_object_uses_db_spend_when_metadata_is_none(
team_object = await prometheus_logger._assemble_team_object(
team_id="team-1",
team_alias="team-a",
spend=None, # simulates None coming from request metadata
spend=None,
max_budget=1000.0,
response_cost=0.5,
)
@ -383,7 +383,7 @@ async def test_assemble_team_object_does_not_override_metadata_spend(
team_object = await prometheus_logger._assemble_team_object(
team_id="team-1",
team_alias="team-a",
spend=50.0, # metadata has a real value
spend=50.0,
max_budget=1000.0,
response_cost=1.0,
)