Skip to content

Commit c41e6dd

Browse files
authored
Merge pull request #5 from numberly/tests/metrics
test(metrics): initial support
2 parents 6c0a11b + 88f575b commit c41e6dd

File tree

6 files changed

+198
-32
lines changed

6 files changed

+198
-32
lines changed

.pre-commit-config.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
default_language_version:
2+
python: python3.12
3+
4+
repos:
5+
- repo: https://github.com/pre-commit/pre-commit-hooks
6+
rev: v4.4.0
7+
hooks:
8+
- id: trailing-whitespace # Trims trailing whitespace.
9+
- id: end-of-file-fixer # Makes sure files end in a newline and only a newline.
10+
- id: check-added-large-files # Prevent giant files from being committed.
11+
- id: requirements-txt-fixer
12+
- id: check-merge-conflict
13+
14+
- repo: https://github.com/commitizen-tools/commitizen
15+
rev: v3.5.3
16+
hooks:
17+
- id: commitizen
18+
stages:
19+
- commit-msg
20+
21+
- repo: https://github.com/astral-sh/ruff-pre-commit
22+
rev: v0.8.1
23+
hooks:
24+
- id: ruff
25+
args: [--fix]
26+
- id: ruff-format
27+
28+
- repo: https://github.com/pre-commit/mirrors-mypy
29+
rev: v1.13.0
30+
hooks:
31+
- id: mypy
32+
entry: mypy
33+
files: send/
34+
language: system
35+
args: [--install-types, --non-interactive]

Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,3 @@ USER nobody:nogroup
1818
EXPOSE 8000
1919

2020
CMD ["python", "typesense_exporter.py", "--port=8000"]
21-

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,3 @@ This design guarantees that metrics are always up-to-date at scrape time (with n
8282
## License
8383

8484
This exporter is released under the MIT License. See LICENSE for details (or replace with your preferred license).
85-

requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mypy>=1.14
2+
pytest>=7.0
23
pytest-asyncio>=0.23.5
34
pytest-cov>=4.1
4-
pytest>=7.0
5+
requests-mock==1.12.1
56
types-requests>=2.32

tests/conftest.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import pytest
2+
from typesense_exporter import TypesenseCollector
3+
4+
5+
@pytest.fixture
6+
def response_metrics_json():
7+
yield {
8+
"system_cpu1_active_percentage": "9.09",
9+
"system_cpu2_active_percentage": "0.00",
10+
"system_cpu3_active_percentage": "0.00",
11+
"system_cpu4_active_percentage": "0.00",
12+
"system_cpu_active_percentage": "0.00",
13+
"system_disk_total_bytes": "102888095744",
14+
"system_disk_used_bytes": "4177268736",
15+
"system_memory_total_bytes": "16764186624",
16+
"system_memory_total_swap_bytes": "0",
17+
"system_memory_used_bytes": "3234148352",
18+
"system_memory_used_swap_bytes": "0",
19+
"system_network_received_bytes": "6534814741",
20+
"system_network_sent_bytes": "4613106962",
21+
"typesense_memory_active_bytes": "51126272",
22+
"typesense_memory_allocated_bytes": "43065104",
23+
"typesense_memory_fragmentation_ratio": "0.16",
24+
"typesense_memory_mapped_bytes": "97370112",
25+
"typesense_memory_metadata_bytes": "9009280",
26+
"typesense_memory_resident_bytes": "51126272",
27+
"typesense_memory_retained_bytes": "30556160",
28+
}
29+
30+
31+
@pytest.fixture
32+
def response_stats_json():
33+
yield {
34+
"delete_latency_ms": 0,
35+
"delete_requests_per_second": 0,
36+
"import_latency_ms": 0,
37+
"import_requests_per_second": 0,
38+
"latency_ms": {"GET /health": 0.0, "GET /status": 0.0},
39+
"overloaded_requests_per_second": 0,
40+
"pending_write_batches": 0,
41+
"requests_per_second": {"GET /health": 1.5, "GET /status": 0.6},
42+
"search_latency_ms": 0,
43+
"search_requests_per_second": 0,
44+
"total_requests_per_second": 2.1,
45+
"write_latency_ms": 0,
46+
"write_requests_per_second": 0,
47+
}
48+
49+
50+
@pytest.fixture
51+
def response_debug_json():
52+
yield {"state": 1, "version": "0.24.0"}
53+
54+
55+
@pytest.fixture
56+
def response_collections_json():
57+
yield [
58+
{"name": "products", "num_documents": 100},
59+
{"name": "users", "num_documents": 50},
60+
]
61+
62+
63+
@pytest.fixture(autouse=True)
64+
def mock_typesense_api(
65+
requests_mock,
66+
response_metrics_json,
67+
response_stats_json,
68+
response_debug_json,
69+
response_collections_json,
70+
):
71+
base_url = "http://localhost:8108"
72+
73+
requests_mock.get(f"{base_url}/metrics.json", json=response_metrics_json)
74+
requests_mock.get(f"{base_url}/stats.json", json=response_stats_json)
75+
requests_mock.get(f"{base_url}/debug", json=response_debug_json)
76+
requests_mock.get(f"{base_url}/collections", json=response_collections_json)
77+
78+
yield requests_mock
79+
80+
81+
@pytest.fixture
82+
def typesense_collector():
83+
return TypesenseCollector(
84+
typesense_api_key="123",
85+
metrics_url="http://localhost:8108/metrics.json",
86+
stats_url="http://localhost:8108/stats.json",
87+
debug_url="http://localhost:8108/debug",
88+
nodes=[{"host": "localhost", "port": "8108", "protocol": "http"}],
89+
)

tests/test_typesense_exporter.py

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,79 @@
22
from typesense_exporter import parse_nodes_from_str
33

44

5-
@pytest.mark.parametrize("test_input,expected,protocol,description", [
6-
(
7-
"localhost:8108",
8-
[{"host": "localhost", "port": "8108", "protocol": "https"}],
9-
"https",
10-
"single node with port"
11-
),
12-
(
13-
"host1:8108,host2:8108",
14-
[
15-
{"host": "host1", "port": "8108", "protocol": "https"},
16-
{"host": "host2", "port": "8108", "protocol": "https"}
17-
],
18-
"https",
19-
"multiple nodes"
20-
),
21-
(
22-
"localhost",
23-
[{"host": "localhost", "port": "8108", "protocol": "https"}],
24-
"https",
25-
"default port"
26-
),
27-
(
28-
"localhost:8108",
29-
[{"host": "localhost", "port": "8108", "protocol": "http"}],
30-
"http",
31-
"custom protocol"
32-
),
33-
])
5+
@pytest.mark.parametrize(
6+
"test_input,expected,protocol,description",
7+
[
8+
(
9+
"localhost:8108",
10+
[{"host": "localhost", "port": "8108", "protocol": "https"}],
11+
"https",
12+
"single node with port",
13+
),
14+
(
15+
"host1:8108,host2:8108",
16+
[
17+
{"host": "host1", "port": "8108", "protocol": "https"},
18+
{"host": "host2", "port": "8108", "protocol": "https"},
19+
],
20+
"https",
21+
"multiple nodes",
22+
),
23+
(
24+
"localhost",
25+
[{"host": "localhost", "port": "8108", "protocol": "https"}],
26+
"https",
27+
"default port",
28+
),
29+
(
30+
"localhost:8108",
31+
[{"host": "localhost", "port": "8108", "protocol": "http"}],
32+
"http",
33+
"custom protocol",
34+
),
35+
],
36+
)
3437
def test_parse_nodes_from_str(test_input, expected, protocol, description):
3538
nodes = parse_nodes_from_str(test_input, default_protocol=protocol)
3639
assert len(nodes) == len(expected)
3740
assert nodes == expected
41+
42+
43+
def test_typesense_collector_metrics(typesense_collector):
44+
metrics = list(typesense_collector._collect_metrics_json())
45+
assert len(metrics) == 20
46+
47+
48+
def test_typesense_collector_stats(typesense_collector):
49+
metrics = list(typesense_collector._collect_stats_json())
50+
assert len(metrics) == 13
51+
52+
53+
def test_typesense_collector_json(typesense_collector):
54+
metrics = list(typesense_collector._collect_debug_json())
55+
assert len(metrics) == 1
56+
57+
58+
def test_typesense_collector_collections(typesense_collector):
59+
metrics = list(typesense_collector._collect_collections())
60+
assert len(metrics) == 1
61+
62+
metric_family = metrics[0]
63+
assert metric_family.name == "typesense_collection_documents"
64+
assert (
65+
metric_family.documentation
66+
== "Number of documents in each Typesense collection"
67+
)
68+
69+
assert len(metric_family.samples) == 2
70+
71+
sample_1 = metric_family.samples[0]
72+
sample_2 = metric_family.samples[1]
73+
74+
assert sample_1.name == "typesense_collection_documents"
75+
assert sample_1.labels == {"collection_name": "products"}
76+
assert sample_1.value == 100.0
77+
78+
assert sample_2.name == "typesense_collection_documents"
79+
assert sample_2.labels == {"collection_name": "users"}
80+
assert sample_2.value == 50.0

0 commit comments

Comments
 (0)