litellm/tests/e2e/logging/test_prometheus_queue_time_e2e.py
ryan-crabbe-berri 79209b92a1
test(e2e): tag guardrails and logging tests with Subject metadata and record client steps (#44963)
* test(e2e): add enum values, auto-discovering label gates and secret hiding for e2e metadata

* test(e2e): tag guardrails and logging tests with Subject metadata and record client steps

* test(e2e): leave the guardrails and logging harness unit tests untagged

* test(e2e): let the inner create_model step name the guardrail backend deployment

* docs(e2e): name every markerless harness test file that carries no Subject

* test(e2e): keep the step discovery comprehensions to one for clause

* test(e2e): declare the default guardrail backend model on the tests that drive it
2026-10-07 10:32:25 -07:00

68 lines
2.3 KiB
Python

from __future__ import annotations
import time
import pytest
from prometheus_client.parser import text_string_to_metric_families
from e2e_config import unique_marker
from e2e_metadata import Domain, Mode, Provider, Route, Subject, meta
from lifecycle import ResourceManager
from logging_client import LoggingClient
pytestmark = pytest.mark.e2e
DRIVER_MODEL = "gemini-2.5-flash"
QUEUE_TIME_METRIC = "litellm_request_queue_time_seconds"
ALIAS_LABEL = "api_key_alias"
def _observation_count(exposition: str, alias: str) -> float | None:
return next(
(
sample.value
for family in text_string_to_metric_families(exposition)
for sample in family.samples
if sample.name == f"{QUEUE_TIME_METRIC}_count" and sample.labels.get(ALIAS_LABEL) == alias
),
None,
)
class TestPrometheusRequestQueueTime:
@pytest.mark.covers("logging.prometheus.success.records_queue_time")
@meta(
Subject(
domain=Domain.OBSERVABILITY,
route=Route.METRICS,
providers=(Provider.GEMINI,),
models=(DRIVER_MODEL,),
mode=Mode.NONSTREAM,
)
)
def test_queue_time_histogram_records_an_observation(
self, client: LoggingClient, resources: ResourceManager
) -> None:
alias = f"e2e-queue-time-{unique_marker()}"
key = client.key_with_alias(alias, models=[DRIVER_MODEL])
resources.defer(lambda: client.delete_key(key))
response = client.chat(key, DRIVER_MODEL, f"reply with one word {alias}")
assert response.model, f"driver call returned no model: {response}"
deadline = time.monotonic() + client.proxy.poll_timeout
count: float | None = None
while time.monotonic() < deadline:
count = _observation_count(client.scrape_metrics(), alias)
if count is not None and count > 0:
break
time.sleep(client.proxy.poll_interval)
assert count is not None, (
f"{QUEUE_TIME_METRIC} has no series for {ALIAS_LABEL}={alias}; the histogram was "
f"never observed for a request that succeeded"
)
assert count > 0, (
f"{QUEUE_TIME_METRIC} series for {alias} exists but recorded {count} observations; "
f"the metric is registered yet never written"
)