|
1 | 1 | # SPDX-License-Identifier: Apache-2.0 |
2 | 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
3 | 3 |
|
| 4 | +import time |
4 | 5 | from collections.abc import Mapping |
5 | 6 | from copy import copy |
6 | 7 | from typing import Any, Callable, Optional, Union |
|
31 | 32 | from vllm.v1.engine.parallel_sampling import ParentRequest |
32 | 33 | from vllm.v1.engine.processor import Processor |
33 | 34 | from vllm.v1.executor.abstract import Executor |
34 | | -from vllm.v1.metrics.loggers import (PrometheusStatLogger, StatLoggerBase, |
35 | | - StatLoggerFactory) |
| 35 | +from vllm.v1.metrics.loggers import StatLoggerFactory, StatLoggerManager |
36 | 36 | from vllm.v1.metrics.reader import Metric, get_metrics_snapshot |
37 | 37 | from vllm.v1.metrics.stats import IterationStats |
38 | 38 | from vllm.v1.worker.worker_base import WorkerBase |
@@ -74,9 +74,6 @@ def __init__( |
74 | 74 | self.cache_config = vllm_config.cache_config |
75 | 75 |
|
76 | 76 | self.log_stats = log_stats |
77 | | - self.stat_logger: Optional[StatLoggerBase] = None |
78 | | - if self.log_stats: |
79 | | - self.stat_logger = PrometheusStatLogger(vllm_config) |
80 | 77 |
|
81 | 78 | executor_backend = ( |
82 | 79 | self.vllm_config.parallel_config.distributed_executor_backend) |
@@ -122,6 +119,15 @@ def __init__( |
122 | 119 | log_stats=self.log_stats, |
123 | 120 | ) |
124 | 121 |
|
| 122 | + self.logger_manager: Optional[StatLoggerManager] = None |
| 123 | + if self.log_stats: |
| 124 | + self.logger_manager = StatLoggerManager( |
| 125 | + vllm_config=vllm_config, |
| 126 | + custom_stat_loggers=stat_loggers, |
| 127 | + enable_default_loggers=log_stats, |
| 128 | + ) |
| 129 | + self.logger_manager.log_engine_initialized() |
| 130 | + |
125 | 131 | if not multiprocess_mode: |
126 | 132 | # for v0 compatibility |
127 | 133 | self.model_executor = self.engine_core.engine_core.model_executor # type: ignore |
@@ -269,10 +275,13 @@ def step(self) -> Union[list[RequestOutput], list[PoolingRequestOutput]]: |
269 | 275 | self.engine_core.abort_requests(processed_outputs.reqs_to_abort) |
270 | 276 |
|
271 | 277 | # 4) Record stats |
272 | | - if self.stat_logger is not None: |
| 278 | + if self.logger_manager is not None: |
273 | 279 | assert outputs.scheduler_stats is not None |
274 | | - self.stat_logger.record(scheduler_stats=outputs.scheduler_stats, |
275 | | - iteration_stats=iteration_stats) |
| 280 | + self.logger_manager.record( |
| 281 | + scheduler_stats=outputs.scheduler_stats, |
| 282 | + iteration_stats=iteration_stats, |
| 283 | + ) |
| 284 | + self.do_log_stats_with_interval() |
276 | 285 |
|
277 | 286 | return processed_outputs.request_outputs |
278 | 287 |
|
@@ -315,6 +324,20 @@ def get_tokenizer(self) -> AnyTokenizer: |
315 | 324 |
|
316 | 325 | return self.tokenizer |
317 | 326 |
|
| 327 | + def do_log_stats(self) -> None: |
| 328 | + """Log stats if logging is enabled.""" |
| 329 | + if self.logger_manager: |
| 330 | + self.logger_manager.log() |
| 331 | + |
| 332 | + def do_log_stats_with_interval(self) -> None: |
| 333 | + """Log stats when the time interval has passed.""" |
| 334 | + now = time.time() |
| 335 | + if not hasattr(self, "_last_log_time"): |
| 336 | + self._last_log_time = now |
| 337 | + if now - self._last_log_time >= envs.VLLM_LOG_STATS_INTERVAL: |
| 338 | + self.do_log_stats() |
| 339 | + self._last_log_time = now |
| 340 | + |
318 | 341 | def add_lora(self, lora_request: LoRARequest) -> bool: |
319 | 342 | """Load a new LoRA adapter into the engine for future requests.""" |
320 | 343 | return self.engine_core.add_lora(lora_request) |
|
0 commit comments