Closed mweinelt closed 8 months ago
In the upcoming version of prometheus_client start_http_server returns the objects WSGIServer and thread.
From: https://github.com/prometheus/client_python/commit/b9edc43221101cad593c64d3fe9853760bef135e
def start_wsgi_server(
port: int,
addr: str = '0.0.0.0',
registry: CollectorRegistry = REGISTRY,
certfile: Optional[str] = None,
keyfile: Optional[str] = None,
client_cafile: Optional[str] = None,
client_capath: Optional[str] = None,
protocol: int = ssl.PROTOCOL_TLS_SERVER,
client_auth_required: bool = False,
) -> Tuple[WSGIServer, threading.Thread]:
"""Starts a WSGI server for prometheus metrics as a daemon thread."""
class TmpServer(ThreadingWSGIServer):
"""Copy of ThreadingWSGIServer to update address_family locally"""
TmpServer.address_family, addr = _get_best_family(addr, port)
app = make_wsgi_app(registry)
httpd = make_server(addr, port, app, TmpServer, handler_class=_SilentHandler)
if certfile and keyfile:
context = _get_ssl_ctx(certfile, keyfile, protocol, client_cafile, client_capath, client_auth_required)
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
t = threading.Thread(target=httpd.serve_forever)
t.daemon = True
t.start()
return httpd, t
start_http_server = start_wsgi_server
Taking inspiration from prometheus clients make_wsgi_app function
def make_wsgi_app(registry: CollectorRegistry = REGISTRY, disable_compression: bool = False) -> Callable:
"""Create a WSGI app which serves the metrics from a registry."""
def prometheus_app(environ, start_response):
# Prepare parameters
accept_header = environ.get('HTTP_ACCEPT')
accept_encoding_header = environ.get('HTTP_ACCEPT_ENCODING')
params = parse_qs(environ.get('QUERY_STRING', ''))
if environ['PATH_INFO'] == '/favicon.ico':
# Serve empty response for browsers
status = '200 OK'
headers = [('', '')]
output = b''
else:
# Bake output
status, headers, output = _bake_output(registry, accept_header, accept_encoding_header, params, disable_compression)
# Return output
start_response(status, headers)
return [output]
return prometheus_app
We could wrap the make_wsgi_app function with our own that executes exporter.update() before every request instead of updating per interval. Then we should get the latest data every GET request.
from prometheus_client import REGISTRY, make_wsgi_app, start_http_server
...
httpd, _ = start_http_server(port, address)
def local_wsgi_app(registry):
func = make_wsgi_app(registry, False)
def app(environ, start_response):
exporter.update()
output_array = func(environ, start_response)
return output_array
return app
httpd.set_app(local_wsgi_app(REGISTRY))
click.echo(f"Listening on http://{address}:{port}")
while True:
time.sleep(1)
In my opinion if something like this is implemented interval should be removed completely.
Prometheus client_python have now been released to version 0.20.0. https://github.com/prometheus/client_python/tree/v0.20.0.
I can make a pull request with my suggested changes.
Closed via #45.
Query kea only when asked, so the timestamping on the data in Prometheus is correct.
This means dropping interval by default.