Signed-off-by: vraiti <vraiti@redhat.com> Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com> Co-authored-by: vraiti <vraiti@redhat.com>
92 lines
2.9 KiB
Python
92 lines
2.9 KiB
Python
from prometheus_client import Counter, Gauge, Histogram
|
|
|
|
from vllm_omni.metrics import definitions as defs
|
|
|
|
_labelnames = list(defs.PIPELINE_LABELS)
|
|
|
|
_running_family = Gauge(
|
|
defs.NUM_REQUESTS_RUNNING,
|
|
"Number of requests currently running across all pipeline stages.",
|
|
labelnames=_labelnames,
|
|
)
|
|
_waiting_family = Gauge(
|
|
defs.NUM_REQUESTS_WAITING,
|
|
"Number of requests waiting to be scheduled.",
|
|
labelnames=_labelnames,
|
|
)
|
|
_completion_family = Counter(
|
|
defs.REQUESTS_SUCCESS,
|
|
"Total requests by completion reason "
|
|
"(stop / length / abort / ...). Aborts cover client-disconnect / "
|
|
"cancellation paths in addition to upstream FinishReason.ABORT.",
|
|
labelnames=list(defs.SUCCESS_LABELS),
|
|
)
|
|
_e2e_latency_family = Histogram(
|
|
defs.E2E_REQUEST_LATENCY_S,
|
|
"Pipeline-global end-to-end request latency in seconds (user arrival to complete response).",
|
|
labelnames=_labelnames,
|
|
buckets=defs.SECONDS_BUCKETS,
|
|
)
|
|
|
|
|
|
class OmniPrometheusMetrics:
|
|
"""Label-bound wrapper around the raw Prometheus metrics.
|
|
|
|
Metric collectors use the ``vllm:omni_`` prefix to avoid being
|
|
removed by upstream vLLM's ``unregister_vllm_metrics()``, which
|
|
strips every collector whose ``_name`` contains ``"vllm"``.
|
|
"""
|
|
|
|
def __init__(self, model_name: str, log_stats: bool = True) -> None:
|
|
self._model_name = model_name
|
|
self._log_stats = log_stats
|
|
self._running = _running_family.labels(model_name=model_name)
|
|
self._waiting = _waiting_family.labels(model_name=model_name)
|
|
self._e2e_latency = _e2e_latency_family.labels(model_name=model_name)
|
|
|
|
def set_running(self, n: int) -> None:
|
|
if not self._log_stats:
|
|
return
|
|
self._running.set(n)
|
|
|
|
def set_waiting(self, n: int) -> None:
|
|
if not self._log_stats:
|
|
return
|
|
self._waiting.set(n)
|
|
|
|
def request_succeeded(
|
|
self,
|
|
e2e_seconds: float,
|
|
finished_reason: str = "stop",
|
|
) -> None:
|
|
if not self._log_stats:
|
|
return
|
|
_completion_family.labels(
|
|
model_name=self._model_name,
|
|
finished_reason=finished_reason,
|
|
).inc()
|
|
self._e2e_latency.observe(e2e_seconds)
|
|
|
|
def request_failed(self) -> None:
|
|
if not self._log_stats:
|
|
return
|
|
# Pipeline-level "fail" maps to the upstream FinishReason.ABORT bucket;
|
|
# a single counter family now covers both normal stops and aborts.
|
|
_completion_family.labels(
|
|
model_name=self._model_name,
|
|
finished_reason="abort",
|
|
).inc()
|
|
|
|
|
|
class OmniRequestCounter:
|
|
"""Running-request counter written by the orchestrator thread, read by the client thread."""
|
|
|
|
def __init__(self) -> None:
|
|
self.value = 0
|
|
|
|
def increment(self) -> None:
|
|
self.value += 1
|
|
|
|
def decrement(self) -> None:
|
|
self.value = max(0, self.value - 1)
|