Closed raxod502 closed 2 years ago
I don't know Prometheus, so I can't evaluate any of what you've written in terms of use cases that Flask's development server is intended to support. Clearly, it's not intended to be used this way, so I'm not clear this is not something Prometheus should address.
It sounds like this metrics server is a production application, not part of the application under development, in which case it should not be run using the development server, even locally.
Can you suggest any alternatives to Flask that the prometheus_flask_exporter project could use to serve local web requests, if the Flask project does not desire to support running more than one Flask app in the same process?
Flask project does not desire to support running more than one Flask app in the same process
That's not what I said.
Flask is a WSGI application framework, not a WSGI server. You wouldn't pick an alternative to Flask, unless you wanted to rewrite that application.
What you want is a production WSGI server, as opposed to the development server. Gunicorn, Waitress, uWSGI, mod_wsgi, Eventlet, and Gevent are the most well known.
Understood. I'll work with the prometheus_flask_exporter project to see if they can migrate to one of those solutions instead of using the Flask development server.
Hi, I originally filed an issue at https://github.com/rycus86/prometheus_flask_exporter/issues/135 but determined that it was impossible to resolve the problem downstream, and changes are required in Flask to support the use case of prometheus_flask_exporter.
The problem is described in the issue report I linked above, but I will also summarize it here for convenience. Basically, when you invoke
flask run
, then Flask setsFLASK_RUN_FROM_CLI
as an environment variable. Then, inapp.run()
, if that environment variable is set, Flask skips starting the app, and prints the following warning:This is all fine and good when
app.run()
is being invoked from the top level in the main module, and it was not intended to launch a duplicate app. However, sometimes the user actually does want to invoke two separate Flask applications: for example, to expose application metrics on a different port from web traffic, which is generally recommended as a security best practice.Specifically, prometheus_flask_exporter offers an option to expose metrics on a separate port by starting a separate Flask app on a separate port and thread. However, Flask's behavior around
FLASK_RUN_FROM_CLI
breaks this functionality, since if the web traffic app is launched usingflask run
, then the environment variable will prevent prometheus_flask_exporter from starting the metrics app.Code in the user application looks like this:
The
metrics.start_http_server()
method instantiates a separate Flask application with the provided configuration, and invokesapp.run()
. If the main Flask application was starting usingflask run
, then the following warning is printed, and no metrics are served:Workarounds
Note that this problem only affects development since the Flask builtin server is not used in production. As such, there are a number of workarounds to the problem at present, but all of them have significant drawbacks.
flask run
. Disadvantage: degraded developer velocity due to having no live reloading during development.FLASK_RUN_FROM_CLI
environment variable from application code. Disadvantage: degraded reliability posture due to reliance on undocumented internal Flask features which may change in future versions, and mutation of the global namespace of environment variables which will affect all threads in the current process, including unrelated internal Flask code.Suggested fix
Add an optional keyword argument to
app.run
that allows bypassing the check onFLASK_RUN_FROM_CLI
. This can be provided by libraries such as prometheus_flask_exporter that invoke Flask as a server. Such a change would solve the use case described above, while preserving all the benefits of the check happening by default.I would be happy to contribute such a fix, along with documentation and tests as desired, if the maintainers of Flask agree that it is an appropriate path forward. If you have other suggestions for a better way to resolve the issue with prometheus_flask_exporter, please let me know and I would be happy to discuss.