Issue 1:
Hi, I originally filed an issue at rycus86/prometheus_flask_exporter#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 sets FLASK_RUN_FROM_CLI as an environment variable. Then, in app.run(), if that environment variable is set, Flask skips starting the app, and prints the following warning:

Warning: Silently ignoring app.run() because the application is run from the flask command line executable. Consider putting app.run() behind an if __name__ == "__main__" guard to silence this 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 using flask run, then the environment variable will prevent prometheus_flask_exporter from starting the metrics app.

Code in the user application looks like this:

metrics = prometheus_flask_exporter.PrometheusMetrics(app)
metrics.start_http_server(8081, host=config.METRICS_HOST)

The metrics.start_http_server() method instantiates a separate Flask application with the provided configuration, and invokes app.run(). If the main Flask application was starting using flask run, then the following warning is printed, and no metrics are served:

website_1 | * Serving Flask app 'src.app:app' (lazy loading)
website_1 | * Environment: development
website_1 | * Debug mode: on
website_1 | /usr/local/lib/python3.8/dist-packages/prometheus_flask_exporter/__init__.py:322: Warning: Silently ignoring app.run() because the application is run from the flask command line executable. Consider putting app.run() behind an if __name__ == "__main__" guard to silence this warning.

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.

Do not use flask run. Disadvantage: degraded developer velocity due to having no live reloading during development.

Do not serve metrics on separate Flask app. Disadvantage: degraded security posture due to internal metrics being (by default) available to public web traffic unless blocked by a separate firewall rule.

Do not run metrics server in development, or serve metrics on the same Flask app only during development. Disadvantage: degraded reliability posture due to loss of parity between development and production.

Manually unset 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 on FLASK_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.

Issue 2:
The current docs are at: https://flask.palletsprojects.com/en/1.1.x/patterns/celery/

They reference Celery's old configuration options which are the CELERY_* options. Since 5.x they've been renamed to be lowercase and there's an official migration guide available on Celery's site at https://docs.celeryproject.org/en/stable/userguide/configuration.html#conf-old-settings-map.

As of Celery 5.x, the old uppercase variants throw a deprecation warning and 6.x will remove them.

The current Flask docs for Celery reference things like:

celery = Celery(
app.import_name,
backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL']
)

flask_app.config.update(
CELERY_BROKER_URL='redis://localhost:6379',
CELERY_RESULT_BACKEND='redis://localhost:6379'
)

These imply you're using Flask's configuration mechanism which require uppercase variable names to be available, but that conflicts with Celery's new lowercase variables.

I talked with @ThiefMaster a few weeks ago about this on IRC and he came up with a great idea of doing:

# settings.py

CELERY_CONFIG = {
"broker_url": "redis://localhost:6379/0",
"result_backend": "redis://localhost:6379/0"
}

And then in your Celery factory you can do celery.conf.update(app.config.get("CELERY_CONFIG", {})).

This solves the problem and is working out nicely in practice. I'm doing that in a real project, along with extracting out the duplicate Redis connection string into an environment variable, etc.. A working example of that pattern is at https://github.com/nickjj/docker-flask-example/blob/ca1d48499a4007378bbe363bd5dc117c1a33cc3a/config/settings.py#L21-L28.

I didn't want to open a PR without asking first because I'm not sure which direction you want to go with the docs. To be honest the current docs are a little confusing because you jump straight into using Flask's app configuration values but there's no reference to setting up those config values.

Also with the current docs if you attempt to break things into separate files you'll end up with circular import issues when importing your tasks unless you start importing your tasks directly inside of the function you're using instead of the top of the file, but that's another issue. Although potentially semi-related if you plan to revamp the Celery docs.