mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(prometheus): pass gauge labels positionally after upstream merge
Merging litellm_internal_staging put the codebase over two ceilings that this branch is responsible for one violation of each. The _LabeledGauge protocol declared labels(**labels), which LIT008 bans outright, and the keyword call also cost a reportGeneralTypeIssues. Both go away by passing label values positionally, which prometheus_client accepts and which the protocol's remove() already did, so the two calls are now consistent and the ordered values are computed once. Also assert observable output in the no-op metric test instead of relying on it not raising.
This commit is contained in:
parent
8059c7c3de
commit
a36e0d4cba
2 changed files with 13 additions and 9 deletions
|
|
@ -160,7 +160,7 @@ def _get_budget_metrics_per_request_timeout() -> float:
|
|||
class _LabeledGauge(Protocol):
|
||||
"""Structural type shared by ``prometheus_client.Gauge`` and the no-op / label-excluding wrappers above."""
|
||||
|
||||
def labels(self, **labels: str) -> _LabeledGauge: ...
|
||||
def labels(self, *labelvalues: str) -> _LabeledGauge: ...
|
||||
|
||||
def set(self, value: float) -> None: ...
|
||||
|
||||
|
|
@ -2171,13 +2171,14 @@ class PrometheusLogger(CustomLogger):
|
|||
enum_values=enum_values,
|
||||
label_context=label_context,
|
||||
)
|
||||
label_values: Final = tuple(labels.get(name, "") for name in labelnames)
|
||||
if value is not None:
|
||||
self._drop_superseded_team_series(gauge=gauge, labelnames=labelnames, labels=labels)
|
||||
gauge.labels(**labels).set(value)
|
||||
gauge.labels(*label_values).set(value)
|
||||
return
|
||||
|
||||
try:
|
||||
gauge.remove(*(labels.get(name, "") for name in labelnames))
|
||||
gauge.remove(*label_values)
|
||||
except KeyError:
|
||||
# No child series for this labelset, which is the common case:
|
||||
# the team never had a limit for this model.
|
||||
|
|
|
|||
|
|
@ -128,10 +128,9 @@ def test_labels_carry_team_and_requested_model():
|
|||
_set_team_metrics(logger, _payload_with_headers(dict(ALL_TEAM_HEADERS)))
|
||||
|
||||
for metric_name in TEAM_RATE_LIMIT_METRICS:
|
||||
labels_kwargs = getattr(logger, metric_name).labels.call_args.kwargs
|
||||
assert labels_kwargs["team"] == "team-abc"
|
||||
assert labels_kwargs["team_alias"] == "research"
|
||||
assert labels_kwargs["model"] == "gpt-4o-mini"
|
||||
labelnames = PrometheusMetricLabels.get_labels(metric_name)
|
||||
label_values = getattr(logger, metric_name).labels.call_args.args
|
||||
assert dict(zip(labelnames, label_values, strict=True)) == TEAM_LABELS
|
||||
|
||||
|
||||
def test_emits_nothing_when_team_has_no_configured_limits():
|
||||
|
|
@ -353,10 +352,14 @@ def test_excluded_label_wrapper_cannot_remove_when_every_label_is_excluded():
|
|||
|
||||
|
||||
def test_noop_metric_remove_is_inert():
|
||||
"""A disabled metric answers every call without recording or raising."""
|
||||
metric = NoOpMetric()
|
||||
|
||||
metric.labels(**TEAM_LABELS).set(60)
|
||||
metric.remove(*TEAM_LABELS.values())
|
||||
child = metric.labels(*TEAM_LABELS.values())
|
||||
|
||||
assert child is metric
|
||||
assert child.set(60) is None
|
||||
assert metric.remove(*TEAM_LABELS.values()) is None
|
||||
|
||||
|
||||
def test_retires_the_old_series_when_a_team_is_renamed():
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue