Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions python/kthena/runtime/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ class EngineType(Enum):


class StandardMetricNames:
GENERATION_TOKENS_TOTAL = "kthena:generation_tokens_total"
# The runtime's parser munges counter families into their OpenMetrics
# form: the FAMILY name loses the _total suffix while samples keep it.
# Rules are matched by family name, so the counter rule is keyed by the
# munged family and RenameMetric's suffix arithmetic restores _total on
# the exposed samples, yielding the documented
# kthena:generation_tokens_total series.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary to write such complicated comments

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 remove these

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

GENERATION_TOKENS = "kthena:generation_tokens"
NUM_REQUESTS_WAITING = "kthena:num_requests_waiting"
TIME_TO_FIRST_TOKEN_SECONDS = "kthena:time_to_first_token_seconds"
TIME_PER_OUTPUT_TOKEN_SECONDS = "kthena:time_per_output_token_seconds"
Expand All @@ -36,8 +42,8 @@ class StandardMetricNames:
STANDARD_RULES: Dict[str, List[MetricOperator]] = {
EngineType.VLLM.value: [
RenameMetric(
"vllm:generation_tokens_total",
StandardMetricNames.GENERATION_TOKENS_TOTAL,
"vllm:generation_tokens",
StandardMetricNames.GENERATION_TOKENS,
),
RenameMetric(
"vllm:num_requests_waiting", StandardMetricNames.NUM_REQUESTS_WAITING
Expand All @@ -57,8 +63,8 @@ class StandardMetricNames:
],
EngineType.SGLANG.value: [
RenameMetric(
"sglang:generation_tokens_total",
StandardMetricNames.GENERATION_TOKENS_TOTAL,
"sglang:generation_tokens",
StandardMetricNames.GENERATION_TOKENS,
),
RenameMetric("sglang:num_queue_reqs", StandardMetricNames.NUM_REQUESTS_WAITING),
RenameMetric(
Expand Down
52 changes: 52 additions & 0 deletions python/kthena/tests/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,55 @@ def test_metric_adapter_handles_empty_metrics():

adapter = MetricAdapter(empty_metric_text, standard)
assert len(adapter.metrics) == 0
VLLM_COUNTER_METRICS = """
# HELP vllm:generation_tokens_total Number of generation tokens processed.
# TYPE vllm:generation_tokens_total counter
vllm:generation_tokens_total{model_name="m"} 42.0
""".strip()

SGLANG_COUNTER_METRICS = """
# HELP sglang:generation_tokens_total Number of generation tokens processed.
# TYPE sglang:generation_tokens_total counter
sglang:generation_tokens_total{model_name="m"} 7.0
""".strip()


def _standardized(adapter, name):
return [m for m in adapter.metrics if m.name == name]


def test_vllm_counter_rename_survives_parser_family_munging():
# The parser strips _total from a counter FAMILY name, so the rule must
# match the munged family and the samples must come back out with _total.
standard = MetricStandard("vllm")
adapter = MetricAdapter(VLLM_COUNTER_METRICS, standard)

twins = _standardized(adapter, "kthena:generation_tokens")
assert len(twins) == 1, [m.name for m in adapter.metrics]
twin = twins[0]
assert twin.type == "counter"
sample_names = [s.name for s in twin.samples]
assert "kthena:generation_tokens_total" in sample_names
total = next(s for s in twin.samples if s.name == "kthena:generation_tokens_total")
assert total.value == 42.0
assert total.labels == {"model_name": "m"}


def test_sglang_counter_rename_survives_parser_family_munging():
standard = MetricStandard("sglang")
adapter = MetricAdapter(SGLANG_COUNTER_METRICS, standard)

twins = _standardized(adapter, "kthena:generation_tokens")
assert len(twins) == 1, [m.name for m in adapter.metrics]
sample_names = [s.name for s in twins[0].samples]
assert "kthena:generation_tokens_total" in sample_names


def test_process_metrics_exposes_documented_counter_series():
import asyncio

from kthena.runtime.collect import process_metrics

standard = MetricStandard("vllm")
output = asyncio.run(process_metrics(VLLM_COUNTER_METRICS, standard))
assert b'kthena:generation_tokens_total{model_name="m"} 42.0' in output
Loading