Closed
Description
This is a very similar issue to #132 and #69.
#69 was closed as a bug in cPython. That bug was resolved in cPython 3.8, however client_python
has since migrated to WSGI.
This is how it all behaves with the latest Python (3.8.5):
# python3.8
Python 3.8.5 (default, Jul 23 2020, 07:58:41)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import prometheus_client
>>> prometheus_client.start_http_server(port=9097, addr='::')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.8/site-packages/prometheus_client/exposition.py", line 78, in start_wsgi_server
httpd = make_server(addr, port, app, ThreadingWSGIServer, handler_class=_SilentHandler)
File "/usr/local/lib/python3.8/wsgiref/simple_server.py", line 154, in make_server
server = server_class((host, port), handler_class)
File "/usr/local/lib/python3.8/socketserver.py", line 452, in __init__
self.server_bind()
File "/usr/local/lib/python3.8/wsgiref/simple_server.py", line 50, in server_bind
HTTPServer.server_bind(self)
File "/usr/local/lib/python3.8/http/server.py", line 138, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/local/lib/python3.8/socketserver.py", line 466, in server_bind
self.socket.bind(self.server_address)
socket.gaierror: [Errno -9] Address family for hostname not supported
The issue lies with the ThreadingWSGIServer
class, which defaults to AF_INET
address family.
A workaround similar to bottlepy/bottle@af547f4 can be implemented in exposition.py
:
# diff -u /usr/local/lib/python3.8/site-packages/prometheus_client/exposition.py.broken /usr/local/lib/python3.8/site-packages/prometheus_client/exposition.py
--- /usr/local/lib/python3.8/site-packages/prometheus_client/exposition.py.broken 2020-07-23 11:28:12.198472090 +0000
+++ /usr/local/lib/python3.8/site-packages/prometheus_client/exposition.py 2020-07-23 11:29:07.506269752 +0000
@@ -75,7 +75,12 @@
def start_wsgi_server(port, addr='', registry=REGISTRY):
"""Starts a WSGI server for prometheus metrics as a daemon thread."""
app = make_wsgi_app(registry)
- httpd = make_server(addr, port, app, ThreadingWSGIServer, handler_class=_SilentHandler)
+ server_cls = ThreadingWSGIServer
+ if ':' in addr: # Fix wsgiref for IPv6 addresses.
+ if getattr(server_cls, 'address_family') == socket.AF_INET:
+ class server_cls(server_cls):
+ address_family = socket.AF_INET6
+ httpd = make_server(addr, port, app, server_cls, handler_class=_SilentHandler)
t = threading.Thread(target=httpd.serve_forever)
t.daemon = True
t.start()
And voila, now it works as expected:
# python3.8
Python 3.8.5 (default, Jul 23 2020, 07:58:41)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import prometheus_client
>>> prometheus_client.start_http_server(port=9097, addr='::')
>>> prometheus_client.start_http_server(port=9098)
>>>
# netstat -ltnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
(...)
tcp 0 0 0.0.0.0:9098 0.0.0.0:* LISTEN 20262/python3.8
(...)
tcp6 0 0 :::9097 :::* LISTEN 20262/python3.8
(...)
This is a non-invasive fix which doesn't break any existing code while at the same time provides those of us who wish our exporters listened on IPv6 sockets.
Is it possible to adjust exposition.py
this way, please? Thank you.
MartinHerren and fblaese
Metadata
Metadata
Assignees
Labels
No labels