Skip to content

Commit 25e5b7c

Browse files
authored
Merge pull request #20 from abyrne55/more_params
Added optional argument for GET params to all query functions + style fixes
2 parents d39ce58 + b95ae7b commit 25e5b7c

File tree

1 file changed

+89
-73
lines changed

1 file changed

+89
-73
lines changed

prometheus_api_client/prometheus_connect.py

+89-73
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,49 @@
1616

1717
# In case of a connection failure try 2 more times
1818
MAX_REQUEST_RETRIES = 3
19-
CONNECTION_RETRY_WAIT_TIME = 1000 # wait 1 second before retrying in case of an error
19+
# wait 1 second before retrying in case of an error
20+
CONNECTION_RETRY_WAIT_TIME = 1000
21+
2022

2123
class PrometheusConnect:
2224
"""
2325
A Class for collection of metrics from a Prometheus Host
2426
2527
:param url: (str) url for the prometheus host
26-
:param headers: (dict) A dictionary of http headers to be used to communicate with the host.
27-
Example: {"Authorization": "bearer my_oauth_token_to_the_host"}
28+
:param headers: (dict) A dictionary of http headers to be used to communicate with
29+
the host. Example: {"Authorization": "bearer my_oauth_token_to_the_host"}
2830
:param disable_ssl: (bool) If set to True, will disable ssl certificate verification
29-
for the http requests made to the prometheus host
30-
31+
for the http requests made to the prometheus host
3132
"""
32-
def __init__(self, url='http://127.0.0.1:9090', headers=None, disable_ssl=False):
33+
34+
def __init__(self, url: str = 'http://127.0.0.1:9090',
35+
headers: dict = None, disable_ssl: bool = False):
3336
"""
3437
Constructor for the class PrometheusConnect
35-
3638
"""
3739
self.headers = headers
3840
self.url = url
3941
self.prometheus_host = urlparse(self.url).netloc
4042
self._all_metrics = None
4143
self.ssl_verification = (not disable_ssl)
4244

43-
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES, wait_fixed=CONNECTION_RETRY_WAIT_TIME)
44-
def all_metrics(self):
45+
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES,
46+
wait_fixed=CONNECTION_RETRY_WAIT_TIME)
47+
def all_metrics(self, params: dict = None):
4548
"""
4649
Get the list of all the metrics that the prometheus host scrapes
4750
48-
:return: (list) A list of names of all the metrics available from the
49-
specified prometheus host
50-
51+
:param params: (dict) Optional dictionary containing GET parameters to be
52+
sent along with the API request, such as "time"
53+
:returns: (list) A list of names of all the metrics available from the
54+
specified prometheus host
5155
:raises: (Http Response error) Raises an exception in case of a connection error
52-
5356
"""
57+
params = params or {}
5458
response = requests.get('{0}/api/v1/label/__name__/values'.format(self.url),
5559
verify=self.ssl_verification,
56-
headers=self.headers)
60+
headers=self.headers,
61+
params=params,)
5762

5863
if response.status_code == 200:
5964
self._all_metrics = response.json()['data']
@@ -64,18 +69,20 @@ def all_metrics(self):
6469
))
6570
return self._all_metrics
6671

67-
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES, wait_fixed=CONNECTION_RETRY_WAIT_TIME)
68-
def get_current_metric_value(self, metric_name, label_config=None):
72+
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES,
73+
wait_fixed=CONNECTION_RETRY_WAIT_TIME)
74+
def get_current_metric_value(
75+
self, metric_name: str, label_config: dict = None, params: dict = None):
6976
"""
7077
A method to get the current metric value for the specified metric
7178
and label configuration.
7279
7380
:param metric_name: (str) The name of the metric
74-
75-
:param label_config: (dict) A dictionary that specifies metric labels and their values
76-
77-
:return: (list) A list of current metric values for the specified metric
78-
81+
:param label_config: (dict) A dictionary that specifies metric labels and their
82+
values
83+
:param params: (dict) Optional dictionary containing GET parameters to be sent
84+
along with the API request, such as "time"
85+
:returns: (list) A list of current metric values for the specified metric
7986
:raises: (Http Response error) Raises an exception in case of a connection error
8087
8188
Example Usage:
@@ -84,19 +91,20 @@ def get_current_metric_value(self, metric_name, label_config=None):
8491
``my_label_config = {'cluster': 'my_cluster_id', 'label_2': 'label_2_value'}``
8592
8693
``prom.get_current_metric_value(metric_name='up', label_config=my_label_config)``
87-
8894
"""
95+
params = params or {}
8996
data = []
9097
if label_config:
91-
label_list = [str(key+"="+ "'" + label_config[key]+ "'") for key in label_config]
98+
label_list = [str(key + "=" + "'" + label_config[key] + "'")
99+
for key in label_config]
92100
# print(label_list)
93101
query = metric_name + "{" + ",".join(label_list) + "}"
94102
else:
95103
query = metric_name
96104

97105
# using the query API to get raw data
98106
response = requests.get('{0}/api/v1/query'.format(self.url),
99-
params={'query': query},
107+
params={**{"query": query}, **params},
100108
verify=self.ssl_verification,
101109
headers=self.headers)
102110

@@ -109,38 +117,37 @@ def get_current_metric_value(self, metric_name, label_config=None):
109117
))
110118
return data
111119

112-
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES, wait_fixed=CONNECTION_RETRY_WAIT_TIME)
120+
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES,
121+
wait_fixed=CONNECTION_RETRY_WAIT_TIME)
113122
def get_metric_range_data(self,
114-
metric_name,
115-
label_config=None,
116-
start_time='10m',
117-
end_time='now',
118-
chunk_size=None,
119-
store_locally=False):
123+
metric_name: str,
124+
label_config: dict = None,
125+
start_time: str = '10m',
126+
end_time: str = 'now',
127+
chunk_size: str = None,
128+
store_locally: bool = False,
129+
params: dict = None):
120130
"""
121131
A method to get the current metric value for the specified metric
122132
and label configuration.
123133
124134
:param metric_name: (str) The name of the metric.
125-
126-
:param label_config: (dict) A dictionary that specifies metric labels and their values.
127-
135+
:param label_config: (dict) A dictionary specifying metric labels and their
136+
values.
128137
:param start_time: (str) A string that specifies the metric range start time.
129-
130138
:param end_time: (str) A string that specifies the metric range end time.
131-
132-
:param chunk_size: (str) Duration of metric data downloaded in one request.
133-
example, setting it to '3h' will download 3 hours
134-
worth of data in each request made to the prometheus host
139+
:param chunk_size: (str) Duration of metric data downloaded in one request. For
140+
example, setting it to '3h' will download 3 hours worth of data in each
141+
request made to the prometheus host
135142
:param store_locally: (bool) If set to True, will store data locally at,
136-
`"./metrics/hostname/metric_date/name_time.json.bz2"`
137-
138-
:return: (list) A list of metric data for the specified metric in the given time range
139-
140-
:raises: (Http Response error) Raises an exception in case of a connection error
141-
143+
`"./metrics/hostname/metric_date/name_time.json.bz2"`
144+
:param params: (dict) Optional dictionary containing GET parameters to be
145+
sent along with the API request, such as "time"
146+
:return: (list) A list of metric data for the specified metric in the given time
147+
range
148+
:raises: (Exception) Raises an exception in case of a connection error
142149
"""
143-
150+
params = params or {}
144151
data = []
145152

146153
start = int(dateparser.parse(str(start_time)).timestamp())
@@ -152,13 +159,14 @@ def get_metric_range_data(self,
152159
else:
153160
chunk_seconds = (int(round((dateparser.parse('now') -
154161
dateparser.parse(chunk_size)
155-
).total_seconds())))
162+
).total_seconds())))
156163

157-
if int(end-start) < chunk_seconds:
164+
if int(end - start) < chunk_seconds:
158165
sys.exit("specified chunk_size is too big")
159166

160167
if label_config:
161-
label_list = [str(key+"="+ "'" + label_config[key]+ "'") for key in label_config]
168+
label_list = [str(key + "=" + "'" + label_config[key] + "'")
169+
for key in label_config]
162170
# print(label_list)
163171
query = metric_name + "{" + ",".join(label_list) + "}"
164172
else:
@@ -167,9 +175,9 @@ def get_metric_range_data(self,
167175
while start < end:
168176
# using the query API to get raw data
169177
response = requests.get('{0}/api/v1/query'.format(self.url),
170-
params={'query': query + '[' + chunk_size + ']',
171-
'time': start + chunk_seconds
172-
},
178+
params={**{'query': query + '[' + chunk_size + ']',
179+
'time': start + chunk_seconds
180+
}, **params},
173181
verify=self.ssl_verification,
174182
headers=self.headers)
175183
if response.status_code == 200:
@@ -182,17 +190,24 @@ def get_metric_range_data(self,
182190
if store_locally:
183191
# store it locally
184192
self._store_metric_values_local(metric_name,
185-
json.dumps(response.json()['data']['result']),
193+
json.dumps(
194+
response.json()['data']['result']),
186195
start + chunk_seconds)
187196

188197
start += chunk_seconds
189198
return data
190199

191-
def _store_metric_values_local(self, metric_name, values, end_timestamp, compressed=False):
192-
'''
193-
Method to store metrics locally
200+
def _store_metric_values_local(
201+
self, metric_name, values, end_timestamp, compressed=False):
202+
"""
203+
Store metrics on the local filesystem, optionally with bz2 compression
194204
195-
'''
205+
:param metric_name: (str) the name of the metric being saved
206+
:param values: (str) metric data in JSON string format
207+
:param end_timestamp: (str) timestamp in any format understood by dateparser
208+
:param compressed: (bool) whether or not to apply bz2 compression
209+
:returns: (str) path to the saved metric file
210+
"""
196211
if not values:
197212
_LOGGER.debug("No values for %s", metric_name)
198213
return None
@@ -211,37 +226,38 @@ def _store_metric_values_local(self, metric_name, values, end_timestamp, compres
211226

212227
return file_path
213228

214-
def _metric_filename(self, metric_name, end_timestamp):
215-
'''
229+
def _metric_filename(self, metric_name: str, end_timestamp: str):
230+
"""
216231
Adds a timestamp to the filename before it is stored
217232
218-
'''
233+
:param metric_name: (str) the name of the metric being saved
234+
:param end_timestamp: (str) timestamp in any format understood by dateparser
235+
:returns: (str) the generated path
236+
"""
219237
end_timestamp = dateparser.parse(str(end_timestamp))
220238
directory_name = end_timestamp.strftime("%Y%m%d")
221239
timestamp = end_timestamp.strftime("%Y%m%d%H%M")
222240
object_path = "./metrics/" + self.prometheus_host + "/" + \
223-
metric_name + "/" + directory_name + "/" + timestamp + ".json"
241+
metric_name + "/" + directory_name + "/" + timestamp + ".json"
224242
return object_path
225243

226-
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES, wait_fixed=CONNECTION_RETRY_WAIT_TIME)
227-
def custom_query(self, query: str, params: dict = {}):
244+
@retry(stop_max_attempt_number=MAX_REQUEST_RETRIES,
245+
wait_fixed=CONNECTION_RETRY_WAIT_TIME)
246+
def custom_query(self, query: str, params: dict = None):
228247
"""
229248
A method to send a custom query to a Prometheus Host.
230249
231250
This method takes as input a string which will be sent as a query to
232251
the specified Prometheus Host. This query is a PromQL query.
233252
234253
:param query: (str) This is a PromQL query, a few examples can be found
235-
at https://prometheus.io/docs/prometheus/latest/querying/examples/
236-
254+
at https://prometheus.io/docs/prometheus/latest/querying/examples/
237255
:param params: (dict) Optional dictionary containing GET parameters to be
238-
sent along with the API request, such as "time"
239-
240-
:Returns: (list) A list of metric data received in response of the query sent
241-
242-
:raises: (Http Response error) Raises an exception in case of a connection error
243-
256+
sent along with the API request, such as "time"
257+
:returns: (list) A list of metric data received in response of the query sent
258+
:raises: (Exception) Raises an exception in case of a connection error
244259
"""
260+
params = params or {}
245261
data = None
246262
query = str(query)
247263
# using the query API to get raw data
@@ -261,13 +277,13 @@ def custom_query(self, query: str, params: dict = {}):
261277

262278
return data
263279

280+
264281
def pretty_print_metric(metric_data):
265282
"""
266283
A function to pretty print the metric data downloaded using class PrometheusConnect.
267284
268285
:param metric_data: (list) This is the metric data list returned from methods
269-
get_metric_range_data and get_current_metric_value
270-
286+
get_metric_range_data and get_current_metric_value
271287
"""
272288
data = metric_data
273289
for metric in data:

0 commit comments

Comments
 (0)