From cf12070a0f8ceea5da4b67d6d73512ae93eb077b Mon Sep 17 00:00:00 2001 From: fzyzcjy <5236035+fzyzcjy@users.noreply.github.com> Date: Mon, 18 May 2026 18:42:34 +0800 Subject: [PATCH] Move idle-metrics logging to SchedulerMetricsReporter (#25631) --- python/sglang/srt/managers/scheduler.py | 6 +- .../scheduler_components/metrics_reporter.py | 43 ++++++++++++++ .../scheduler_runtime_checker_mixin.py | 56 ------------------- 3 files changed, 44 insertions(+), 61 deletions(-) delete mode 100644 python/sglang/srt/managers/scheduler_runtime_checker_mixin.py diff --git a/python/sglang/srt/managers/scheduler.py b/python/sglang/srt/managers/scheduler.py index 5712ef1c9..0e75c36eb 100644 --- a/python/sglang/srt/managers/scheduler.py +++ b/python/sglang/srt/managers/scheduler.py @@ -199,9 +199,6 @@ from sglang.srt.managers.scheduler_output_processor_mixin import ( ) from sglang.srt.managers.scheduler_pp_mixin import SchedulerPPMixin from sglang.srt.managers.scheduler_recv_skipper import SchedulerRecvSkipper -from sglang.srt.managers.scheduler_runtime_checker_mixin import ( - SchedulerRuntimeCheckerMixin, -) from sglang.srt.managers.utils import GenerationBatchResult, validate_input_length from sglang.srt.mem_cache import kv_cache_builder from sglang.srt.mem_cache.common import maybe_cache_unfinished_req, release_kv_cache @@ -361,7 +358,6 @@ class Scheduler( SchedulerDisaggregationDecodeMixin, SchedulerDisaggregationPrefillMixin, SchedulerMultiplexMixin, - SchedulerRuntimeCheckerMixin, SchedulerPPMixin, SchedulerDllmMixin, SchedulerMlxOverlapMixin, @@ -3188,7 +3184,7 @@ class Scheduler( self.invariant_checker._check_tree_cache() # metrics every 30s - self._maybe_log_idle_metrics() + self.metrics_reporter._maybe_log_idle_metrics() # kv event publishing self.kv_events_publisher.publish_kv_events() diff --git a/python/sglang/srt/managers/scheduler_components/metrics_reporter.py b/python/sglang/srt/managers/scheduler_components/metrics_reporter.py index 3f05bac45..c0a1b0d35 100644 --- a/python/sglang/srt/managers/scheduler_components/metrics_reporter.py +++ b/python/sglang/srt/managers/scheduler_components/metrics_reporter.py @@ -961,3 +961,46 @@ class SchedulerMetricsReporter: if ENABLE_METRICS_DEVICE_TIMER: self._device_timer_window_batch_count = 0 self.fwd_occupancy = float("nan") + + def _maybe_log_idle_metrics(self): + """Collect and log metrics every 30 seconds during idle.""" + if ( + not self.current_scheduler_metrics_enabled + or time.perf_counter() <= self.metrics_collector.last_log_time + 30 + ): + return + + self.scheduler.pool_stats_observer.get_pool_stats().update_scheduler_stats( + self.stats + ) + self.stats.num_streaming_sessions = ( + self.scheduler.pool_stats_observer.streaming_session_count() + ) + self.stats.streaming_session_held_tokens = ( + self.scheduler.pool_stats_observer.session_held_tokens() + ) + + priority_enabled = self.scheduler.enable_priority_scheduling + self.stats.num_running_reqs = QueueCount.from_reqs( + self.scheduler.running_batch.reqs, priority_enabled + ) + self.stats.gen_throughput = 0 + self.stats.num_queue_reqs = QueueCount.from_reqs( + self.scheduler.waiting_queue, priority_enabled + ) + self.stats.num_grammar_queue_reqs = len(self.scheduler.grammar_manager) + if self.scheduler.disaggregation_mode == DisaggregationMode.PREFILL: + self.stats.num_prefill_bootstrap_queue_reqs = QueueCount.from_reqs( + self.scheduler.disagg_prefill_bootstrap_queue.queue, priority_enabled + ) + self.stats.num_prefill_inflight_queue_reqs = QueueCount.from_reqs( + self.scheduler.disagg_prefill_inflight_queue, priority_enabled + ) + if self.scheduler.disaggregation_mode == DisaggregationMode.DECODE: + self.stats.num_decode_prealloc_queue_reqs = QueueCount.from_reqs( + self.scheduler.disagg_decode_prealloc_queue.queue, priority_enabled + ) + self.stats.num_decode_transfer_queue_reqs = QueueCount.from_reqs( + self.scheduler.disagg_decode_transfer_queue.queue, priority_enabled + ) + self.metrics_collector.log_stats(self.stats) diff --git a/python/sglang/srt/managers/scheduler_runtime_checker_mixin.py b/python/sglang/srt/managers/scheduler_runtime_checker_mixin.py deleted file mode 100644 index 10cbe4670..000000000 --- a/python/sglang/srt/managers/scheduler_runtime_checker_mixin.py +++ /dev/null @@ -1,56 +0,0 @@ -from __future__ import annotations - -import logging -import time -from typing import TYPE_CHECKING - -from sglang.srt.disaggregation.utils import DisaggregationMode -from sglang.srt.observability.metrics_collector import QueueCount - -if TYPE_CHECKING: - from sglang.srt.managers.scheduler import Scheduler - -logger = logging.getLogger(__name__) - - -class SchedulerRuntimeCheckerMixin: - def _maybe_log_idle_metrics(self: Scheduler): - """Collect and log metrics every 30 seconds during idle.""" - if ( - not self.current_scheduler_metrics_enabled - or time.perf_counter() <= self.metrics_collector.last_log_time + 30 - ): - return - - self.pool_stats_observer.get_pool_stats().update_scheduler_stats(self.stats) - self.stats.num_streaming_sessions = ( - self.pool_stats_observer.streaming_session_count() - ) - self.stats.streaming_session_held_tokens = ( - self.pool_stats_observer.session_held_tokens() - ) - - priority_enabled = self.enable_priority_scheduling - self.stats.num_running_reqs = QueueCount.from_reqs( - self.running_batch.reqs, priority_enabled - ) - self.stats.gen_throughput = 0 - self.stats.num_queue_reqs = QueueCount.from_reqs( - self.waiting_queue, priority_enabled - ) - self.stats.num_grammar_queue_reqs = len(self.grammar_manager) - if self.disaggregation_mode == DisaggregationMode.PREFILL: - self.stats.num_prefill_bootstrap_queue_reqs = QueueCount.from_reqs( - self.disagg_prefill_bootstrap_queue.queue, priority_enabled - ) - self.stats.num_prefill_inflight_queue_reqs = QueueCount.from_reqs( - self.disagg_prefill_inflight_queue, priority_enabled - ) - if self.disaggregation_mode == DisaggregationMode.DECODE: - self.stats.num_decode_prealloc_queue_reqs = QueueCount.from_reqs( - self.disagg_decode_prealloc_queue.queue, priority_enabled - ) - self.stats.num_decode_transfer_queue_reqs = QueueCount.from_reqs( - self.disagg_decode_transfer_queue.queue, priority_enabled - ) - self.metrics_collector.log_stats(self.stats)