Skip to content

Commit affdcd5

Browse files
committed
add unit test for aibrix metrics collector
Signed-off-by: googs1025 <[email protected]>
1 parent be5d1b5 commit affdcd5

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed

python/aibrix/tests/test_metrics.py

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313
# limitations under the License.
1414
import pytest
1515

16+
from prometheus_client.core import CounterMetricFamily
17+
from unittest.mock import MagicMock, patch
18+
1619
from aibrix.metrics.engine_rules import get_metric_standard_rules
20+
from aibrix.metrics.http_collector import HTTPCollector
21+
from aibrix.metrics.standard_rules import RenameStandardRule
1722

1823

1924
def test_get_metric_standard_rules_ignore_case():
@@ -33,3 +38,189 @@ def test_get_metric_standard_rules_not_support():
3338

3439
with pytest.raises(ValueError):
3540
get_metric_standard_rules("TensorRT-LLM")
41+
42+
43+
class TestRenameStandardRule:
44+
@staticmethod
45+
def create_sample_metric(
46+
name: str, value: float = 1.0, metric_type: str = "counter"
47+
):
48+
if metric_type == "counter":
49+
metric = CounterMetricFamily(name, f"Test {metric_type} metric for {name}")
50+
else:
51+
raise ValueError(f"Unsupported metric type: {metric_type}")
52+
metric.add_metric(labels=[], value=value)
53+
return metric
54+
55+
def test_rename(self):
56+
metric = self.create_sample_metric("old_metric_name")
57+
rule = RenameStandardRule(
58+
original_name="old_metric_name", new_name="new_metric_name"
59+
)
60+
61+
result = list(rule(metric))
62+
63+
assert len(result) == 1
64+
assert len(result[0].samples) == 1
65+
renamed_metric = result[0]
66+
assert renamed_metric.name == "new_metric_name"
67+
assert renamed_metric.samples[0].name == "new_metric_name_total"
68+
69+
def test_rename_with_prefix_suffix(self):
70+
metric = self.create_sample_metric("http_requests")
71+
rule = RenameStandardRule(
72+
original_name="http_requests", new_name="http_requests_renamed"
73+
)
74+
75+
result = list(rule(metric))
76+
77+
assert len(result) == 1
78+
assert len(result[0].samples) == 1
79+
renamed_metric = result[0]
80+
assert renamed_metric.name == "http_requests_renamed"
81+
assert renamed_metric.samples[0].name == "http_requests_renamed_total"
82+
83+
def test_assertion_on_name_mismatch(self):
84+
metric = self.create_sample_metric("wrong_metric_name")
85+
rule = RenameStandardRule(original_name="expected_name", new_name="new_name")
86+
87+
with pytest.raises(AssertionError) as exc_info:
88+
list(rule(metric))
89+
90+
assert "does not match Rule original name" in str(exc_info.value)
91+
92+
def test_multiple_samples(self):
93+
metric = CounterMetricFamily("old_metric", "Test multiple samples")
94+
metric.add_metric([], 1.0)
95+
metric.add_metric([], 2.0)
96+
97+
rule = RenameStandardRule(original_name="old_metric", new_name="new_metric")
98+
99+
result = list(rule(metric))
100+
101+
assert len(result) == 1
102+
assert len(result[0].samples) == 2
103+
renamed_metric = result[0]
104+
assert renamed_metric.name == "new_metric"
105+
assert renamed_metric.samples[0].name == "new_metric_total"
106+
assert renamed_metric.samples[1].name == "new_metric_total"
107+
108+
109+
class TestHTTPCollector:
110+
SAMPLE_METRICS_TEXT = """
111+
# HELP http_requests The total number of HTTP requests.
112+
# TYPE http_requests counter
113+
http_requests{job="api-server",instance="localhost:9090"} 100
114+
# HELP temperature_degrees Current temperature in degrees.
115+
# TYPE temperature_degrees gauge
116+
temperature_degrees{} 25.5
117+
"""
118+
119+
@patch("aibrix.metrics.http_collector.requests.Session")
120+
def test_collect_success(self, mock_session):
121+
# Arrange
122+
mock_response = MagicMock()
123+
mock_response.status_code = 200
124+
mock_response.text = self.SAMPLE_METRICS_TEXT
125+
mock_session.return_value.get.return_value = mock_response
126+
127+
metrics_rules = {
128+
"http_requests": RenameStandardRule(
129+
original_name="http_requests", new_name="http_requests_renamed"
130+
)
131+
}
132+
133+
collector = HTTPCollector(
134+
endpoint="http://fake.metrics.url",
135+
metrics_rules=metrics_rules,
136+
keep_original_metric=False,
137+
timeout=5,
138+
)
139+
140+
results = list(collector.collect())
141+
# Assert
142+
assert len(collector.metrics_rules) == 1
143+
144+
original_metric = next((m for m in results if m.name == "http_requests"), None)
145+
assert original_metric is None
146+
147+
renamed_metric = next(
148+
(m for m in results if m.name == "http_requests_renamed"), None
149+
)
150+
assert renamed_metric is not None
151+
assert renamed_metric.samples[0].name == "http_requests_renamed_total"
152+
153+
@patch("aibrix.metrics.http_collector.requests.Session")
154+
def test_collect_keep_original_metric(self, mock_session):
155+
# Arrange
156+
mock_response = MagicMock()
157+
mock_response.status_code = 200
158+
mock_response.text = self.SAMPLE_METRICS_TEXT
159+
mock_session.return_value.get.return_value = mock_response
160+
161+
metrics_rules = {
162+
"http_requests": RenameStandardRule(
163+
original_name="http_requests", new_name="http_requests_renamed"
164+
)
165+
}
166+
167+
collector = HTTPCollector(
168+
endpoint="http://fake.metrics.url",
169+
metrics_rules=metrics_rules,
170+
keep_original_metric=True,
171+
timeout=5,
172+
)
173+
174+
results = list(collector.collect())
175+
# Assert
176+
assert len(collector.metrics_rules) == 1
177+
178+
original_metric = next((m for m in results if m.name == "http_requests"), None)
179+
assert original_metric is None
180+
181+
renamed_metric = next(
182+
(m for m in results if m.name == "http_requests_renamed"), None
183+
)
184+
assert renamed_metric is not None
185+
186+
@patch("aibrix.metrics.http_collector.requests.Session")
187+
def test_collect_request_failure(self, mock_session):
188+
# Arrange
189+
mock_session.return_value.get.side_effect = Exception("Connection refused")
190+
191+
collector = HTTPCollector(
192+
endpoint="http://fake.metrics.url", metrics_rules={}, timeout=1
193+
)
194+
195+
results = list(collector.collect())
196+
# Assert
197+
assert len(results) == 0
198+
199+
@patch("aibrix.metrics.http_collector.requests.Session")
200+
def test_collect_non_200_response(self, mock_session):
201+
# Arrange
202+
mock_response = MagicMock()
203+
mock_response.status_code = 500
204+
mock_response.text = "Internal Server Error"
205+
mock_session.return_value.get.return_value = mock_response
206+
207+
collector = HTTPCollector(
208+
endpoint="http://fake.metrics.url", metrics_rules={}, timeout=5
209+
)
210+
211+
results = list(collector.collect())
212+
# Assert
213+
assert len(results) == 0
214+
215+
def test_empty_metrics_text(self):
216+
class FakeHTTPCollector(HTTPCollector):
217+
def _collect(self):
218+
return ""
219+
220+
collector = FakeHTTPCollector(
221+
endpoint="http://fake.metrics.url", metrics_rules={}
222+
)
223+
224+
results = list(collector.collect())
225+
# Assert
226+
assert len(results) == 0

0 commit comments

Comments
 (0)