diff --git a/python/sglang/srt/observability/scheduler_metrics_mixin.py b/python/sglang/srt/observability/scheduler_metrics_mixin.py index b161d9b51..392c5ca51 100644 --- a/python/sglang/srt/observability/scheduler_metrics_mixin.py +++ b/python/sglang/srt/observability/scheduler_metrics_mixin.py @@ -116,9 +116,16 @@ class SchedulerMetricsMixin: # Metrics self.enable_metrics = self.server_args.enable_metrics - self.is_stats_logging_rank = self.attn_tp_rank == 0 + # Under CP, attn_cp_size shards the TP group so attn_tp_size collapses to 1 and + # attn_tp_rank == 0 on EVERY CP rank. Gate on (attn_tp_rank == 0 AND attn_cp_rank == 0) + # -- matching the scheduler's other single-rank guards -- so exactly one rank logs / + # emits scheduler-side metrics; otherwise all attn_cp_size ranks would each report, + # inflating summed token-throughput / SchedulerStats by cp_size. No-op when CP is off + # (attn_cp_rank is always 0 there). + self.is_stats_logging_rank = self.attn_tp_rank == 0 and self.attn_cp_rank == 0 self.current_scheduler_metrics_enabled = self.enable_metrics and ( - self.attn_tp_rank == 0 or self.server_args.enable_metrics_for_all_schedulers + (self.attn_tp_rank == 0 and self.attn_cp_rank == 0) + or self.server_args.enable_metrics_for_all_schedulers ) if self.enable_metrics: if self.server_args.disaggregation_mode == DisaggregationMode.PREFILL.value: