132 lines
4.8 KiB
Python
132 lines
4.8 KiB
Python
"""Lane metrics registry semantics and the pod-local scrape endpoint."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
from testing.tests.test_hermes_cli_support import lanes
|
|
|
|
|
|
def test_registry_renders_counters_and_gauges_with_stable_labels():
|
|
registry = lanes.LaneMetricsRegistry()
|
|
registry.increment(
|
|
"hermes_cli_route_decisions_total",
|
|
{"provider": "codex", "effort": "high", "classifier": "c", "outcome": "completed"},
|
|
)
|
|
registry.increment(
|
|
"hermes_cli_route_decisions_total",
|
|
{"provider": "codex", "effort": "high", "classifier": "c", "outcome": "completed"},
|
|
)
|
|
registry.increment("hermes_cli_quota_fetch_failures_total")
|
|
registry.set_value(
|
|
"hermes_cli_quota_remaining_percent", {"provider": 'we"ird\n\\'}, 12.5
|
|
)
|
|
rendered = registry.render().decode("utf-8")
|
|
|
|
assert "# TYPE hermes_cli_route_decisions_total counter" in rendered
|
|
assert "# TYPE hermes_cli_quota_remaining_percent gauge" in rendered
|
|
assert (
|
|
'hermes_cli_route_decisions_total{classifier="c",effort="high",'
|
|
'outcome="completed",provider="codex"} 2' in rendered
|
|
)
|
|
assert "hermes_cli_quota_fetch_failures_total 1" in rendered
|
|
assert (
|
|
'hermes_cli_quota_remaining_percent{provider="we\\"ird\\n\\\\"} 12.5'
|
|
in rendered
|
|
)
|
|
|
|
|
|
def test_recording_helpers_feed_the_shared_registry():
|
|
lanes.record_route_decision("codex", "xhigh", "metrics-test", "completed")
|
|
lanes.record_provider_fallback("codex", "claude", "rate-limit")
|
|
lanes.record_router_selection_failure()
|
|
lanes.record_quota_fetch_failure()
|
|
lanes.record_provider_quota("metrics-test-provider", 42.0, 777.0)
|
|
lanes.record_provider_quota("metrics-test-no-reset", 41.0, None)
|
|
lanes.record_soft_exclusion("metrics-test-provider", True)
|
|
rendered = lanes.METRICS.render().decode("utf-8")
|
|
|
|
assert (
|
|
'hermes_cli_route_decisions_total{classifier="metrics-test",'
|
|
'effort="xhigh",outcome="completed",provider="codex"} 1' in rendered
|
|
)
|
|
assert (
|
|
'hermes_cli_provider_fallbacks_total{from_provider="codex",'
|
|
'reason="rate-limit",to_provider="claude"}' in rendered
|
|
)
|
|
assert "hermes_cli_router_selection_failures_total" in rendered
|
|
assert "hermes_cli_quota_fetch_failures_total" in rendered
|
|
assert (
|
|
'hermes_cli_quota_remaining_percent{provider="metrics-test-provider"} 42'
|
|
in rendered
|
|
)
|
|
assert (
|
|
'hermes_cli_quota_reset_timestamp_seconds{provider="metrics-test-provider"} 777'
|
|
in rendered
|
|
)
|
|
assert (
|
|
'hermes_cli_quota_reset_timestamp_seconds{provider="metrics-test-no-reset"}'
|
|
not in rendered
|
|
)
|
|
assert (
|
|
'hermes_cli_provider_soft_excluded{provider="metrics-test-provider"} 1'
|
|
in rendered
|
|
)
|
|
|
|
|
|
def test_metrics_server_serves_scrapes_health_and_rejects_unknown_paths():
|
|
server = lanes.start_metrics_server(0)
|
|
assert server is not None
|
|
try:
|
|
port = server.server_address[1]
|
|
lanes.record_route_decision("codex", "low", "scrape-test", "completed")
|
|
with urllib.request.urlopen(f"http://127.0.0.1:{port}/metrics") as response:
|
|
assert response.status == 200
|
|
assert b'classifier="scrape-test"' in response.read()
|
|
with urllib.request.urlopen(f"http://127.0.0.1:{port}/healthz") as response:
|
|
assert response.status == 200
|
|
try:
|
|
urllib.request.urlopen(f"http://127.0.0.1:{port}/nope")
|
|
raise AssertionError("unknown paths must 404")
|
|
except urllib.error.HTTPError as error:
|
|
assert error.code == 404
|
|
finally:
|
|
server.shutdown()
|
|
server.server_close()
|
|
|
|
|
|
def test_metrics_server_reads_port_from_environment(monkeypatch):
|
|
monkeypatch.setenv("HERMES_CLI_LANE_METRICS_PORT", "0")
|
|
server = lanes.start_metrics_server()
|
|
assert server is not None
|
|
server.shutdown()
|
|
server.server_close()
|
|
|
|
|
|
def test_metrics_server_reports_in_process_readiness_failure():
|
|
server = lanes.start_metrics_server(0, health_check=lambda: False)
|
|
assert server is not None
|
|
try:
|
|
port = server.server_address[1]
|
|
try:
|
|
urllib.request.urlopen(f"http://127.0.0.1:{port}/healthz")
|
|
raise AssertionError("failed lane readiness must return 503")
|
|
except urllib.error.HTTPError as error:
|
|
assert error.code == 503
|
|
finally:
|
|
server.shutdown()
|
|
server.server_close()
|
|
|
|
|
|
def test_metrics_server_declines_conflicting_port(capsys):
|
|
first = lanes.start_metrics_server(0)
|
|
assert first is not None
|
|
try:
|
|
second = lanes.start_metrics_server(first.server_address[1])
|
|
assert second is None
|
|
assert "metrics server unavailable" in capsys.readouterr().err
|
|
finally:
|
|
first.shutdown()
|
|
first.server_close()
|