diff --git a/python/sglang/srt/constrained/base_grammar_backend.py b/python/sglang/srt/constrained/base_grammar_backend.py index dda3fab4f..1144bb17c 100644 --- a/python/sglang/srt/constrained/base_grammar_backend.py +++ b/python/sglang/srt/constrained/base_grammar_backend.py @@ -36,6 +36,7 @@ class GrammarStats: is_grammar_aborted: bool = False tree_traversal_time: List[float] = field(default_factory=list) dispatch_type: Optional[str] = None + num_timeout: int = 0 class BaseGrammarObject: diff --git a/python/sglang/srt/metrics/collector.py b/python/sglang/srt/metrics/collector.py index 69d7dafc5..b4af2288f 100644 --- a/python/sglang/srt/metrics/collector.py +++ b/python/sglang/srt/metrics/collector.py @@ -488,6 +488,11 @@ class SchedulerMetricsCollector: documentation="Number of grammar aborted requests.", labelnames=labels.keys(), ) + self.num_grammar_timeout = Counter( + name="sglang:num_grammar_timeout_total", + documentation="Number of grammar timeouts.", + labelnames=labels.keys(), + ) self.num_grammar_total = Counter( name="sglang:num_grammar_total", documentation="Number of the total grammar requests.", @@ -683,25 +688,28 @@ class SchedulerMetricsCollector: self.last_log_time = time.perf_counter() def log_grammar_stats(self, grammar_stats) -> None: - # Duck-typed GrammarStats to avoid cross-package dependency - if getattr(grammar_stats, "compilation_time", None) is not None: + if grammar_stats.compilation_time is not None: self._log_histogram( self.grammar_compilation_time, grammar_stats.compilation_time ) - if getattr(grammar_stats, "schema_count", None) is not None: + if grammar_stats.schema_count is not None: self._log_histogram(self.grammar_schema_count, grammar_stats.schema_count) - if getattr(grammar_stats, "ebnf_size", None) is not None: + if grammar_stats.ebnf_size is not None: self._log_histogram(self.grammar_ebnf_size, grammar_stats.ebnf_size) - tree_times = getattr(grammar_stats, "tree_traversal_time", None) + tree_times = grammar_stats.tree_traversal_time if tree_times: max_time = max(tree_times) avg_time = sum(tree_times) / len(tree_times) self._log_histogram(self.grammar_tree_traversal_time_max, max_time) self._log_histogram(self.grammar_tree_traversal_time_avg, avg_time) - if getattr(grammar_stats, "is_cache_hit", False): + if grammar_stats.is_cache_hit: self.num_grammar_cache_hit.labels(**self.labels).inc(1) - if getattr(grammar_stats, "is_grammar_aborted", False): + if grammar_stats.is_grammar_aborted: self.num_grammar_aborted.labels(**self.labels).inc(1) + if grammar_stats.num_timeout > 0: + self.num_grammar_timeout.labels(**self.labels).inc( + grammar_stats.num_timeout + ) self.num_grammar_total.labels(**self.labels).inc(1)