Skip to content

Commit 7471c5e

Browse files
author
RiviaAzusa
committed
feat: Add new Prometheus target and metadata API endpoints
Add four new methods to PrometheusConnect class: - get_scrape_pools(): Retrieve list of unique scrape pool names - get_targets(): Get active/dropped targets with optional state and pool filters - get_target_metadata(): Fetch metadata about metrics from specific targets - get_metric_metadata(): Get metadata about metrics with optional filtering These additions provide better visibility into Prometheus targets and metric metadata, enabling more detailed monitoring and configuration analysis.
1 parent 9a94bab commit 7471c5e

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

prometheus_api_client/prometheus_connect.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,145 @@ def get_metric_aggregation(
561561
else:
562562
raise TypeError("Invalid operation: " + operation)
563563
return aggregated_values
564+
565+
566+
def get_scrape_pools(self) -> list[str]:
567+
"""
568+
Get a list of all scrape pools in activeTargets.
569+
"""
570+
scrape_pools = []
571+
for target in self.get_targets()['activeTargets']:
572+
scrape_pools.append(target['scrapePool'])
573+
return list(set(scrape_pools))
574+
575+
def get_targets(self, state: str = None, scrape_pool: str = None):
576+
"""
577+
Get a list of all targets from Prometheus.
578+
579+
:param state: (str) Optional filter for target state ('active', 'dropped', 'any').
580+
If None, returns both active and dropped targets.
581+
:param scrape_pool: (str) Optional filter by scrape pool name
582+
:returns: (dict) A dictionary containing active and dropped targets
583+
:raises:
584+
(RequestException) Raises an exception in case of a connection error
585+
(PrometheusApiClientException) Raises in case of non 200 response status code
586+
"""
587+
params = {}
588+
if state:
589+
params['state'] = state
590+
if scrape_pool:
591+
params['scrapePool'] = scrape_pool
592+
593+
response = self._session.get(
594+
"{0}/api/v1/targets".format(self.url),
595+
verify=self._session.verify,
596+
headers=self.headers,
597+
params=params,
598+
auth=self.auth,
599+
cert=self._session.cert,
600+
timeout=self._timeout,
601+
)
602+
603+
if response.status_code == 200:
604+
return response.json()["data"]
605+
else:
606+
raise PrometheusApiClientException(
607+
"HTTP Status Code {} ({!r})".format(
608+
response.status_code, response.content)
609+
)
610+
611+
def get_target_metadata(self, target: dict[str, str], metric: str = None, limit: int = None):
612+
"""
613+
Get metadata about metrics from a specific target.
614+
615+
:param target: (dict) A dictionary containing target labels to match against (e.g. {'job': 'prometheus'})
616+
:param metric: (str) Optional metric name to filter metadata
617+
:param limit: (int) Optional maximum number of targets to match
618+
:returns: (list) A list of metadata entries for matching targets
619+
:raises:
620+
(RequestException) Raises an exception in case of a connection error
621+
(PrometheusApiClientException) Raises in case of non 200 response status code
622+
"""
623+
params = {}
624+
625+
# Convert target dict to label selector string
626+
if metric:
627+
params['metric'] = metric
628+
629+
if target:
630+
match_target = "{" + \
631+
",".join(f'{k}="{v}"' for k, v in target.items()) + "}"
632+
params['match_target'] = match_target
633+
634+
if limit:
635+
params['limit'] = limit
636+
637+
response = self._session.get(
638+
"{0}/api/v1/targets/metadata".format(self.url),
639+
verify=self._session.verify,
640+
headers=self.headers,
641+
params=params,
642+
auth=self.auth,
643+
cert=self._session.cert,
644+
timeout=self._timeout,
645+
)
646+
647+
if response.status_code == 200:
648+
return response.json()["data"]
649+
else:
650+
raise PrometheusApiClientException(
651+
"HTTP Status Code {} ({!r})".format(
652+
response.status_code, response.content)
653+
)
654+
655+
def get_metric_metadata(self, metric: str, limit: int = None, limit_per_metric: int = None):
656+
"""
657+
Get metadata about metrics.
658+
659+
:param metric: (str) Optional metric name to filter metadata
660+
:param limit: (int) Optional maximum number of metrics to return
661+
:param limit_per_metric: (int) Optional maximum number of metadata entries per metric
662+
:returns: (dict) A dictionary mapping metric names to lists of metadata entries in format:
663+
{'metric_name': [{'type': str, 'help': str, 'unit': str}, ...]}
664+
:raises:
665+
(RequestException) Raises an exception in case of a connection error
666+
(PrometheusApiClientException) Raises in case of non 200 response status code
667+
"""
668+
params = {}
669+
670+
if metric:
671+
params['metric'] = metric
672+
673+
if limit:
674+
params['limit'] = limit
675+
676+
if limit_per_metric:
677+
params['limit_per_metric'] = limit_per_metric
678+
679+
response = self._session.get(
680+
"{0}/api/v1/metadata".format(self.url),
681+
verify=self._session.verify,
682+
headers=self.headers,
683+
params=params,
684+
auth=self.auth,
685+
cert=self._session.cert,
686+
timeout=self._timeout,
687+
)
688+
689+
if response.status_code == 200:
690+
data = response.json()["data"]
691+
formatted_data = []
692+
for k, v in data.items():
693+
for v_ in v:
694+
formatted_data.append({
695+
"metric_name": k,
696+
"type": v_.get('type', 'unknown'),
697+
"help": v_.get('help', ''),
698+
"unit": v_.get('unit', '')
699+
})
700+
return formatted_data
701+
else:
702+
raise PrometheusApiClientException(
703+
"HTTP Status Code {} ({!r})".format(
704+
response.status_code, response.content)
705+
)

0 commit comments

Comments
 (0)