mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-01 07:03:02 +00:00
fix(proxy): don't send llm_exceptions alert for BudgetExceededError (#49290)
* fix(proxy): don't send llm_exceptions alert for BudgetExceededError * test(proxy): verify budget alert suppression through failure hooks --------- Co-authored-by: Arvind Kumar <arvindkumar.acad@gmail.com>
This commit is contained in:
parent
0d5cf9b2f7
commit
7b259690e7
2 changed files with 51 additions and 0 deletions
|
|
@ -633,6 +633,8 @@ def _is_client_error_exception(exc: Exception) -> bool:
|
|||
return exc.status_code < 500
|
||||
if isinstance(exc, ProxyException):
|
||||
return not (exc.code.isdigit() and int(exc.code) >= 500)
|
||||
if isinstance(exc, litellm.BudgetExceededError):
|
||||
return exc.status_code < 500
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1844,6 +1844,26 @@ class TestPostCallFailureHookLLMExceptionAlerting:
|
|||
alerting_handler = await self._alerted(HTTPException(status_code=429, detail="rate limited"))
|
||||
assert alerting_handler.called is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("status_code, should_alert", ((400, False), (422, False), (429, False), (500, True)))
|
||||
async def test_budget_exceeded_alerts_only_for_server_status(
|
||||
self, status_code: int, should_alert: bool, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
monkeypatch.setattr(litellm, "budget_exceeded_status_code", status_code)
|
||||
exc: Final = litellm.BudgetExceededError(current_cost=1.0, max_budget=0.5)
|
||||
assert (await self._alerted(exc)).called is should_alert
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"exc",
|
||||
(
|
||||
litellm.AuthenticationError(message="invalid provider key", model="test-model", llm_provider="openai"),
|
||||
litellm.RateLimitError(message="provider quota exceeded", model="test-model", llm_provider="openai"),
|
||||
),
|
||||
)
|
||||
async def test_provider_client_status_still_alerts(self, exc: Exception) -> None:
|
||||
assert (await self._alerted(exc)).called is True
|
||||
|
||||
|
||||
class TestPostCallFailureHookProxyExceptionLogging:
|
||||
"""A guardrail block raises a ProxyException; on an LLM route it must still
|
||||
|
|
@ -4109,3 +4129,32 @@ def test_handle_exception_on_proxy_logs_bug_report_only_for_unmapped_500(caplog)
|
|||
assert provider_result.code == internal_result.code == "500"
|
||||
assert ISSUE_URL_BASE in caplog.text
|
||||
assert ISSUE_URL_BASE not in internal_result.message
|
||||
|
||||
|
||||
def test_is_client_error_exception_budget_exceeded_is_client_error() -> None:
|
||||
from litellm.exceptions import BudgetExceededError
|
||||
from litellm.proxy.utils import _is_client_error_exception
|
||||
|
||||
exc: Final = BudgetExceededError(current_cost=100.56, max_budget=100.0)
|
||||
assert _is_client_error_exception(exc) is True
|
||||
|
||||
|
||||
def test_is_client_error_exception_budget_exceeded_5xx_is_not_client_error() -> None:
|
||||
from litellm.exceptions import BudgetExceededError
|
||||
from litellm.proxy.utils import _is_client_error_exception
|
||||
|
||||
exc: Final = BudgetExceededError(current_cost=100.56, max_budget=100.0)
|
||||
exc.status_code = 500
|
||||
assert _is_client_error_exception(exc) is False
|
||||
|
||||
|
||||
def test_is_client_error_exception_existing_behaviour_unchanged() -> None:
|
||||
from litellm.proxy._types import ProxyException
|
||||
from litellm.proxy.utils import _is_client_error_exception
|
||||
|
||||
assert _is_client_error_exception(HTTPException(status_code=400, detail="x")) is True
|
||||
assert _is_client_error_exception(HTTPException(status_code=500, detail="x")) is False
|
||||
assert _is_client_error_exception(
|
||||
ProxyException(message="x", type="x", param=None, code="429")
|
||||
) is True
|
||||
assert _is_client_error_exception(ValueError("x")) is False
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue