refactor(prometheus): drop transitive fastapi import from _get_exception_class_name
Some checks failed
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled

Read the legacy exception_class label from a prometheus_exception_class_name
marker on ProxyRateLimitError instead of importing the proxy module, keeping
the integrations layer free of a transitive fastapi dependency.
This commit is contained in:
mateo-berri 2026-06-03 21:38:17 +00:00
parent 9c92921479
commit 443563c2e4
No known key found for this signature in database
2 changed files with 16 additions and 26 deletions

View file

@ -2875,32 +2875,15 @@ class PrometheusLogger(CustomLogger):
@staticmethod
def _get_exception_class_name(exception: Exception) -> str:
# Back-compat: ProxyRateLimitError multi-inherits from
# fastapi.HTTPException + litellm.RateLimitError. Before the unified
# rate-limit error class landed, every proxy-side 429 surfaced on this
# label as the literal string "HTTPException", and existing dashboards
# / alerts (e.g. trho's HubSpot dashboard) key off that exact value.
# Renaming the class would silently break those queries, so we keep
# emitting "HTTPException" here. Callers that need to distinguish
# vendor vs. litellm rate limits should use the new
# ``rate_limit_category`` / ``rate_limit_type`` labels instead.
#
# The import is intentionally lazy + ImportError-tolerant: this method
# is also called from router-side fallback events
# (``log_success_fallback_event`` / ``log_failure_fallback_event``)
# which can run in non-proxy installs where ``fastapi`` (a transitive
# dep of ``proxy_rate_limit_error``) is not installed.
try:
from litellm.proxy.common_utils.proxy_rate_limit_error import (
ProxyRateLimitError,
)
except ImportError:
ProxyRateLimitError = None # type: ignore[assignment,misc]
if ProxyRateLimitError is not None and isinstance(
exception, ProxyRateLimitError
):
return "HTTPException"
# Some exception types pin the ``exception_class`` label to a legacy
# value for back-compat with existing dashboards (e.g. proxy-side 429s
# keep reporting as "HTTPException"). Honor that opt-in marker before
# deriving the label from the runtime class name. Reading it via
# ``getattr`` keeps this core integrations module free of a transitive
# ``fastapi`` dependency.
legacy_class_name = getattr(exception, "prometheus_exception_class_name", None)
if isinstance(legacy_class_name, str) and legacy_class_name:
return legacy_class_name
# Same back-compat reasoning for ``BudgetExceededError``: the unified
# rate-limit error work attached ``.llm_provider`` to budget errors

View file

@ -133,6 +133,13 @@ class ProxyRateLimitError(HTTPException, RateLimitError): # type: ignore[misc]
compatibility with logging / standard payload extraction.
"""
# Prometheus' ``exception_class`` label is pinned to "HTTPException" for
# this type: before the unified class existed, proxy-side 429s surfaced as
# ``fastapi.HTTPException`` and existing dashboards/alerts key off that exact
# value. Distinguishing vendor vs. litellm 429s is now the job of the
# ``rate_limit_category`` / ``rate_limit_type`` labels.
prometheus_exception_class_name = "HTTPException"
def __init__(
self,
detail: Any,