8
8
import threading
9
9
from contextlib import closing
10
10
from wsgiref .simple_server import make_server
11
+ import base64
12
+ import sys
11
13
12
14
from . import core
13
15
try :
@@ -118,7 +120,46 @@ def write_to_textfile(path, registry):
118
120
os .rename (tmppath , path )
119
121
120
122
121
- def push_to_gateway (gateway , job , registry , grouping_key = None , timeout = None ):
123
+ def default_handler (url , method , timeout , headers , data ):
124
+ '''Default handler that implements HTTP/HTTPS connections.
125
+
126
+ Used by the push_to_gateway functions. Can be re-used by other handlers.'''
127
+ def handle ():
128
+ request = Request (url , data = data )
129
+ request .get_method = lambda : method
130
+ for k , v in headers :
131
+ request .add_header (k , v )
132
+ resp = build_opener (HTTPHandler ).open (request , timeout = timeout )
133
+ if resp .code >= 400 :
134
+ raise IOError ("error talking to pushgateway: {0} {1}" .format (
135
+ resp .code , resp .msg ))
136
+
137
+ return handle
138
+
139
+
140
+ def basic_auth_handler (url , method , timeout , headers , data , username = None , password = None ):
141
+ '''Handler that implements HTTP/HTTPS connections with Basic Auth.
142
+
143
+ Sets auth headers using supplied 'username' and 'password', if set.
144
+ Used by the push_to_gateway functions. Can be re-used by other handlers.'''
145
+ def handle ():
146
+ '''Handler that implements HTTP Basic Auth.
147
+ '''
148
+ if username is not None and password is not None :
149
+ if sys .version_info >= (3 ,0 ):
150
+ auth_value = bytes ('{0}:{1}' .format (username , password ), 'utf8' )
151
+ auth_token = str (base64 .b64encode (auth_value ), 'utf8' )
152
+ else :
153
+ auth_value = '{0}:{1}' .format (username , password )
154
+ auth_token = base64 .b64encode (auth_value )
155
+ auth_header = "Basic {0}" .format (auth_token )
156
+ headers .append (['Authorization' , auth_header ])
157
+ default_handler (url , method , timeout , headers , data )()
158
+
159
+ return handle
160
+
161
+
162
+ def push_to_gateway (gateway , job , registry , grouping_key = None , timeout = None , handler = default_handler ):
122
163
'''Push metrics to the given pushgateway.
123
164
124
165
`gateway` the url for your push gateway. Either of the form
@@ -130,13 +171,37 @@ def push_to_gateway(gateway, job, registry, grouping_key=None, timeout=None):
130
171
Defaults to None
131
172
`timeout` is how long push will attempt to connect before giving up.
132
173
Defaults to None
174
+ `handler` is an optional function which can be provided to perform
175
+ requests to the 'gateway'.
176
+ Defaults to None, in which case an http or https request
177
+ will be carried out by a default handler.
178
+ If not None, the argument must be a function which accepts
179
+ the following arguments:
180
+ url, method, timeout, headers, and content
181
+ May be used to implement additional functionality not
182
+ supported by the built-in default handler (such as SSL
183
+ client certicates, and HTTP authentication mechanisms).
184
+ 'url' is the URL for the request, the 'gateway' argument
185
+ described earlier will form the basis of this URL.
186
+ 'method' is the HTTP method which should be used when
187
+ carrying out the request.
188
+ 'timeout' requests not successfully completed after this
189
+ many seconds should be aborted. If timeout is None, then
190
+ the handler should not set a timeout.
191
+
F438
'headers' is a list of ("header-name","header-value") tuples
192
+ which must be passed to the pushgateway in the form of HTTP
193
+ request headers.
194
+ The function should raise an exception (e.g. IOError) on
195
+ failure.
196
+ 'content' is the data which should be used to form the HTTP
197
+ Message Body.
133
198
134
199
This overwrites all metrics with the same job and grouping_key.
135
200
This uses the PUT HTTP method.'''
136
- _use_gateway ('PUT' , gateway , job , registry , grouping_key , timeout )
201
+ _use_gateway ('PUT' , gateway , job , registry , grouping_key , timeout , handler )
137
202
138
203
139
- def pushadd_to_gateway (gateway , job , registry , grouping_key = None , timeout = None ):
204
+ def pushadd_to_gateway (gateway , job , registry , grouping_key = None , timeout = None , handler = default_handler ):
140
205
'''PushAdd metrics to the given pushgateway.
141
206
142
207
`gateway` the url for your push gateway. Either of the form
@@ -148,13 +213,19 @@ def pushadd_to_gateway(gateway, job, registry, grouping_key=None, timeout=None):
148
213
Defaults to None
149
214
`timeout` is how long push will attempt to connect before giving up.
150
215
Defaults to None
216
+ `handler` is an optional function which can be provided to perform
217
+ requests to the 'gateway'.
218
+ Defaults to None, in which case an http or https request
219
+ will be carried out by a default handler.
220
+ See the 'prometheus_client.push_to_gateway' documentation
221
+ for implementation requirements.
151
222
152
223
This replaces metrics with the same name, job and grouping_key.
153
224
This uses the POST HTTP method.'''
154
- _use_gateway ('POST' , gateway , job , registry , grouping_key , timeout )
225
+ _use_gateway ('POST' , gateway , job , registry , grouping_key , timeout , handler )
155
226
156
227
157
- def delete_from_gateway (gateway , job , grouping_key = None , timeout = None ):
228
+ def delete_from_gateway (gateway , job , grouping_key = None , timeout = None , handler = default_handler ):
158
229
'''Delete metrics from the given pushgateway.
159
230
160
231
`gateway` the url for your push gateway. Either of the form
@@ -165,14 +236,21 @@ def delete_from_gateway(gateway, job, grouping_key=None, timeout=None):
165
236
Defaults to None
166
237
`timeout` is how long delete will attempt to connect before giving up.
167
238
Defaults to None
239
+ `handler` is an optional function which can be provided to perform
240
+ requests to the 'gateway'.
241
+ Defaults to None, in which case an http or https request
242
+ will be carried out by a default handler.
243
+ See the 'prometheus_client.push_to_gateway' documentation
244
+ for implementation requirements.
168
245
169
246
This deletes metrics with the given job and grouping_key.
170
247
This uses the DELETE HTTP method.'''
171
- _use_gateway ('DELETE' , gateway , job , None , grouping_key , timeout )
248
+ _use_gateway ('DELETE' , gateway , job , None , grouping_key , timeout , handler )
172
249
173
250
174
- def _use_gateway (method , gateway , job , registry , grouping_key , timeout ):
175
- if not (gateway .startswith ('http://' ) or gateway .startswith ('https://' )):
251
+ def _use_gateway (method , gateway , job , registry , grouping_key , timeout , handler ):
252
+ gateway_url = urlparse (gateway )
253
+ if not gateway_url .scheme :
176
254
gateway = 'http://{0}' .format (gateway )
177
255
url = '{0}/metrics/job/{1}' .format (gateway , quote_plus (job ))
178
256
@@ -185,13 +263,9 @@ def _use_gateway(method, gateway, job, registry, grouping_key, timeout):
185
263
url = url + '' .join (['/{0}/{1}' .format (quote_plus (str (k )), quote_plus (str (v )))
186
264
for k , v in sorted (grouping_key .items ())])
187
265
188
- request = Request (url , data = data )
189
- request .add_header ('Content-Type' , CONTENT_TYPE_LATEST )
190
- request .get_method = lambda : method
191
- resp = build_opener (HTTPHandler ).open (request , timeout = timeout )
192
- if resp .code >= 400 :
193
- raise IOError ("error talking to pushgateway: {0} {1}" .format (
194
- resp .code , resp .msg ))
266
+ headers = [('Content-Type' , CONTENT_TYPE_LATEST )]
267
+ handler (url = url , method = method , timeout = timeout ,
268
+ headers = headers , data = data )()
195
269
196
270
def instance_ip_grouping_key ():
197
271
'''Grouping key with instance set to the IP Address of this host.'''
0 commit comments