The prometheus_client library documentation addresses this case:
Prometheus client libraries presume a threaded model, where metrics are shared across workers. This doesn't work so well for languages such as Python where it's common to have processes rather than threads to handle large workloads.
I won't copy here the explanation (which is geared toward gunicorn) use case but basically, you need to:
- define an env variable with directory to use: since you are using
Processyourself, you can set it in the code
os.environ["PROMETHEUS_MULTIPROC_DIR"] = "/path/to/writeable/tmp/"
- each process must have its own collector, register it at start and unregister it at exit:
from prometheus_client import multiprocess
def called_from_process():
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(CollectorRegistry())
def process_exit(process):
if process.pid is not None:
multiprocess.mark_process_dead(process.pid)
p = Process(target=f)
# f calls called_from_process
p.start()
p.join()
process_exit(process)
See the full documentation about how to handle gauge and any other quirk.
I expect that PROMETHEUS_MULTIPROC_DIRshould be cleaned at startup of your application to handle odd case where the application previous run was not able to do so.
Show HN: Pytheus – Python Prometheus client built with multiprocessing in mind
How to collect prometheus metrics from multiple python-flask sub-process? - Stack Overflow
pytheus: a modern python library for collecting prometheus metrics built with multiprocessing in mind
python - Prometheus how to expose metrics in multiprocess app with start_http_server - Stack Overflow
What you would want to do here is start up a separate process just to serve the metrics. Put the app function in https://github.com/prometheus/client_python#multiprocess-mode-gunicorn in an app of its own, and make sure that prometheus_multiproc_dir is the same for both it and the main application.
I used Prometheus_flask_exporter to do that.
My gunicorn config file was like this-
from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics
hostname = "0.0.0.0"
portname = 8080
def when_ready(server):
GunicornPrometheusMetrics.start_http_server_when_ready(8000)
def child_exit(server, worker):
GunicornPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid)
The wsgi file included-
from prometheus_flask_exporter import PrometheusMetrics
# an extension targeted at Gunicorn deployments for prometheus scraping in flask applications
from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics
application = Flask(__name__, static_url_path='')
CORS(application)
health = HealthCheck(application, "/healthcheck")
metrics = PrometheusMetrics(application)
metrics = GunicornPrometheusMetrics(application)