Production Metrics

vLLM exposes a number of metrics that can be used to monitor the health of the system. These metrics are exposed via the /metrics endpoint on the vLLM OpenAI compatible API server.

The following metrics are exposed:

  1. class Metrics:
  2. """
  3. vLLM uses a multiprocessing-based frontend for the OpenAI server.
  4. This means that we need to run prometheus_client in multiprocessing mode
  5. See https://prometheus.github.io/client_python/multiprocess/ for more
  6. details on limitations.
  7. """
  8. labelname_finish_reason = "finished_reason"
  9. _gauge_cls = prometheus_client.Gauge
  10. _counter_cls = prometheus_client.Counter
  11. _histogram_cls = prometheus_client.Histogram
  12. def __init__(self, labelnames: List[str], max_model_len: int):
  13. # Unregister any existing vLLM collectors (for CI/CD)
  14. self._unregister_vllm_metrics()
  15. # System stats
  16. # Scheduler State
  17. self.gauge_scheduler_running = self._gauge_cls(
  18. name="vllm:num_requests_running",
  19. documentation="Number of requests currently running on GPU.",
  20. labelnames=labelnames,
  21. multiprocess_mode="sum")
  22. self.gauge_scheduler_waiting = self._gauge_cls(
  23. name="vllm:num_requests_waiting",
  24. documentation="Number of requests waiting to be processed.",
  25. labelnames=labelnames,
  26. multiprocess_mode="sum")
  27. self.gauge_scheduler_swapped = self._gauge_cls(
  28. name="vllm:num_requests_swapped",
  29. documentation="Number of requests swapped to CPU.",
  30. labelnames=labelnames,
  31. multiprocess_mode="sum")
  32. # KV Cache Usage in %
  33. self.gauge_gpu_cache_usage = self._gauge_cls(
  34. name="vllm:gpu_cache_usage_perc",
  35. documentation="GPU KV-cache usage. 1 means 100 percent usage.",
  36. labelnames=labelnames,
  37. multiprocess_mode="sum")
  38. self.gauge_cpu_cache_usage = self._gauge_cls(
  39. name="vllm:cpu_cache_usage_perc",
  40. documentation="CPU KV-cache usage. 1 means 100 percent usage.",
  41. labelnames=labelnames,
  42. multiprocess_mode="sum")
  43. # Prefix caching block hit rate
  44. self.gauge_cpu_prefix_cache_hit_rate = self._gauge_cls(
  45. name="vllm:cpu_prefix_cache_hit_rate",
  46. documentation="CPU prefix cache block hit rate.",
  47. labelnames=labelnames,
  48. multiprocess_mode="sum")
  49. self.gauge_gpu_prefix_cache_hit_rate = self._gauge_cls(
  50. name="vllm:gpu_prefix_cache_hit_rate",
  51. documentation="GPU prefix cache block hit rate.",
  52. labelnames=labelnames,
  53. multiprocess_mode="sum")
  54. # Iteration stats
  55. self.counter_num_preemption = self._counter_cls(
  56. name="vllm:num_preemptions_total",
  57. documentation="Cumulative number of preemption from the engine.",
  58. labelnames=labelnames)
  59. self.counter_prompt_tokens = self._counter_cls(
  60. name="vllm:prompt_tokens_total",
  61. documentation="Number of prefill tokens processed.",
  62. labelnames=labelnames)
  63. self.counter_generation_tokens = self._counter_cls(
  64. name="vllm:generation_tokens_total",
  65. documentation="Number of generation tokens processed.",
  66. labelnames=labelnames)
  67. self.histogram_time_to_first_token = self._histogram_cls(
  68. name="vllm:time_to_first_token_seconds",
  69. documentation="Histogram of time to first token in seconds.",
  70. labelnames=labelnames,
  71. buckets=[
  72. 0.001, 0.005, 0.01, 0.02, 0.04, 0.06, 0.08, 0.1, 0.25, 0.5,
  73. 0.75, 1.0, 2.5, 5.0, 7.5, 10.0
  74. ])
  75. self.histogram_time_per_output_token = self._histogram_cls(
  76. name="vllm:time_per_output_token_seconds",
  77. documentation="Histogram of time per output token in seconds.",
  78. labelnames=labelnames,
  79. buckets=[
  80. 0.01, 0.025, 0.05, 0.075, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.75,
  81. 1.0, 2.5
  82. ])
  83. # Request stats
  84. # Latency
  85. self.histogram_e2e_time_request = self._histogram_cls(
  86. name="vllm:e2e_request_latency_seconds",
  87. documentation="Histogram of end to end request latency in seconds.",
  88. labelnames=labelnames,
  89. buckets=[1.0, 2.5, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 60.0])
  90. # Metadata
  91. self.histogram_num_prompt_tokens_request = self._histogram_cls(
  92. name="vllm:request_prompt_tokens",
  93. documentation="Number of prefill tokens processed.",
  94. labelnames=labelnames,
  95. buckets=build_1_2_5_buckets(max_model_len),
  96. )
  97. self.histogram_num_generation_tokens_request = \
  98. self._histogram_cls(
  99. name="vllm:request_generation_tokens",
  100. documentation="Number of generation tokens processed.",
  101. labelnames=labelnames,
  102. buckets=build_1_2_5_buckets(max_model_len),
  103. )
  104. self.histogram_best_of_request = self._histogram_cls(
  105. name="vllm:request_params_best_of",
  106. documentation="Histogram of the best_of request parameter.",
  107. labelnames=labelnames,
  108. buckets=[1, 2, 5, 10, 20],
  109. )
  110. self.histogram_n_request = self._histogram_cls(
  111. name="vllm:request_params_n",
  112. documentation="Histogram of the n request parameter.",
  113. labelnames=labelnames,
  114. buckets=[1, 2, 5, 10, 20],
  115. )
  116. self.counter_request_success = self._counter_cls(
  117. name="vllm:request_success_total",
  118. documentation="Count of successfully processed requests.",
  119. labelnames=labelnames + [Metrics.labelname_finish_reason])
  120. # Speculatie decoding stats
  121. self.gauge_spec_decode_draft_acceptance_rate = self._gauge_cls(
  122. name="vllm:spec_decode_draft_acceptance_rate",
  123. documentation="Speulative token acceptance rate.",
  124. labelnames=labelnames,
  125. multiprocess_mode="sum")
  126. self.gauge_spec_decode_efficiency = self._gauge_cls(
  127. name="vllm:spec_decode_efficiency",
  128. documentation="Speculative decoding system efficiency.",
  129. labelnames=labelnames,
  130. multiprocess_mode="sum")
  131. self.counter_spec_decode_num_accepted_tokens = (self._counter_cls(
  132. name="vllm:spec_decode_num_accepted_tokens_total",
  133. documentation="Number of accepted tokens.",
  134. labelnames=labelnames))
  135. self.counter_spec_decode_num_draft_tokens = self._counter_cls(
  136. name="vllm:spec_decode_num_draft_tokens_total",
  137. documentation="Number of draft tokens.",
  138. labelnames=labelnames)
  139. self.counter_spec_decode_num_emitted_tokens = (self._counter_cls(
  140. name="vllm:spec_decode_num_emitted_tokens_total",
  141. documentation="Number of emitted tokens.",
  142. labelnames=labelnames))
  143. # Deprecated in favor of vllm:prompt_tokens_total
  144. self.gauge_avg_prompt_throughput = self._gauge_cls(
  145. name="vllm:avg_prompt_throughput_toks_per_s",
  146. documentation="Average prefill throughput in tokens/s.",
  147. labelnames=labelnames,
  148. multiprocess_mode="sum",
  149. )
  150. # Deprecated in favor of vllm:generation_tokens_total
  151. self.gauge_avg_generation_throughput = self._gauge_cls(
  152. name="vllm:avg_generation_throughput_toks_per_s",
  153. documentation="Average generation throughput in tokens/s.",
  154. labelnames=labelnames,
  155. multiprocess_mode="sum",
  156. )