mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-10 22:41:41 +00:00
fix(rate-limiting): read success-event tags from the resolved metadata bucket, not raw kwargs
Bugbot finding: async_log_success_event passed raw kwargs (Logging.model_call_details) to _get_tags_from_request_kwargs, which checks a top-level key matching metadata_variable_name before falling back to kwargs["litellm_params"]. Some call paths populate that top-level key present but None, so it won it over the real, populated dict nested under litellm_params, silently dropping token/dollar accounting for those routes. key_hash/key_alias/order_tags_for_identity_resolution already read from litellm_params_for_metadata; tag extraction now does too. Regression test confirmed to fail on the pre-fix code.
This commit is contained in:
parent
1fe4b6699d
commit
63299d9df6
2 changed files with 45 additions and 1 deletions
|
|
@ -725,7 +725,7 @@ class _PROXY_GlobalTagRateLimitsHook( # pyright: ignore[reportUnusedClass] # o
|
|||
key_alias: Final = _extract_key_alias(litellm_params_for_metadata, metadata_variable_name)
|
||||
|
||||
tags: Final = _order_tags_for_identity_resolution(
|
||||
_get_tags_from_request_kwargs(kwargs, metadata_variable_name=metadata_variable_name),
|
||||
_get_tags_from_request_kwargs(litellm_params_for_metadata, metadata_variable_name=metadata_variable_name),
|
||||
litellm_params_for_metadata,
|
||||
metadata_variable_name,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1181,6 +1181,50 @@ async def test_log_success_event_accounts_when_litellm_params_carries_a_null_lit
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_log_success_event_reads_tags_when_top_level_kwargs_carries_a_null_metadata_key(
|
||||
time_controller, monkeypatch
|
||||
):
|
||||
"""
|
||||
Bugbot finding: some call paths populate a top-level "metadata" (or
|
||||
"litellm_metadata") key on kwargs (Logging.model_call_details) set to
|
||||
None, alongside the real, populated dict nested under
|
||||
kwargs["litellm_params"]. _get_tags_from_request_kwargs checks the
|
||||
top-level key first; passing it raw kwargs made a present-but-None
|
||||
top-level key win, reading no tags at all even though
|
||||
metadata_variable_name correctly resolved to "metadata".
|
||||
"""
|
||||
monkeypatch.setattr(
|
||||
litellm,
|
||||
"global_tag_rate_limits",
|
||||
{
|
||||
"dollar_limits": {
|
||||
"limits": [{"name": "daily_spend", "tag_id": "end_user_id", "limit": 10.0, "period_seconds": 86400}]
|
||||
}
|
||||
},
|
||||
)
|
||||
hook = _make_hook(time_controller)
|
||||
|
||||
kwargs = {
|
||||
"litellm_call_id": "call-1",
|
||||
"metadata": None,
|
||||
"litellm_params": {
|
||||
"metadata": {"tags": ["end_user_id:u1"], "user_api_key": "hash"},
|
||||
},
|
||||
"standard_logging_object": {"total_tokens": 0, "response_cost": 12.0},
|
||||
}
|
||||
await hook.async_log_success_event(kwargs=kwargs, response_obj=None, start_time=0, end_time=0)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
with pytest.raises(ProxyRateLimitError):
|
||||
await hook.async_pre_call_hook(
|
||||
user_api_key_dict=_key(),
|
||||
cache=DualCache(),
|
||||
data=_data(["end_user_id:u1"], call_id="call-2"),
|
||||
call_type="completion",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dollar_limit_respects_apply_to_key_alias_at_accounting_time(time_controller, monkeypatch):
|
||||
"""The entry only applies to `premium-key`; a non-listed key's spend must
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue