diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-04-10 07:48:46 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-04-10 07:48:46 +0000 |
| commit | 98eadd768585f308c2d8497a0dce98879ed52ffa (patch) | |
| tree | a02806b20756f492a0dac479b14fd151288a08ae | |
| parent | 64e16e96e3fdd13f1bdeca1d54eb62146841eec0 (diff) | |
automatic import of python-prometheus-flask-exporter
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-prometheus-flask-exporter.spec | 1547 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 1549 insertions, 0 deletions
@@ -0,0 +1 @@ +/prometheus_flask_exporter-0.22.3.tar.gz diff --git a/python-prometheus-flask-exporter.spec b/python-prometheus-flask-exporter.spec new file mode 100644 index 0000000..2f9a3e4 --- /dev/null +++ b/python-prometheus-flask-exporter.spec @@ -0,0 +1,1547 @@ +%global _empty_manifest_terminate_build 0 +Name: python-prometheus-flask-exporter +Version: 0.22.3 +Release: 1 +Summary: Prometheus metrics exporter for Flask +License: MIT +URL: https://github.com/rycus86/prometheus_flask_exporter +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/f5/a8/a6c0625cd1efc5f475ab8f3ca508eedcc3d199bfa9d390214406af37b144/prometheus_flask_exporter-0.22.3.tar.gz +BuildArch: noarch + +Requires: python3-prometheus-client +Requires: python3-flask + +%description +# Prometheus Flask exporter + +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://coveralls.io/github/rycus86/prometheus_flask_exporter?branch=master) +[](https://codeclimate.com/github/rycus86/prometheus_flask_exporter) +[](https://github.com/rycus86/prometheus_flask_exporter/actions/workflows/test-and-publish.yml) + +This library provides HTTP request metrics to export into +[Prometheus](https://prometheus.io/). +It can also track method invocations using convenient functions. + +## Installing + +Install using [PIP](https://pip.pypa.io/en/stable/quickstart/): + +```bash +pip install prometheus-flask-exporter +``` +or paste it into requirements.txt: +``` +# newest version +prometheus-flask-exporter + +# or with specific version number +prometheus-flask-exporter==0.22.3 +``` +and then install dependencies from requirements.txt file as usual: +``` +pip install -r requirements.txt +``` + + +## Usage + +```python +from flask import Flask, request +from prometheus_flask_exporter import PrometheusMetrics + +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +# static information as metric +metrics.info('app_info', 'Application info', version='1.0.3') + +@app.route('/') +def main(): + pass # requests tracked by default + +@app.route('/skip') +@metrics.do_not_track() +def skip(): + pass # default metrics are not collected + +@app.route('/<item_type>') +@metrics.do_not_track() +@metrics.counter('invocation_by_type', 'Number of invocations by type', + labels={'item_type': lambda: request.view_args['type']}) +def by_type(item_type): + pass # only the counter is collected, not the default metrics + +@app.route('/long-running') +@metrics.gauge('in_progress', 'Long running requests in progress') +def long_running(): + pass + +@app.route('/status/<int:status>') +@metrics.do_not_track() +@metrics.summary('requests_by_status', 'Request latencies by status', + labels={'status': lambda r: r.status_code}) +@metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path', + labels={'status': lambda r: r.status_code, 'path': lambda: request.path}) +def echo_status(status): + return 'Status: %s' % status, status +``` + +## Default metrics + +The following metrics are exported by default +(unless the `export_defaults` is set to `False`). + +- `flask_http_request_duration_seconds` (Histogram) + Labels: `method`, `path` and `status`. + Flask HTTP request duration in seconds for all Flask requests. +- `flask_http_request_total` (Counter) + Labels: `method` and `status`. + Total number of HTTP requests for all Flask requests. +- `flask_http_request_exceptions_total` (Counter) + Labels: `method` and `status`. + Total number of uncaught exceptions when serving Flask requests. +- `flask_exporter_info` (Gauge) + Information about the Prometheus Flask exporter itself (e.g. `version`). + +The prefix for the default metrics can be controlled by the `defaults_prefix` parameter. +If you don't want to use any prefix, pass the `prometheus_flask_exporter.NO_PREFIX` value in. +The buckets on the default request latency histogram can be changed by the `buckets` parameter, and if using a summary for them is more appropriate for your use case, then use the `default_latency_as_histogram=False` parameter. + +To register your own *default* metrics that will track all registered +Flask view functions, use the `register_default` function. + +```python +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +@app.route('/simple') +def simple_get(): + pass + +metrics.register_default( + metrics.counter( + 'by_path_counter', 'Request count by request paths', + labels={'path': lambda: request.path} + ) +) +``` + +*Note:* register your default metrics after all routes have been set up. +Also note, that Gauge metrics registered as default will track the +`/metrics` endpoint, and this can't be disabled at the moment. + +If you want to apply the same metric to multiple (but not all) endpoints, +create its wrapper first, then add to each function. + +```python +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +by_path_counter = metrics.counter( + 'by_path_counter', 'Request count by request paths', + labels={'path': lambda: request.path} +) + +@app.route('/simple') +@by_path_counter +def simple_get(): + pass + +@app.route('/plain') +@by_path_counter +def plain(): + pass + +@app.route('/not/tracked/by/path') +def not_tracked_by_path(): + pass +``` + +You can avoid recording metrics on individual endpoints +by decorating them with `@metrics.do_not_track()`, or use the +`excluded_paths` argument when creating the `PrometheusMetrics` instance +that takes a regular expression (either a single string, or a list) and +matching paths will be excluded. These apply to both built-in and user-defined +default metrics, unless you disable it by setting the `exclude_user_defaults` +argument to `False`. If you have functions that are inherited or otherwise get +metrics collected that you don't want, you can use `@metrics.exclude_all_metrics()` +to exclude both default and non-default metrics being collected from it. + +## Configuration + +By default, the metrics are exposed on the same Flask application on the +`/metrics` endpoint and using the core Prometheus registry. +If this doesn't suit your needs, set the `path` argument to `None` and/or +the `export_defaults` argument to `False` plus change the `registry` +argument if needed. + +The `group_by` constructor argument controls what +the default request duration metric is tracked by: endpoint (function) +instead of URI path (the default). This parameter also accepts a function +to extract the value from the request, or a name of a property of the request object. +Examples: + +```python +PrometheusMetrics(app, group_by='path') # the default +PrometheusMetrics(app, group_by='endpoint') # by endpoint +PrometheusMetrics(app, group_by='url_rule') # by URL rule + +def custom_rule(req): # the Flask request object + """ The name of the function becomes the label name. """ + return '%s::%s' % (req.method, req.path) + +PrometheusMetrics(app, group_by=custom_rule) # by a function + +# Error: this is not supported: +PrometheusMetrics(app, group_by=lambda r: r.path) +``` + +> The `group_by_endpoint` argument is deprecated since 0.4.0, +> please use the new `group_by` argument. + +The `register_endpoint` allows exposing the metrics endpoint on a specific path. +It also allows passing in a Flask application to register it on but defaults +to the main one if not defined. + +Similarly, the `start_http_server` allows exposing the endpoint on an +independent Flask application on a selected HTTP port. +It also supports overriding the endpoint's path and the HTTP listen address. + +You can also set default labels to add to every request managed by +a `PrometheusMetrics` instance, using the `default_labels` argument. +This needs to be a dictionary, where each key will become a metric +label name, and the values the label values. +These can be constant values, or dynamic functions, see below in the +[Labels](#Labels) section. + +> The `static_labels` argument is deprecated since 0.15.0, +> please use the new `default_labels` argument. + +If you use another framework over Flask (perhaps +[Connexion](https://connexion.readthedocs.io/)) then you might return +responses from your endpoints that Flask can't deal with by default. +If that is the case, you might need to pass in a `response_converter` +that takes the returned object and should convert that to a Flask +friendly response. +See `ConnexionPrometheusMetrics` for an example. + +## Labels + +When defining labels for metrics on functions, +the following values are supported in the dictionary: + +- A simple static value +- A no-argument callable +- A single argument callable that will receive the Flask response + as the argument + +Label values are evaluated within the request context. + +## Initial metric values +_For more info see: https://github.com/prometheus/client_python#labels_ + +Metrics without any labels will get an initial value. +Metrics that only have static-value labels will also have an initial value. (except when they are created with the option `initial_value_when_only_static_labels=False`) +Metrics that have one or more callable-value labels will not have an initial value. + +## Application information + +The `PrometheusMetrics.info(..)` method provides a way to expose +information as a `Gauge` metric, the application version for example. + +The metric is returned from the method to allow changing its value +from the default `1`: + +```python +metrics = PrometheusMetrics(app) +info = metrics.info('dynamic_info', 'Something dynamic') +... +info.set(42.1) +``` + +## Examples + +See some simple examples visualized on a Grafana dashboard by running +the demo in the [examples/sample-signals](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/sample-signals) folder. + + + +## App Factory Pattern + +This library also supports the Flask [app factory pattern](http://flask.pocoo.org/docs/1.0/patterns/appfactories/). Use the `init_app` method to attach the library to one or more application objects. Note, that to use this mode, you'll need to use the `for_app_factory()` class method to create the `metrics` instance, or pass in `None` for the `app` in the constructor. + +```python +metrics = PrometheusMetrics.for_app_factory() +# then later: +metrics.init_app(app) +``` + +## Securing the metrics endpoint + +If you wish to have authentication (or any other special handling) on the metrics endpoint, +you can use the `metrics_decorator` argument when creating the `PrometheusMetrics` instance. +For example to integrate with [Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +use it like it's shown in the example below. + +```python +app = Flask(__name__) +auth = HTTPBasicAuth() +metrics = PrometheusMetrics(app, metrics_decorator=auth.login_required) + +# ... other authentication setup like @auth.verify_password below +``` + +See a full example in the [examples/flask-httpauth](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/flask-httpauth) folder. + +## Custom metrics endpoint + +You can also take full control of the metrics endpoint by generating its contents, +and managing how it is exposed by yourself. + +```python +app = Flask(__name__) +# path=None to avoid registering a /metrics endpoint on the same Flask app +metrics = PrometheusMetrics(app, path=None) + +# later ... generate the response (and its content type) to expose to Prometheus +response_data, content_type = metrics.generate_metrics() +``` + +See the related conversation in [issue #135](https://github.com/rycus86/prometheus_flask_exporter/issues/135). + +## Debug mode + +Please note, that changes being live-reloaded, when running the Flask +app with `debug=True`, are not going to be reflected in the metrics. +See [https://github.com/rycus86/prometheus_flask_exporter/issues/4](https://github.com/rycus86/prometheus_flask_exporter/issues/4) +for more details. + +Alternatively - since version `0.5.1` - if you set the `DEBUG_METRICS` +environment variable, you will get metrics for the latest reloaded code. +These will be exported on the main Flask app. +Serving the metrics on a different port is not going to work +most probably - e.g. `PrometheusMetrics.start_http_server(..)` is not +expected to work. + +## WSGI + +Getting accurate metrics for WSGI apps might require a bit more setup. +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#5](https://github.com/rycus86/prometheus_flask_exporter/issues/5) issue. + +### Multiprocess applications + +For multiprocess applications (WSGI or otherwise), you can find some +helper classes in the `prometheus_flask_exporter.multiprocess` module. +These provide convenience wrappers for exposing metrics in an +environment where multiple copies of the application will run on a single host. + +```python +# an extension targeted at Gunicorn deployments +from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics + +app = Flask(__name__) +metrics = GunicornPrometheusMetrics(app) + +# then in the Gunicorn config file: +from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics + +def when_ready(server): + GunicornPrometheusMetrics.start_http_server_when_ready(8080) + +def child_exit(server, worker): + GunicornPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid) +``` + +Also see the `GunicornInternalPrometheusMetrics` class if you want to have +the metrics HTTP endpoint exposed internally, on the same Flask application. + +```python +# an extension targeted at Gunicorn deployments with an internal metrics endpoint +from prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics + +app = Flask(__name__) +metrics = GunicornInternalPrometheusMetrics(app) + +# then in the Gunicorn config file: +from prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics + +def child_exit(server, worker): + GunicornInternalPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid) +``` + +There's a small wrapper available for [Gunicorn](https://gunicorn.org/) and +[uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/index.html), for everything +else you can extend the `prometheus_flask_exporter.multiprocess.MultiprocessPrometheusMetrics` class +and implement the `should_start_http_server` method at least. + +```python +from prometheus_flask_exporter.multiprocess import MultiprocessPrometheusMetrics + +class MyMultiprocessMetrics(MultiprocessPrometheusMetrics): + def should_start_http_server(self): + return this_worker() == primary_worker() +``` + +This should return `True` on one process only, and the underlying +[Prometheus client library](https://github.com/prometheus/client_python) +will collect the metrics for all the forked children or siblings. + +An additional Flask extension for apps with `processes=N` and `threaded=False` exists +with the `MultiprocessInternalPrometheusMetrics` class. + +```python +from flask import Flask +from prometheus_flask_exporter.multiprocess import MultiprocessInternalPrometheusMetrics + +app = Flask(__name__) +metrics = MultiprocessInternalPrometheusMetrics(app) + +... + +if __name__ == '__main__': + app.run('0.0.0.0', 4000, processes=5, threaded=False) +``` + +__Note:__ this needs the `PROMETHEUS_MULTIPROC_DIR` environment variable +to point to a valid, writable directory. + +You'll also have to call the `metrics.start_http_server()` function +explicitly somewhere, and the `should_start_http_server` takes care of +only starting it once. +The [examples](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples) folder +has some working examples on this. + +Please also note, that the Prometheus client library does not collect process level +metrics, like memory, CPU and Python GC stats when multiprocessing is enabled. +See the [prometheus_flask_exporter#18](https://github.com/rycus86/prometheus_flask_exporter/issues/18) +issue for some more context and details. + +A final caveat is that the metrics HTTP server will listen on __any__ paths +on the given HTTP port, not only on `/metrics`, and it is not implemented +at the moment to be able to change this. + +### uWSGI lazy-apps + +When [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) is configured +to run with [lazy-apps]([lazy-apps](https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#preforking-vs-lazy-apps-vs-lazy)), +exposing the metrics endpoint on a separate HTTP server (and port) is not functioning yet. +A workaround is to register the endpoint on the main Flask application. + +```python +app = Flask(__name__) +metrics = UWsgiPrometheusMetrics(app) +metrics.register_endpoint('/metrics') +# instead of metrics.start_http_server(port) +``` + +See [#31](https://github.com/rycus86/prometheus_flask_exporter/issues/31) +for context, and please let me know if you know a better way! + +## Connexion integration + +The [Connexion](https://connexion.readthedocs.io/) library has some +support to automatically deal with certain response types, for example +dataclasses, which a plain Flask application would not accept. +To ease the integration, you can use `ConnexionPrometheusMetrics` in +place of `PrometheusMetrics` that has the `response_converter` set +appropriately to be able to deal with whatever Connexion supports for +Flask integrations. + +```python +import connexion +from prometheus_flask_exporter import ConnexionPrometheusMetrics + +app = connexion.App(__name__) +metrics = ConnexionPrometheusMetrics(app) +``` + +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#61](https://github.com/rycus86/prometheus_flask_exporter/issues/61) issue. + +There's a caveat about this integration, where any endpoints that +do not return JSON responses need to be decorated with +`@metrics.content_type('...')` as this integration would force them +to be `application/json` otherwise. + +```python +metrics = ConnexionPrometheusMetrics(app) + +@metrics.content_type('text/plain') +def plain_response(): + return 'plain text' +``` + +See the [prometheus_flask_exporter#64](https://github.com/rycus86/prometheus_flask_exporter/issues/64) issue for more details. + +## Flask-RESTful integration + +The [Flask-RESTful library](https://flask-restful.readthedocs.io/) has +some custom response handling logic, which can be helpful in some cases. +For example, returning `None` would fail on plain Flask, but it +works on Flask-RESTful. +To ease the integration, you can use `RESTfulPrometheusMetrics` in +place of `PrometheusMetrics` that sets the `response_converter` to use +the Flask-RESTful `API` response utilities. + +```python +from flask import Flask +from flask_restful import Api +from prometheus_flask_exporter import RESTfulPrometheusMetrics + +app = Flask(__name__) +restful_api = Api(app) +metrics = RESTfulPrometheusMetrics(app, restful_api) +``` + +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#62](https://github.com/rycus86/prometheus_flask_exporter/issues/62) issue. + +## License + +MIT + + +%package -n python3-prometheus-flask-exporter +Summary: Prometheus metrics exporter for Flask +Provides: python-prometheus-flask-exporter +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-prometheus-flask-exporter +# Prometheus Flask exporter + +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://coveralls.io/github/rycus86/prometheus_flask_exporter?branch=master) +[](https://codeclimate.com/github/rycus86/prometheus_flask_exporter) +[](https://github.com/rycus86/prometheus_flask_exporter/actions/workflows/test-and-publish.yml) + +This library provides HTTP request metrics to export into +[Prometheus](https://prometheus.io/). +It can also track method invocations using convenient functions. + +## Installing + +Install using [PIP](https://pip.pypa.io/en/stable/quickstart/): + +```bash +pip install prometheus-flask-exporter +``` +or paste it into requirements.txt: +``` +# newest version +prometheus-flask-exporter + +# or with specific version number +prometheus-flask-exporter==0.22.3 +``` +and then install dependencies from requirements.txt file as usual: +``` +pip install -r requirements.txt +``` + + +## Usage + +```python +from flask import Flask, request +from prometheus_flask_exporter import PrometheusMetrics + +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +# static information as metric +metrics.info('app_info', 'Application info', version='1.0.3') + +@app.route('/') +def main(): + pass # requests tracked by default + +@app.route('/skip') +@metrics.do_not_track() +def skip(): + pass # default metrics are not collected + +@app.route('/<item_type>') +@metrics.do_not_track() +@metrics.counter('invocation_by_type', 'Number of invocations by type', + labels={'item_type': lambda: request.view_args['type']}) +def by_type(item_type): + pass # only the counter is collected, not the default metrics + +@app.route('/long-running') +@metrics.gauge('in_progress', 'Long running requests in progress') +def long_running(): + pass + +@app.route('/status/<int:status>') +@metrics.do_not_track() +@metrics.summary('requests_by_status', 'Request latencies by status', + labels={'status': lambda r: r.status_code}) +@metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path', + labels={'status': lambda r: r.status_code, 'path': lambda: request.path}) +def echo_status(status): + return 'Status: %s' % status, status +``` + +## Default metrics + +The following metrics are exported by default +(unless the `export_defaults` is set to `False`). + +- `flask_http_request_duration_seconds` (Histogram) + Labels: `method`, `path` and `status`. + Flask HTTP request duration in seconds for all Flask requests. +- `flask_http_request_total` (Counter) + Labels: `method` and `status`. + Total number of HTTP requests for all Flask requests. +- `flask_http_request_exceptions_total` (Counter) + Labels: `method` and `status`. + Total number of uncaught exceptions when serving Flask requests. +- `flask_exporter_info` (Gauge) + Information about the Prometheus Flask exporter itself (e.g. `version`). + +The prefix for the default metrics can be controlled by the `defaults_prefix` parameter. +If you don't want to use any prefix, pass the `prometheus_flask_exporter.NO_PREFIX` value in. +The buckets on the default request latency histogram can be changed by the `buckets` parameter, and if using a summary for them is more appropriate for your use case, then use the `default_latency_as_histogram=False` parameter. + +To register your own *default* metrics that will track all registered +Flask view functions, use the `register_default` function. + +```python +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +@app.route('/simple') +def simple_get(): + pass + +metrics.register_default( + metrics.counter( + 'by_path_counter', 'Request count by request paths', + labels={'path': lambda: request.path} + ) +) +``` + +*Note:* register your default metrics after all routes have been set up. +Also note, that Gauge metrics registered as default will track the +`/metrics` endpoint, and this can't be disabled at the moment. + +If you want to apply the same metric to multiple (but not all) endpoints, +create its wrapper first, then add to each function. + +```python +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +by_path_counter = metrics.counter( + 'by_path_counter', 'Request count by request paths', + labels={'path': lambda: request.path} +) + +@app.route('/simple') +@by_path_counter +def simple_get(): + pass + +@app.route('/plain') +@by_path_counter +def plain(): + pass + +@app.route('/not/tracked/by/path') +def not_tracked_by_path(): + pass +``` + +You can avoid recording metrics on individual endpoints +by decorating them with `@metrics.do_not_track()`, or use the +`excluded_paths` argument when creating the `PrometheusMetrics` instance +that takes a regular expression (either a single string, or a list) and +matching paths will be excluded. These apply to both built-in and user-defined +default metrics, unless you disable it by setting the `exclude_user_defaults` +argument to `False`. If you have functions that are inherited or otherwise get +metrics collected that you don't want, you can use `@metrics.exclude_all_metrics()` +to exclude both default and non-default metrics being collected from it. + +## Configuration + +By default, the metrics are exposed on the same Flask application on the +`/metrics` endpoint and using the core Prometheus registry. +If this doesn't suit your needs, set the `path` argument to `None` and/or +the `export_defaults` argument to `False` plus change the `registry` +argument if needed. + +The `group_by` constructor argument controls what +the default request duration metric is tracked by: endpoint (function) +instead of URI path (the default). This parameter also accepts a function +to extract the value from the request, or a name of a property of the request object. +Examples: + +```python +PrometheusMetrics(app, group_by='path') # the default +PrometheusMetrics(app, group_by='endpoint') # by endpoint +PrometheusMetrics(app, group_by='url_rule') # by URL rule + +def custom_rule(req): # the Flask request object + """ The name of the function becomes the label name. """ + return '%s::%s' % (req.method, req.path) + +PrometheusMetrics(app, group_by=custom_rule) # by a function + +# Error: this is not supported: +PrometheusMetrics(app, group_by=lambda r: r.path) +``` + +> The `group_by_endpoint` argument is deprecated since 0.4.0, +> please use the new `group_by` argument. + +The `register_endpoint` allows exposing the metrics endpoint on a specific path. +It also allows passing in a Flask application to register it on but defaults +to the main one if not defined. + +Similarly, the `start_http_server` allows exposing the endpoint on an +independent Flask application on a selected HTTP port. +It also supports overriding the endpoint's path and the HTTP listen address. + +You can also set default labels to add to every request managed by +a `PrometheusMetrics` instance, using the `default_labels` argument. +This needs to be a dictionary, where each key will become a metric +label name, and the values the label values. +These can be constant values, or dynamic functions, see below in the +[Labels](#Labels) section. + +> The `static_labels` argument is deprecated since 0.15.0, +> please use the new `default_labels` argument. + +If you use another framework over Flask (perhaps +[Connexion](https://connexion.readthedocs.io/)) then you might return +responses from your endpoints that Flask can't deal with by default. +If that is the case, you might need to pass in a `response_converter` +that takes the returned object and should convert that to a Flask +friendly response. +See `ConnexionPrometheusMetrics` for an example. + +## Labels + +When defining labels for metrics on functions, +the following values are supported in the dictionary: + +- A simple static value +- A no-argument callable +- A single argument callable that will receive the Flask response + as the argument + +Label values are evaluated within the request context. + +## Initial metric values +_For more info see: https://github.com/prometheus/client_python#labels_ + +Metrics without any labels will get an initial value. +Metrics that only have static-value labels will also have an initial value. (except when they are created with the option `initial_value_when_only_static_labels=False`) +Metrics that have one or more callable-value labels will not have an initial value. + +## Application information + +The `PrometheusMetrics.info(..)` method provides a way to expose +information as a `Gauge` metric, the application version for example. + +The metric is returned from the method to allow changing its value +from the default `1`: + +```python +metrics = PrometheusMetrics(app) +info = metrics.info('dynamic_info', 'Something dynamic') +... +info.set(42.1) +``` + +## Examples + +See some simple examples visualized on a Grafana dashboard by running +the demo in the [examples/sample-signals](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/sample-signals) folder. + + + +## App Factory Pattern + +This library also supports the Flask [app factory pattern](http://flask.pocoo.org/docs/1.0/patterns/appfactories/). Use the `init_app` method to attach the library to one or more application objects. Note, that to use this mode, you'll need to use the `for_app_factory()` class method to create the `metrics` instance, or pass in `None` for the `app` in the constructor. + +```python +metrics = PrometheusMetrics.for_app_factory() +# then later: +metrics.init_app(app) +``` + +## Securing the metrics endpoint + +If you wish to have authentication (or any other special handling) on the metrics endpoint, +you can use the `metrics_decorator` argument when creating the `PrometheusMetrics` instance. +For example to integrate with [Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +use it like it's shown in the example below. + +```python +app = Flask(__name__) +auth = HTTPBasicAuth() +metrics = PrometheusMetrics(app, metrics_decorator=auth.login_required) + +# ... other authentication setup like @auth.verify_password below +``` + +See a full example in the [examples/flask-httpauth](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/flask-httpauth) folder. + +## Custom metrics endpoint + +You can also take full control of the metrics endpoint by generating its contents, +and managing how it is exposed by yourself. + +```python +app = Flask(__name__) +# path=None to avoid registering a /metrics endpoint on the same Flask app +metrics = PrometheusMetrics(app, path=None) + +# later ... generate the response (and its content type) to expose to Prometheus +response_data, content_type = metrics.generate_metrics() +``` + +See the related conversation in [issue #135](https://github.com/rycus86/prometheus_flask_exporter/issues/135). + +## Debug mode + +Please note, that changes being live-reloaded, when running the Flask +app with `debug=True`, are not going to be reflected in the metrics. +See [https://github.com/rycus86/prometheus_flask_exporter/issues/4](https://github.com/rycus86/prometheus_flask_exporter/issues/4) +for more details. + +Alternatively - since version `0.5.1` - if you set the `DEBUG_METRICS` +environment variable, you will get metrics for the latest reloaded code. +These will be exported on the main Flask app. +Serving the metrics on a different port is not going to work +most probably - e.g. `PrometheusMetrics.start_http_server(..)` is not +expected to work. + +## WSGI + +Getting accurate metrics for WSGI apps might require a bit more setup. +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#5](https://github.com/rycus86/prometheus_flask_exporter/issues/5) issue. + +### Multiprocess applications + +For multiprocess applications (WSGI or otherwise), you can find some +helper classes in the `prometheus_flask_exporter.multiprocess` module. +These provide convenience wrappers for exposing metrics in an +environment where multiple copies of the application will run on a single host. + +```python +# an extension targeted at Gunicorn deployments +from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics + +app = Flask(__name__) +metrics = GunicornPrometheusMetrics(app) + +# then in the Gunicorn config file: +from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics + +def when_ready(server): + GunicornPrometheusMetrics.start_http_server_when_ready(8080) + +def child_exit(server, worker): + GunicornPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid) +``` + +Also see the `GunicornInternalPrometheusMetrics` class if you want to have +the metrics HTTP endpoint exposed internally, on the same Flask application. + +```python +# an extension targeted at Gunicorn deployments with an internal metrics endpoint +from prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics + +app = Flask(__name__) +metrics = GunicornInternalPrometheusMetrics(app) + +# then in the Gunicorn config file: +from prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics + +def child_exit(server, worker): + GunicornInternalPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid) +``` + +There's a small wrapper available for [Gunicorn](https://gunicorn.org/) and +[uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/index.html), for everything +else you can extend the `prometheus_flask_exporter.multiprocess.MultiprocessPrometheusMetrics` class +and implement the `should_start_http_server` method at least. + +```python +from prometheus_flask_exporter.multiprocess import MultiprocessPrometheusMetrics + +class MyMultiprocessMetrics(MultiprocessPrometheusMetrics): + def should_start_http_server(self): + return this_worker() == primary_worker() +``` + +This should return `True` on one process only, and the underlying +[Prometheus client library](https://github.com/prometheus/client_python) +will collect the metrics for all the forked children or siblings. + +An additional Flask extension for apps with `processes=N` and `threaded=False` exists +with the `MultiprocessInternalPrometheusMetrics` class. + +```python +from flask import Flask +from prometheus_flask_exporter.multiprocess import MultiprocessInternalPrometheusMetrics + +app = Flask(__name__) +metrics = MultiprocessInternalPrometheusMetrics(app) + +... + +if __name__ == '__main__': + app.run('0.0.0.0', 4000, processes=5, threaded=False) +``` + +__Note:__ this needs the `PROMETHEUS_MULTIPROC_DIR` environment variable +to point to a valid, writable directory. + +You'll also have to call the `metrics.start_http_server()` function +explicitly somewhere, and the `should_start_http_server` takes care of +only starting it once. +The [examples](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples) folder +has some working examples on this. + +Please also note, that the Prometheus client library does not collect process level +metrics, like memory, CPU and Python GC stats when multiprocessing is enabled. +See the [prometheus_flask_exporter#18](https://github.com/rycus86/prometheus_flask_exporter/issues/18) +issue for some more context and details. + +A final caveat is that the metrics HTTP server will listen on __any__ paths +on the given HTTP port, not only on `/metrics`, and it is not implemented +at the moment to be able to change this. + +### uWSGI lazy-apps + +When [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) is configured +to run with [lazy-apps]([lazy-apps](https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#preforking-vs-lazy-apps-vs-lazy)), +exposing the metrics endpoint on a separate HTTP server (and port) is not functioning yet. +A workaround is to register the endpoint on the main Flask application. + +```python +app = Flask(__name__) +metrics = UWsgiPrometheusMetrics(app) +metrics.register_endpoint('/metrics') +# instead of metrics.start_http_server(port) +``` + +See [#31](https://github.com/rycus86/prometheus_flask_exporter/issues/31) +for context, and please let me know if you know a better way! + +## Connexion integration + +The [Connexion](https://connexion.readthedocs.io/) library has some +support to automatically deal with certain response types, for example +dataclasses, which a plain Flask application would not accept. +To ease the integration, you can use `ConnexionPrometheusMetrics` in +place of `PrometheusMetrics` that has the `response_converter` set +appropriately to be able to deal with whatever Connexion supports for +Flask integrations. + +```python +import connexion +from prometheus_flask_exporter import ConnexionPrometheusMetrics + +app = connexion.App(__name__) +metrics = ConnexionPrometheusMetrics(app) +``` + +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#61](https://github.com/rycus86/prometheus_flask_exporter/issues/61) issue. + +There's a caveat about this integration, where any endpoints that +do not return JSON responses need to be decorated with +`@metrics.content_type('...')` as this integration would force them +to be `application/json` otherwise. + +```python +metrics = ConnexionPrometheusMetrics(app) + +@metrics.content_type('text/plain') +def plain_response(): + return 'plain text' +``` + +See the [prometheus_flask_exporter#64](https://github.com/rycus86/prometheus_flask_exporter/issues/64) issue for more details. + +## Flask-RESTful integration + +The [Flask-RESTful library](https://flask-restful.readthedocs.io/) has +some custom response handling logic, which can be helpful in some cases. +For example, returning `None` would fail on plain Flask, but it +works on Flask-RESTful. +To ease the integration, you can use `RESTfulPrometheusMetrics` in +place of `PrometheusMetrics` that sets the `response_converter` to use +the Flask-RESTful `API` response utilities. + +```python +from flask import Flask +from flask_restful import Api +from prometheus_flask_exporter import RESTfulPrometheusMetrics + +app = Flask(__name__) +restful_api = Api(app) +metrics = RESTfulPrometheusMetrics(app, restful_api) +``` + +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#62](https://github.com/rycus86/prometheus_flask_exporter/issues/62) issue. + +## License + +MIT + + +%package help +Summary: Development documents and examples for prometheus-flask-exporter +Provides: python3-prometheus-flask-exporter-doc +%description help +# Prometheus Flask exporter + +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://pypi.python.org/pypi/prometheus-flask-exporter) +[](https://coveralls.io/github/rycus86/prometheus_flask_exporter?branch=master) +[](https://codeclimate.com/github/rycus86/prometheus_flask_exporter) +[](https://github.com/rycus86/prometheus_flask_exporter/actions/workflows/test-and-publish.yml) + +This library provides HTTP request metrics to export into +[Prometheus](https://prometheus.io/). +It can also track method invocations using convenient functions. + +## Installing + +Install using [PIP](https://pip.pypa.io/en/stable/quickstart/): + +```bash +pip install prometheus-flask-exporter +``` +or paste it into requirements.txt: +``` +# newest version +prometheus-flask-exporter + +# or with specific version number +prometheus-flask-exporter==0.22.3 +``` +and then install dependencies from requirements.txt file as usual: +``` +pip install -r requirements.txt +``` + + +## Usage + +```python +from flask import Flask, request +from prometheus_flask_exporter import PrometheusMetrics + +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +# static information as metric +metrics.info('app_info', 'Application info', version='1.0.3') + +@app.route('/') +def main(): + pass # requests tracked by default + +@app.route('/skip') +@metrics.do_not_track() +def skip(): + pass # default metrics are not collected + +@app.route('/<item_type>') +@metrics.do_not_track() +@metrics.counter('invocation_by_type', 'Number of invocations by type', + labels={'item_type': lambda: request.view_args['type']}) +def by_type(item_type): + pass # only the counter is collected, not the default metrics + +@app.route('/long-running') +@metrics.gauge('in_progress', 'Long running requests in progress') +def long_running(): + pass + +@app.route('/status/<int:status>') +@metrics.do_not_track() +@metrics.summary('requests_by_status', 'Request latencies by status', + labels={'status': lambda r: r.status_code}) +@metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path', + labels={'status': lambda r: r.status_code, 'path': lambda: request.path}) +def echo_status(status): + return 'Status: %s' % status, status +``` + +## Default metrics + +The following metrics are exported by default +(unless the `export_defaults` is set to `False`). + +- `flask_http_request_duration_seconds` (Histogram) + Labels: `method`, `path` and `status`. + Flask HTTP request duration in seconds for all Flask requests. +- `flask_http_request_total` (Counter) + Labels: `method` and `status`. + Total number of HTTP requests for all Flask requests. +- `flask_http_request_exceptions_total` (Counter) + Labels: `method` and `status`. + Total number of uncaught exceptions when serving Flask requests. +- `flask_exporter_info` (Gauge) + Information about the Prometheus Flask exporter itself (e.g. `version`). + +The prefix for the default metrics can be controlled by the `defaults_prefix` parameter. +If you don't want to use any prefix, pass the `prometheus_flask_exporter.NO_PREFIX` value in. +The buckets on the default request latency histogram can be changed by the `buckets` parameter, and if using a summary for them is more appropriate for your use case, then use the `default_latency_as_histogram=False` parameter. + +To register your own *default* metrics that will track all registered +Flask view functions, use the `register_default` function. + +```python +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +@app.route('/simple') +def simple_get(): + pass + +metrics.register_default( + metrics.counter( + 'by_path_counter', 'Request count by request paths', + labels={'path': lambda: request.path} + ) +) +``` + +*Note:* register your default metrics after all routes have been set up. +Also note, that Gauge metrics registered as default will track the +`/metrics` endpoint, and this can't be disabled at the moment. + +If you want to apply the same metric to multiple (but not all) endpoints, +create its wrapper first, then add to each function. + +```python +app = Flask(__name__) +metrics = PrometheusMetrics(app) + +by_path_counter = metrics.counter( + 'by_path_counter', 'Request count by request paths', + labels={'path': lambda: request.path} +) + +@app.route('/simple') +@by_path_counter +def simple_get(): + pass + +@app.route('/plain') +@by_path_counter +def plain(): + pass + +@app.route('/not/tracked/by/path') +def not_tracked_by_path(): + pass +``` + +You can avoid recording metrics on individual endpoints +by decorating them with `@metrics.do_not_track()`, or use the +`excluded_paths` argument when creating the `PrometheusMetrics` instance +that takes a regular expression (either a single string, or a list) and +matching paths will be excluded. These apply to both built-in and user-defined +default metrics, unless you disable it by setting the `exclude_user_defaults` +argument to `False`. If you have functions that are inherited or otherwise get +metrics collected that you don't want, you can use `@metrics.exclude_all_metrics()` +to exclude both default and non-default metrics being collected from it. + +## Configuration + +By default, the metrics are exposed on the same Flask application on the +`/metrics` endpoint and using the core Prometheus registry. +If this doesn't suit your needs, set the `path` argument to `None` and/or +the `export_defaults` argument to `False` plus change the `registry` +argument if needed. + +The `group_by` constructor argument controls what +the default request duration metric is tracked by: endpoint (function) +instead of URI path (the default). This parameter also accepts a function +to extract the value from the request, or a name of a property of the request object. +Examples: + +```python +PrometheusMetrics(app, group_by='path') # the default +PrometheusMetrics(app, group_by='endpoint') # by endpoint +PrometheusMetrics(app, group_by='url_rule') # by URL rule + +def custom_rule(req): # the Flask request object + """ The name of the function becomes the label name. """ + return '%s::%s' % (req.method, req.path) + +PrometheusMetrics(app, group_by=custom_rule) # by a function + +# Error: this is not supported: +PrometheusMetrics(app, group_by=lambda r: r.path) +``` + +> The `group_by_endpoint` argument is deprecated since 0.4.0, +> please use the new `group_by` argument. + +The `register_endpoint` allows exposing the metrics endpoint on a specific path. +It also allows passing in a Flask application to register it on but defaults +to the main one if not defined. + +Similarly, the `start_http_server` allows exposing the endpoint on an +independent Flask application on a selected HTTP port. +It also supports overriding the endpoint's path and the HTTP listen address. + +You can also set default labels to add to every request managed by +a `PrometheusMetrics` instance, using the `default_labels` argument. +This needs to be a dictionary, where each key will become a metric +label name, and the values the label values. +These can be constant values, or dynamic functions, see below in the +[Labels](#Labels) section. + +> The `static_labels` argument is deprecated since 0.15.0, +> please use the new `default_labels` argument. + +If you use another framework over Flask (perhaps +[Connexion](https://connexion.readthedocs.io/)) then you might return +responses from your endpoints that Flask can't deal with by default. +If that is the case, you might need to pass in a `response_converter` +that takes the returned object and should convert that to a Flask +friendly response. +See `ConnexionPrometheusMetrics` for an example. + +## Labels + +When defining labels for metrics on functions, +the following values are supported in the dictionary: + +- A simple static value +- A no-argument callable +- A single argument callable that will receive the Flask response + as the argument + +Label values are evaluated within the request context. + +## Initial metric values +_For more info see: https://github.com/prometheus/client_python#labels_ + +Metrics without any labels will get an initial value. +Metrics that only have static-value labels will also have an initial value. (except when they are created with the option `initial_value_when_only_static_labels=False`) +Metrics that have one or more callable-value labels will not have an initial value. + +## Application information + +The `PrometheusMetrics.info(..)` method provides a way to expose +information as a `Gauge` metric, the application version for example. + +The metric is returned from the method to allow changing its value +from the default `1`: + +```python +metrics = PrometheusMetrics(app) +info = metrics.info('dynamic_info', 'Something dynamic') +... +info.set(42.1) +``` + +## Examples + +See some simple examples visualized on a Grafana dashboard by running +the demo in the [examples/sample-signals](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/sample-signals) folder. + + + +## App Factory Pattern + +This library also supports the Flask [app factory pattern](http://flask.pocoo.org/docs/1.0/patterns/appfactories/). Use the `init_app` method to attach the library to one or more application objects. Note, that to use this mode, you'll need to use the `for_app_factory()` class method to create the `metrics` instance, or pass in `None` for the `app` in the constructor. + +```python +metrics = PrometheusMetrics.for_app_factory() +# then later: +metrics.init_app(app) +``` + +## Securing the metrics endpoint + +If you wish to have authentication (or any other special handling) on the metrics endpoint, +you can use the `metrics_decorator` argument when creating the `PrometheusMetrics` instance. +For example to integrate with [Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth) +use it like it's shown in the example below. + +```python +app = Flask(__name__) +auth = HTTPBasicAuth() +metrics = PrometheusMetrics(app, metrics_decorator=auth.login_required) + +# ... other authentication setup like @auth.verify_password below +``` + +See a full example in the [examples/flask-httpauth](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/flask-httpauth) folder. + +## Custom metrics endpoint + +You can also take full control of the metrics endpoint by generating its contents, +and managing how it is exposed by yourself. + +```python +app = Flask(__name__) +# path=None to avoid registering a /metrics endpoint on the same Flask app +metrics = PrometheusMetrics(app, path=None) + +# later ... generate the response (and its content type) to expose to Prometheus +response_data, content_type = metrics.generate_metrics() +``` + +See the related conversation in [issue #135](https://github.com/rycus86/prometheus_flask_exporter/issues/135). + +## Debug mode + +Please note, that changes being live-reloaded, when running the Flask +app with `debug=True`, are not going to be reflected in the metrics. +See [https://github.com/rycus86/prometheus_flask_exporter/issues/4](https://github.com/rycus86/prometheus_flask_exporter/issues/4) +for more details. + +Alternatively - since version `0.5.1` - if you set the `DEBUG_METRICS` +environment variable, you will get metrics for the latest reloaded code. +These will be exported on the main Flask app. +Serving the metrics on a different port is not going to work +most probably - e.g. `PrometheusMetrics.start_http_server(..)` is not +expected to work. + +## WSGI + +Getting accurate metrics for WSGI apps might require a bit more setup. +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#5](https://github.com/rycus86/prometheus_flask_exporter/issues/5) issue. + +### Multiprocess applications + +For multiprocess applications (WSGI or otherwise), you can find some +helper classes in the `prometheus_flask_exporter.multiprocess` module. +These provide convenience wrappers for exposing metrics in an +environment where multiple copies of the application will run on a single host. + +```python +# an extension targeted at Gunicorn deployments +from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics + +app = Flask(__name__) +metrics = GunicornPrometheusMetrics(app) + +# then in the Gunicorn config file: +from prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics + +def when_ready(server): + GunicornPrometheusMetrics.start_http_server_when_ready(8080) + +def child_exit(server, worker): + GunicornPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid) +``` + +Also see the `GunicornInternalPrometheusMetrics` class if you want to have +the metrics HTTP endpoint exposed internally, on the same Flask application. + +```python +# an extension targeted at Gunicorn deployments with an internal metrics endpoint +from prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics + +app = Flask(__name__) +metrics = GunicornInternalPrometheusMetrics(app) + +# then in the Gunicorn config file: +from prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics + +def child_exit(server, worker): + GunicornInternalPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid) +``` + +There's a small wrapper available for [Gunicorn](https://gunicorn.org/) and +[uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/index.html), for everything +else you can extend the `prometheus_flask_exporter.multiprocess.MultiprocessPrometheusMetrics` class +and implement the `should_start_http_server` method at least. + +```python +from prometheus_flask_exporter.multiprocess import MultiprocessPrometheusMetrics + +class MyMultiprocessMetrics(MultiprocessPrometheusMetrics): + def should_start_http_server(self): + return this_worker() == primary_worker() +``` + +This should return `True` on one process only, and the underlying +[Prometheus client library](https://github.com/prometheus/client_python) +will collect the metrics for all the forked children or siblings. + +An additional Flask extension for apps with `processes=N` and `threaded=False` exists +with the `MultiprocessInternalPrometheusMetrics` class. + +```python +from flask import Flask +from prometheus_flask_exporter.multiprocess import MultiprocessInternalPrometheusMetrics + +app = Flask(__name__) +metrics = MultiprocessInternalPrometheusMetrics(app) + +... + +if __name__ == '__main__': + app.run('0.0.0.0', 4000, processes=5, threaded=False) +``` + +__Note:__ this needs the `PROMETHEUS_MULTIPROC_DIR` environment variable +to point to a valid, writable directory. + +You'll also have to call the `metrics.start_http_server()` function +explicitly somewhere, and the `should_start_http_server` takes care of +only starting it once. +The [examples](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples) folder +has some working examples on this. + +Please also note, that the Prometheus client library does not collect process level +metrics, like memory, CPU and Python GC stats when multiprocessing is enabled. +See the [prometheus_flask_exporter#18](https://github.com/rycus86/prometheus_flask_exporter/issues/18) +issue for some more context and details. + +A final caveat is that the metrics HTTP server will listen on __any__ paths +on the given HTTP port, not only on `/metrics`, and it is not implemented +at the moment to be able to change this. + +### uWSGI lazy-apps + +When [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) is configured +to run with [lazy-apps]([lazy-apps](https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#preforking-vs-lazy-apps-vs-lazy)), +exposing the metrics endpoint on a separate HTTP server (and port) is not functioning yet. +A workaround is to register the endpoint on the main Flask application. + +```python +app = Flask(__name__) +metrics = UWsgiPrometheusMetrics(app) +metrics.register_endpoint('/metrics') +# instead of metrics.start_http_server(port) +``` + +See [#31](https://github.com/rycus86/prometheus_flask_exporter/issues/31) +for context, and please let me know if you know a better way! + +## Connexion integration + +The [Connexion](https://connexion.readthedocs.io/) library has some +support to automatically deal with certain response types, for example +dataclasses, which a plain Flask application would not accept. +To ease the integration, you can use `ConnexionPrometheusMetrics` in +place of `PrometheusMetrics` that has the `response_converter` set +appropriately to be able to deal with whatever Connexion supports for +Flask integrations. + +```python +import connexion +from prometheus_flask_exporter import ConnexionPrometheusMetrics + +app = connexion.App(__name__) +metrics = ConnexionPrometheusMetrics(app) +``` + +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#61](https://github.com/rycus86/prometheus_flask_exporter/issues/61) issue. + +There's a caveat about this integration, where any endpoints that +do not return JSON responses need to be decorated with +`@metrics.content_type('...')` as this integration would force them +to be `application/json` otherwise. + +```python +metrics = ConnexionPrometheusMetrics(app) + +@metrics.content_type('text/plain') +def plain_response(): + return 'plain text' +``` + +See the [prometheus_flask_exporter#64](https://github.com/rycus86/prometheus_flask_exporter/issues/64) issue for more details. + +## Flask-RESTful integration + +The [Flask-RESTful library](https://flask-restful.readthedocs.io/) has +some custom response handling logic, which can be helpful in some cases. +For example, returning `None` would fail on plain Flask, but it +works on Flask-RESTful. +To ease the integration, you can use `RESTfulPrometheusMetrics` in +place of `PrometheusMetrics` that sets the `response_converter` to use +the Flask-RESTful `API` response utilities. + +```python +from flask import Flask +from flask_restful import Api +from prometheus_flask_exporter import RESTfulPrometheusMetrics + +app = Flask(__name__) +restful_api = Api(app) +metrics = RESTfulPrometheusMetrics(app, restful_api) +``` + +See a working sample app in the `examples` folder, and also the +[prometheus_flask_exporter#62](https://github.com/rycus86/prometheus_flask_exporter/issues/62) issue. + +## License + +MIT + + +%prep +%autosetup -n prometheus-flask-exporter-0.22.3 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-prometheus-flask-exporter -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Mon Apr 10 2023 Python_Bot <Python_Bot@openeuler.org> - 0.22.3-1 +- Package Spec generated @@ -0,0 +1 @@ +489bdf3bd3277cebfe89f0628b4ac9a1 prometheus_flask_exporter-0.22.3.tar.gz |
