mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-26 01:12:21 +00:00
fix(errors): only link bug reports for exceptions without a provider status
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
2fb4391232
commit
33ff50eb11
7 changed files with 54 additions and 10 deletions
|
|
@ -43,6 +43,10 @@ def bug_report_enabled() -> bool:
|
|||
return os.getenv(DISABLE_ENV_VAR, "").lower() != "true"
|
||||
|
||||
|
||||
def should_report_bug(exc: object) -> bool:
|
||||
return bug_report_enabled() and isinstance(exc, BaseException) and getattr(exc, "status_code", None) is None
|
||||
|
||||
|
||||
def _format_frame(frame: traceback.FrameSummary, package_dir: Path, package_parent: Path) -> str | None:
|
||||
frame_path: Final = Path(frame.filename).resolve()
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import httpx
|
|||
import litellm
|
||||
from litellm._logging import _ENABLE_SECRET_REDACTION, _redact_string, verbose_logger
|
||||
from litellm.litellm_core_utils.bug_report import (
|
||||
bug_report_enabled,
|
||||
bug_report_notice,
|
||||
build_bug_report,
|
||||
should_report_bug,
|
||||
)
|
||||
from litellm.litellm_core_utils.secret_redaction import redact_string
|
||||
from litellm.types.utils import LlmProviders
|
||||
|
|
@ -2690,7 +2690,7 @@ def exception_type(
|
|||
custom_llm_provider=cast(str | None, custom_llm_provider),
|
||||
)
|
||||
)
|
||||
if bug_report_enabled() and isinstance(original_exception, BaseException)
|
||||
if should_report_bug(original_exception)
|
||||
else ""
|
||||
)
|
||||
),
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ from litellm.constants import (
|
|||
)
|
||||
from litellm.integrations.custom_guardrail import CustomGuardrail
|
||||
from litellm.litellm_core_utils.bug_report import (
|
||||
bug_report_enabled,
|
||||
bug_report_notice,
|
||||
build_bug_report,
|
||||
should_report_bug,
|
||||
strip_bug_report_notice,
|
||||
)
|
||||
from litellm.litellm_core_utils.core_helpers import (
|
||||
|
|
@ -3665,7 +3665,7 @@ class ProxyBaseLLMRequestProcessing:
|
|||
_code = _exc_status_code
|
||||
else:
|
||||
_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
if bug_report_enabled():
|
||||
if should_report_bug(e):
|
||||
proxy_server_request: Final = self.data.get("proxy_server_request")
|
||||
request_url: Final = (
|
||||
proxy_server_request.get("url") if isinstance(proxy_server_request, Mapping) else None
|
||||
|
|
|
|||
|
|
@ -75,9 +75,9 @@ from litellm.constants import (
|
|||
)
|
||||
from litellm.litellm_core_utils.asyncify import asyncify
|
||||
from litellm.litellm_core_utils.bug_report import (
|
||||
bug_report_enabled,
|
||||
bug_report_notice,
|
||||
build_bug_report,
|
||||
should_report_bug,
|
||||
)
|
||||
from litellm.litellm_core_utils.litellm_logging import (
|
||||
_init_custom_logger_compatible_class,
|
||||
|
|
@ -1875,7 +1875,7 @@ async def otel_unhandled_exception_handler(request: Request, exc: Exception):
|
|||
if isinstance(exc, (ProxyException, HTTPException, RequestValidationError)):
|
||||
raise exc
|
||||
verbose_proxy_logger.exception("Unhandled exception in request: %s", type(exc).__name__)
|
||||
if bug_report_enabled():
|
||||
if should_report_bug(exc):
|
||||
verbose_proxy_logger.error(
|
||||
bug_report_notice(build_bug_report(exc, surface="proxy", call_type=request.url.path))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ from litellm.constants import (
|
|||
SPEND_LOG_WRITE_BATCH_MAX_ROWS,
|
||||
)
|
||||
from litellm.litellm_core_utils.bug_report import (
|
||||
bug_report_enabled,
|
||||
bug_report_notice,
|
||||
build_bug_report,
|
||||
should_report_bug,
|
||||
strip_bug_report_notice,
|
||||
)
|
||||
from litellm.proxy._types import (
|
||||
|
|
@ -7842,7 +7842,7 @@ def handle_exception_on_proxy(e: Exception, litellm_call_id: str | None = None)
|
|||
elif isinstance(e, ProxyException):
|
||||
return with_litellm_call_id(e, litellm_call_id)
|
||||
_status_code: Final = getattr(e, "status_code", status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
if _status_code == status.HTTP_500_INTERNAL_SERVER_ERROR and bug_report_enabled() and isinstance(e, BaseException):
|
||||
if should_report_bug(e):
|
||||
verbose_proxy_logger.error(bug_report_notice(build_bug_report(e, surface="proxy")))
|
||||
return ProxyException(
|
||||
message=strip_bug_report_notice(str(e)),
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ from __future__ import annotations
|
|||
from typing import cast
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from litellm._version import version
|
||||
from litellm.exceptions import BadRequestError
|
||||
from litellm.exceptions import APIConnectionError, BadRequestError, InternalServerError
|
||||
from litellm.litellm_core_utils.bug_report import (
|
||||
DISABLE_ENV_VAR,
|
||||
ISSUE_URL_BASE,
|
||||
|
|
@ -15,6 +16,7 @@ from litellm.litellm_core_utils.bug_report import (
|
|||
bug_report_issue_url,
|
||||
bug_report_notice,
|
||||
build_bug_report,
|
||||
should_report_bug,
|
||||
strip_bug_report_notice,
|
||||
)
|
||||
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
|
||||
|
|
@ -81,6 +83,29 @@ def test_bug_report_can_be_disabled(monkeypatch: pytest.MonkeyPatch):
|
|||
monkeypatch.setenv(DISABLE_ENV_VAR, "true")
|
||||
|
||||
assert bug_report_enabled() is False
|
||||
assert should_report_bug(RuntimeError("boom")) is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"exc",
|
||||
[
|
||||
InternalServerError(message="upstream 500", llm_provider="openai", model="gpt-4"),
|
||||
APIConnectionError(
|
||||
message="connection reset",
|
||||
llm_provider="openai",
|
||||
model="gpt-4",
|
||||
request=httpx.Request(method="POST", url="https://api.openai.com/v1/"),
|
||||
),
|
||||
BadRequestError(message="bad input", llm_provider="openai", model="gpt-4"),
|
||||
"not an exception",
|
||||
],
|
||||
)
|
||||
def test_should_report_bug_skips_provider_and_network_errors(exc: object):
|
||||
assert should_report_bug(exc) is False
|
||||
|
||||
|
||||
def test_should_report_bug_accepts_plain_python_errors():
|
||||
assert should_report_bug(KeyError("missing")) is True
|
||||
|
||||
|
||||
def test_proxy_provider_uses_translation_domain():
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import pytest
|
|||
from fastapi import HTTPException
|
||||
|
||||
from litellm.caching.caching import DualCache
|
||||
from litellm.exceptions import InternalServerError
|
||||
from litellm.integrations.custom_guardrail import CustomGuardrail
|
||||
from litellm.integrations.custom_logger import CustomLogger
|
||||
from litellm.litellm_core_utils.bug_report import ISSUE_URL_BASE
|
||||
from litellm.proxy._types import ProxyErrorTypes, UserAPIKeyAuth
|
||||
from litellm.proxy.utils import PrismaClient, ProxyLogging
|
||||
from litellm.proxy.utils import PrismaClient, ProxyLogging, handle_exception_on_proxy
|
||||
from litellm.types.guardrails import GuardrailEventHooks
|
||||
|
||||
|
||||
|
|
@ -2418,3 +2420,16 @@ def test_mcp_auth_policy_uses_original_request_model(monkeypatch, model, expecte
|
|||
synthetic = proxy_logging._convert_mcp_to_llm_format(proxy_logging._create_mcp_request_object_from_kwargs(kwargs), kwargs)
|
||||
assert ("model-rule" in synthetic["metadata"]["guardrails"]) is expected
|
||||
assert "request-rule" in synthetic["metadata"]["guardrails"]
|
||||
|
||||
|
||||
def test_handle_exception_on_proxy_logs_bug_report_only_for_unmapped_500(caplog):
|
||||
with caplog.at_level("ERROR", logger="LiteLLM Proxy"):
|
||||
provider_result = handle_exception_on_proxy(
|
||||
InternalServerError(message="upstream 500", llm_provider="openai", model="gpt-4")
|
||||
)
|
||||
assert ISSUE_URL_BASE not in caplog.text
|
||||
internal_result = handle_exception_on_proxy(KeyError("missing"))
|
||||
|
||||
assert provider_result.code == internal_result.code == "500"
|
||||
assert ISSUE_URL_BASE in caplog.text
|
||||
assert ISSUE_URL_BASE not in internal_result.message
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue