This commit is contained in:
VyNox 2026-11-06 15:50:38 -05:00 • committed by GitHub
commit 8b292e02ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 39 additions and 1 deletions

View file

@ -52,6 +52,7 @@ from litellm.litellm_core_utils.core_helpers import (
)
from litellm.litellm_core_utils.get_llm_provider_logic import is_registered_custom_provider
from litellm.litellm_core_utils.service_tier_utils import (
KNOWN_REQUEST_SERVICE_TIERS,
get_service_tier_from_standard_logging_payload,
)
from litellm.llms.azure.common_utils import caused_by_entra_rejection
@ -3072,6 +3073,7 @@ class PrometheusLogger(CustomLogger):
api_provider: Final = self._extract_api_provider_from_request_data(
request_data
) or self._extract_api_provider_from_exception(original_exception)
requested_tier: Final = request_data.get("service_tier")
enum_values: Final = UserAPIKeyLabelValues(
end_user=user_api_key_dict.end_user_id,
user=user_api_key_dict.user_id,
@ -3097,6 +3099,9 @@ class PrometheusLogger(CustomLogger):
model_id=model_id,
api_provider=api_provider,
stream=(str(request_data.get("stream")) if litellm.prometheus_emit_stream_label else None),
service_tier=requested_tier
if isinstance(requested_tier, str) and requested_tier in KNOWN_REQUEST_SERVICE_TIERS
else None,
)
_label_ctx: Final = PrometheusLabelFactoryContext(enum_values)
PrometheusLogger._inc_labeled_counter(

View file

@ -515,6 +515,7 @@ class PrometheusMetricLabels:
UserAPIKeyLabelNames.USER_EMAIL.value,
UserAPIKeyLabelNames.EXCEPTION_STATUS.value,
UserAPIKeyLabelNames.EXCEPTION_CLASS.value,
UserAPIKeyLabelNames.SERVICE_TIER.value,
# ``rate_limit_category`` / ``rate_limit_type`` are appended in
# ``get_labels()`` when ``litellm.prometheus_emit_rate_limit_labels``
# is True. Kept opt-in so existing dashboards keyed on this metric's

View file

@ -1,5 +1,5 @@
"""
Unit tests for the service_tier Prometheus label on latency and spend metrics.
Unit tests for the service_tier Prometheus label on latency, spend, and failure metrics.
Covers the label being declared on the metrics that carry it, the precedence
between the tier a provider served and the tier a caller requested, and the
@ -10,9 +10,12 @@ Run with:
"""
import datetime
from typing import Final
import pytest
from prometheus_client import generate_latest
from litellm.exceptions import RateLimitError
from litellm.integrations.prometheus import PrometheusLogger
from litellm.litellm_core_utils.service_tier_utils import (
KNOWN_REQUEST_SERVICE_TIERS,
@ -23,6 +26,7 @@ from litellm.types.integrations.prometheus import (
UserAPIKeyLabelNames,
UserAPIKeyLabelValues,
)
from litellm.types.proxy.auth.user_api_key_auth import UserAPIKeyAuth
SERVICE_TIER_METRICS = [
"litellm_llm_api_latency_metric",
@ -239,3 +243,31 @@ def test_allowlist_covers_every_modeled_service_tier():
missing = {tier.value for tier in ServiceTier} - KNOWN_REQUEST_SERVICE_TIERS
assert not missing, f"ServiceTier values missing from the allowlist: {sorted(missing)}"
@pytest.mark.parametrize("tier", (*sorted(KNOWN_REQUEST_SERVICE_TIERS), None, "", "unknown-tier", 42, []))
@pytest.mark.asyncio
async def test_failed_request_emits_bounded_service_tier(tier: object) -> None:
_clear_prometheus_registry()
try:
logger: Final = PrometheusLogger()
await logger.async_post_call_failure_hook(
request_data={"model": "test-model", "service_tier": tier},
original_exception=RateLimitError(
message="capacity unavailable", llm_provider="openai", model="test-model"
),
user_api_key_dict=UserAPIKeyAuth(),
)
series: Final = tuple(
line
for line in generate_latest().decode().splitlines()
if line.startswith("litellm_proxy_failed_requests_metric_total{")
)
assert len(series) == 1
expected_tier: Final = tier if isinstance(tier, str) and tier in KNOWN_REQUEST_SERVICE_TIERS else "None"
assert f'service_tier="{expected_tier}"' in series[0]
assert 'exception_status="429"' in series[0]
assert 'exception_class="Openai.RateLimitError"' in series[0]
assert series[0].endswith(" 1.0")
finally:
_clear_prometheus_registry()