Multiprocessing with Gunicorn + FastAPI
I've been trying to make multiprocessing work with FastAPI, but it just doesn't seem to happen.
This part is what I've been struggling the most:
def app(environ, start_response):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
data = generate_latest(registry)
status = '200 OK'
response_headers = [
('Content-type', CONTENT_TYPE_LATEST),
('Content-Length', str(len(data)))
]
start_response(status, response_headers)
return iter([data])
Had no idea where to put this, but after some experimentation it turns out, the simplest solution of creating a metrics app looks like this (including other parts from the documentation):
app = FastAPI(debug=False)
# Preparing gunicorn multiprocessing HACKS
def make_metrics_app():
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
return prometheus_client.make_asgi_app(registry=registry)
metrics_app = make_metrics_app()
app.mount("/metrics", metrics_app))
Just posting this to help others save hours of researching and debugging.
Thanks for the report! Would you be interested in adding some documentation to the README similar to how we have an example for flask, but under the multiprocess section?
@csmarchbanks If you think this is a correct way of doing things, I will add the instructions to the README
(me from my alt acc) Added my PR here: https://github.com/prometheus/client_python/pull/812
Looking at the README I see this
It is a best practice to create this registry inside the context of a request
Doesn't this mean that we could add that setup in a route? (see below)
I've seen other people also use the gunicorn when_ready hook to do the setup. Not sure what would be the best way and why.
@app.get("/metrics")
def metrics(request: Request):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
data = generate_latest(registry)
res = Response(content=data)
res.headers["Content-Type"] = CONTENT_TYPE_LATEST
return res
Closing this as the information is now in the readme!