Skip to content

Commit d089c46

Browse files
authored
Merge pull request #307 from titouanfreville/master
feat: Add support for `/series` endpoint
2 parents 330400b + 0cdc932 commit d089c46

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

prometheus_api_client/prometheus_connect.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,42 @@ def all_metrics(self, params: dict = None):
117117
self._all_metrics = self.get_label_values(label_name="__name__", params=params)
118118
return self._all_metrics
119119

120+
121+
def get_series(self, start: datetime, end: datetime, params: dict = None):
122+
"""
123+
Get a list series happening between start and end times.
124+
125+
:param start: (int) Start time unix ts
126+
:param end: (int) End time unix ts
127+
:param params: (dict) Optional dictionary containing GET parameters to be
128+
sent along with the API request, such as "start", "end" or "match[]".
129+
:returns: (list) A list of labels from the specified prometheus host
130+
:raises:
131+
(RequestException) Raises an exception in case of a connection error
132+
(PrometheusApiClientException) Raises in case of non 200 response status code
133+
"""
134+
params = params or {}
135+
params["start"] = start.timestamp()
136+
params["end"] = end.timestamp()
137+
response = self._session.get(
138+
"{0}/api/v1/series".format(self.url),
139+
verify=self._session.verify,
140+
headers=self.headers,
141+
params=params,
142+
auth=self.auth,
143+
cert=self._session.cert,
144+
timeout=self._timeout,
145+
)
146+
147+
if response.status_code == 200:
148+
labels = response.json()["data"]
149+
else:
150+
raise PrometheusApiClientException(
151+
"HTTP Status Code {} ({!r})".format(response.status_code, response.content)
152+
)
153+
return labels
154+
155+
120156
def get_label_names(self, params: dict = None):
121157
"""
122158
Get a list of all labels.

tests/test_prometheus_connect.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ def test_get_label_names_method(self): # noqa D102
139139
self.assertEqual(len(labels), 3)
140140
self.assertEqual(labels, ["__name__", "instance", "job"])
141141

142+
def test_get_series(self): # noqa D102
143+
start_time = datetime.now() - timedelta(hours=1)
144+
end_time = datetime.now()
145+
series = self.pc.get_series(start=start_time, end=end_time, params={"match[]": "up"})
146+
self.assertIsInstance(series, list)
147+
self.assertTrue(len(series) > 0, "no series data received from prometheus")
148+
# Verify that each series entry is a dict with labels
149+
for series_entry in series:
150+
self.assertIsInstance(series_entry, dict)
151+
self.assertIn("__name__", series_entry)
152+
142153
def test_get_scrape_pools(self): # noqa D102
143154
scrape_pools = self.pc.get_scrape_pools()
144155
self.assertIsInstance(scrape_pools, list)
@@ -251,6 +262,10 @@ def test_broken_responses(self): # noqa D102
251262
self.pc.get_label_values("label_name")
252263
self.assertEqual("HTTP Status Code 403 (b'BOOM!')", str(exc.exception))
253264

265+
with self.assertRaises(PrometheusApiClientException) as exc:
266+
self.pc.get_series(start=datetime.now() - timedelta(hours=1), end=datetime.now())
267+
self.assertEqual("HTTP Status Code 403 (b'BOOM!')", str(exc.exception))
268+
254269
with self.assertRaises(PrometheusApiClientException) as exc:
255270
self.pc.get_current_metric_value("metric")
256271
self.assertEqual("HTTP Status Code 403 (b'BOOM!')", str(exc.exception))
@@ -284,6 +299,25 @@ def test_all_metrics_method(self): # noqa D102
284299
request = handler.requests[0]
285300
self.assertEqual(request.path_url, "/api/v1/label/__name__/values")
286301

302+
303+
def test_get_series_method(self): # noqa D102
304+
series_payload = {"status": "success", "data": [
305+
{"__name__": "up", "job": "prometheus", "instance": "localhost:9090"},
306+
{"__name__": "up", "job": "node", "instance": "localhost:9100"}
307+
]}
308+
309+
with self.mock_response(series_payload) as handler:
310+
start_time = datetime.now() - timedelta(hours=1)
311+
end_time = datetime.now()
312+
result = self.pc.get_series(start=start_time, end=end_time)
313+
self.assertTrue(len(result) > 0)
314+
self.assertEqual(handler.call_count, 1)
315+
request = handler.requests[0]
316+
self.assertTrue(request.path_url.startswith("/api/v1/series"))
317+
# Verify that start and end parameters are included
318+
self.assertIn("start", request.url)
319+
self.assertIn("end", request.url)
320+
287321
def test_get_label_names_method(self): # noqa D102
288322
all_metrics_payload = {"status": "success", "data": ["value1", "value2"]}
289323

0 commit comments

Comments
 (0)