prometheus-flask-exporter


Nameprometheus-flask-exporter JSON
Version 0.23.0 PyPI version JSON
download
home_pagehttps://github.com/rycus86/prometheus_flask_exporter
SummaryPrometheus metrics exporter for Flask
upload_time2023-10-27 00:04:03
maintainer
docs_urlNone
authorViktor Adam
requires_python
licenseMIT
keywords prometheus flask monitoring exporter
VCS
bugtrack_url
requirements flask prometheus_client werkzeug
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Prometheus Flask exporter

[![PyPI](https://img.shields.io/pypi/v/prometheus-flask-exporter.svg)](https://pypi.python.org/pypi/prometheus-flask-exporter)
[![PyPI](https://img.shields.io/pypi/pyversions/prometheus-flask-exporter.svg)](https://pypi.python.org/pypi/prometheus-flask-exporter)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/prometheus-flask-exporter.svg)](https://pypi.python.org/pypi/prometheus-flask-exporter)
[![Coverage Status](https://coveralls.io/repos/github/rycus86/prometheus_flask_exporter/badge.svg?branch=master)](https://coveralls.io/github/rycus86/prometheus_flask_exporter?branch=master)
[![Code Climate](https://codeclimate.com/github/rycus86/prometheus_flask_exporter/badges/gpa.svg)](https://codeclimate.com/github/rycus86/prometheus_flask_exporter)
[![Test & publish package](https://github.com/rycus86/prometheus_flask_exporter/actions/workflows/test-and-publish.yml/badge.svg)](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.23.0
```
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.

![Example dashboard](https://github.com/rycus86/prometheus_flask_exporter/raw/master/examples/sample-signals/dashboard.png)

## 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

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/rycus86/prometheus_flask_exporter",
    "name": "prometheus-flask-exporter",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "prometheus,flask,monitoring,exporter",
    "author": "Viktor Adam",
    "author_email": "rycus86@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/05/5a/7b4346cdd1273ef2875b2aa478ffd97a47cb132d3c7de443a31338cda8ee/prometheus_flask_exporter-0.23.0.tar.gz",
    "platform": null,
    "description": "# Prometheus Flask exporter\n\n[![PyPI](https://img.shields.io/pypi/v/prometheus-flask-exporter.svg)](https://pypi.python.org/pypi/prometheus-flask-exporter)\n[![PyPI](https://img.shields.io/pypi/pyversions/prometheus-flask-exporter.svg)](https://pypi.python.org/pypi/prometheus-flask-exporter)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/prometheus-flask-exporter.svg)](https://pypi.python.org/pypi/prometheus-flask-exporter)\n[![Coverage Status](https://coveralls.io/repos/github/rycus86/prometheus_flask_exporter/badge.svg?branch=master)](https://coveralls.io/github/rycus86/prometheus_flask_exporter?branch=master)\n[![Code Climate](https://codeclimate.com/github/rycus86/prometheus_flask_exporter/badges/gpa.svg)](https://codeclimate.com/github/rycus86/prometheus_flask_exporter)\n[![Test & publish package](https://github.com/rycus86/prometheus_flask_exporter/actions/workflows/test-and-publish.yml/badge.svg)](https://github.com/rycus86/prometheus_flask_exporter/actions/workflows/test-and-publish.yml)\n\nThis library provides HTTP request metrics to export into\n[Prometheus](https://prometheus.io/).\nIt can also track method invocations using convenient functions.\n\n## Installing\n\nInstall using [PIP](https://pip.pypa.io/en/stable/quickstart/):\n\n```bash\npip install prometheus-flask-exporter\n```\nor paste it into requirements.txt:\n```\n# newest version\nprometheus-flask-exporter\n\n# or with specific version number\nprometheus-flask-exporter==0.23.0\n```\nand then install dependencies from requirements.txt file as usual:\n```\npip install -r requirements.txt\n```\n\n\n## Usage\n\n```python\nfrom flask import Flask, request\nfrom prometheus_flask_exporter import PrometheusMetrics\n\napp = Flask(__name__)\nmetrics = PrometheusMetrics(app)\n\n# static information as metric\nmetrics.info('app_info', 'Application info', version='1.0.3')\n\n@app.route('/')\ndef main():\n    pass  # requests tracked by default\n\n@app.route('/skip')\n@metrics.do_not_track()\ndef skip():\n    pass  # default metrics are not collected\n\n@app.route('/<item_type>')\n@metrics.do_not_track()\n@metrics.counter('invocation_by_type', 'Number of invocations by type',\n         labels={'item_type': lambda: request.view_args['type']})\ndef by_type(item_type):\n    pass  # only the counter is collected, not the default metrics\n\n@app.route('/long-running')\n@metrics.gauge('in_progress', 'Long running requests in progress')\ndef long_running():\n    pass\n\n@app.route('/status/<int:status>')\n@metrics.do_not_track()\n@metrics.summary('requests_by_status', 'Request latencies by status',\n                 labels={'status': lambda r: r.status_code})\n@metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path',\n                   labels={'status': lambda r: r.status_code, 'path': lambda: request.path})\ndef echo_status(status):\n    return 'Status: %s' % status, status\n```\n\n## Default metrics\n\nThe following metrics are exported by default\n(unless the `export_defaults` is set to `False`).\n\n- `flask_http_request_duration_seconds` (Histogram)\n  Labels: `method`, `path` and `status`.\n  Flask HTTP request duration in seconds for all Flask requests.\n- `flask_http_request_total` (Counter)\n  Labels: `method` and `status`.\n  Total number of HTTP requests for all Flask requests.\n- `flask_http_request_exceptions_total` (Counter)\n  Labels: `method` and `status`.\n  Total number of uncaught exceptions when serving Flask requests.\n- `flask_exporter_info` (Gauge)\n  Information about the Prometheus Flask exporter itself (e.g. `version`).\n\nThe prefix for the default metrics can be controlled by the `defaults_prefix` parameter.\nIf you don't want to use any prefix, pass the `prometheus_flask_exporter.NO_PREFIX` value in.\nThe 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.\n\nTo register your own *default* metrics that will track all registered\nFlask view functions, use the `register_default` function.\n\n```python\napp = Flask(__name__)\nmetrics = PrometheusMetrics(app)\n\n@app.route('/simple')\ndef simple_get():\n    pass\n    \nmetrics.register_default(\n    metrics.counter(\n        'by_path_counter', 'Request count by request paths',\n        labels={'path': lambda: request.path}\n    )\n)\n```\n\n*Note:* register your default metrics after all routes have been set up.\nAlso note, that Gauge metrics registered as default will track the\n`/metrics` endpoint, and this can't be disabled at the moment.\n\nIf you want to apply the same metric to multiple (but not all) endpoints,\ncreate its wrapper first, then add to each function.\n\n```python\napp = Flask(__name__)\nmetrics = PrometheusMetrics(app)\n\nby_path_counter = metrics.counter(\n    'by_path_counter', 'Request count by request paths',\n    labels={'path': lambda: request.path}\n)\n\n@app.route('/simple')\n@by_path_counter\ndef simple_get():\n    pass\n    \n@app.route('/plain')\n@by_path_counter\ndef plain():\n    pass\n    \n@app.route('/not/tracked/by/path')\ndef not_tracked_by_path():\n    pass\n```\n\nYou can avoid recording metrics on individual endpoints\nby decorating them with `@metrics.do_not_track()`, or use the \n`excluded_paths` argument when creating the `PrometheusMetrics` instance\nthat takes a regular expression (either a single string, or a list) and\nmatching paths will be excluded. These apply to both built-in and user-defined\ndefault metrics, unless you disable it by setting the `exclude_user_defaults`\nargument to `False`. If you have functions that are inherited or otherwise get\nmetrics collected that you don't want, you can use `@metrics.exclude_all_metrics()`\nto exclude both default and non-default metrics being collected from it.\n\n## Configuration\n\nBy default, the metrics are exposed on the same Flask application on the\n`/metrics` endpoint and using the core Prometheus registry.\nIf this doesn't suit your needs, set the `path` argument to `None` and/or\nthe `export_defaults` argument to `False` plus change the `registry`\nargument if needed.\n\nThe `group_by` constructor argument controls what\nthe default request duration metric is tracked by: endpoint (function)\ninstead of URI path (the default). This parameter also accepts a function\nto extract the value from the request, or a name of a property of the request object.\nExamples:\n\n```python\nPrometheusMetrics(app, group_by='path')         # the default\nPrometheusMetrics(app, group_by='endpoint')     # by endpoint\nPrometheusMetrics(app, group_by='url_rule')     # by URL rule\n\ndef custom_rule(req):  # the Flask request object\n    \"\"\" The name of the function becomes the label name. \"\"\"\n    return '%s::%s' % (req.method, req.path)\n\nPrometheusMetrics(app, group_by=custom_rule)    # by a function\n\n# Error: this is not supported:\nPrometheusMetrics(app, group_by=lambda r: r.path)\n```\n\n> The `group_by_endpoint` argument is deprecated since 0.4.0,\n> please use the new `group_by` argument.\n\nThe `register_endpoint` allows exposing the metrics endpoint on a specific path.\nIt also allows passing in a Flask application to register it on but defaults\nto the main one if not defined.\n\nSimilarly, the `start_http_server` allows exposing the endpoint on an\nindependent Flask application on a selected HTTP port.\nIt also supports overriding the endpoint's path and the HTTP listen address.\n\nYou can also set default labels to add to every request managed by\na `PrometheusMetrics` instance, using the `default_labels` argument.\nThis needs to be a dictionary, where each key will become a metric\nlabel name, and the values the label values.\nThese can be constant values, or dynamic functions, see below in the\n[Labels](#Labels) section.\n\n> The `static_labels` argument is deprecated since 0.15.0,\n> please use the new `default_labels` argument.\n\nIf you use another framework over Flask (perhaps\n[Connexion](https://connexion.readthedocs.io/)) then you might return\nresponses from your endpoints that Flask can't deal with by default.\nIf that is the case, you might need to pass in a `response_converter`\nthat takes the returned object and should convert that to a Flask\nfriendly response.\nSee `ConnexionPrometheusMetrics` for an example.\n\n## Labels\n\nWhen defining labels for metrics on functions,\nthe following values are supported in the dictionary:\n\n- A simple static value\n- A no-argument callable\n- A single argument callable that will receive the Flask response\n  as the argument\n\nLabel values are evaluated within the request context.\n\n## Initial metric values\n_For more info see: https://github.com/prometheus/client_python#labels_\n\nMetrics without any labels will get an initial value.\nMetrics 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`)\nMetrics that have one or more callable-value labels will not have an initial value.\n\n## Application information\n\nThe `PrometheusMetrics.info(..)` method provides a way to expose\ninformation as a `Gauge` metric, the application version for example.\n\nThe metric is returned from the method to allow changing its value\nfrom the default `1`:\n\n```python\nmetrics = PrometheusMetrics(app)\ninfo = metrics.info('dynamic_info', 'Something dynamic')\n...\ninfo.set(42.1)\n```\n\n## Examples\n\nSee some simple examples visualized on a Grafana dashboard by running\nthe demo in the [examples/sample-signals](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/sample-signals) folder.\n\n![Example dashboard](https://github.com/rycus86/prometheus_flask_exporter/raw/master/examples/sample-signals/dashboard.png)\n\n## App Factory Pattern\n\nThis 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.\n\n```python\nmetrics = PrometheusMetrics.for_app_factory()\n# then later:\nmetrics.init_app(app)\n```\n\n## Securing the metrics endpoint\n\nIf you wish to have authentication (or any other special handling) on the metrics endpoint,\nyou can use the `metrics_decorator` argument when creating the `PrometheusMetrics` instance.\nFor example to integrate with [Flask-HTTPAuth](https://github.com/miguelgrinberg/Flask-HTTPAuth)\nuse it like it's shown in the example below.\n\n```python\napp = Flask(__name__)\nauth = HTTPBasicAuth()\nmetrics = PrometheusMetrics(app, metrics_decorator=auth.login_required)\n\n# ... other authentication setup like @auth.verify_password below\n```\n\nSee a full example in the [examples/flask-httpauth](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples/flask-httpauth) folder.\n\n## Custom metrics endpoint\n\nYou can also take full control of the metrics endpoint by generating its contents,\nand managing how it is exposed by yourself.\n\n```python\napp = Flask(__name__)\n# path=None to avoid registering a /metrics endpoint on the same Flask app\nmetrics = PrometheusMetrics(app, path=None)\n\n# later ... generate the response (and its content type) to expose to Prometheus\nresponse_data, content_type = metrics.generate_metrics()\n```\n\nSee the related conversation in [issue #135](https://github.com/rycus86/prometheus_flask_exporter/issues/135).\n\n## Debug mode\n\nPlease note, that changes being live-reloaded, when running the Flask\napp with `debug=True`, are not going to be reflected in the metrics.\nSee [https://github.com/rycus86/prometheus_flask_exporter/issues/4](https://github.com/rycus86/prometheus_flask_exporter/issues/4)\nfor more details.\n\nAlternatively - since version `0.5.1` - if you set the `DEBUG_METRICS`\nenvironment variable, you will get metrics for the latest reloaded code.\nThese will be exported on the main Flask app.\nServing the metrics on a different port is not going to work\nmost probably - e.g. `PrometheusMetrics.start_http_server(..)` is not\nexpected to work.\n\n## WSGI\n\nGetting accurate metrics for WSGI apps might require a bit more setup.\nSee a working sample app in the `examples` folder, and also the\n[prometheus_flask_exporter#5](https://github.com/rycus86/prometheus_flask_exporter/issues/5) issue.\n\n### Multiprocess applications\n\nFor multiprocess applications (WSGI or otherwise), you can find some\nhelper classes in the `prometheus_flask_exporter.multiprocess` module.\nThese provide convenience wrappers for exposing metrics in an\nenvironment where multiple copies of the application will run on a single host.\n\n```python\n# an extension targeted at Gunicorn deployments\nfrom prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics\n\napp = Flask(__name__)\nmetrics = GunicornPrometheusMetrics(app)\n\n# then in the Gunicorn config file:\nfrom prometheus_flask_exporter.multiprocess import GunicornPrometheusMetrics\n\ndef when_ready(server):\n    GunicornPrometheusMetrics.start_http_server_when_ready(8080)\n\ndef child_exit(server, worker):\n    GunicornPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid)\n```\n\nAlso see the `GunicornInternalPrometheusMetrics` class if you want to have\nthe metrics HTTP endpoint exposed internally, on the same Flask application.\n\n```python\n# an extension targeted at Gunicorn deployments with an internal metrics endpoint\nfrom prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics\n\napp = Flask(__name__)\nmetrics = GunicornInternalPrometheusMetrics(app)\n\n# then in the Gunicorn config file:\nfrom prometheus_flask_exporter.multiprocess import GunicornInternalPrometheusMetrics\n\ndef child_exit(server, worker):\n    GunicornInternalPrometheusMetrics.mark_process_dead_on_child_exit(worker.pid)\n```\n\nThere's a small wrapper available for [Gunicorn](https://gunicorn.org/) and\n[uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/index.html), for everything\nelse you can extend the `prometheus_flask_exporter.multiprocess.MultiprocessPrometheusMetrics` class\nand implement the `should_start_http_server` method at least.\n\n```python\nfrom prometheus_flask_exporter.multiprocess import MultiprocessPrometheusMetrics\n\nclass MyMultiprocessMetrics(MultiprocessPrometheusMetrics):\n    def should_start_http_server(self):\n        return this_worker() == primary_worker()\n```\n\nThis should return `True` on one process only, and the underlying\n[Prometheus client library](https://github.com/prometheus/client_python)\nwill collect the metrics for all the forked children or siblings.\n\nAn additional Flask extension for apps with `processes=N` and `threaded=False` exists\nwith the `MultiprocessInternalPrometheusMetrics` class.\n\n```python\nfrom flask import Flask\nfrom prometheus_flask_exporter.multiprocess import MultiprocessInternalPrometheusMetrics\n\napp = Flask(__name__)\nmetrics = MultiprocessInternalPrometheusMetrics(app)\n\n...\n\nif __name__ == '__main__':\n    app.run('0.0.0.0', 4000, processes=5, threaded=False)\n```\n\n__Note:__ this needs the `PROMETHEUS_MULTIPROC_DIR` environment variable\nto point to a valid, writable directory.\n\nYou'll also have to call the `metrics.start_http_server()` function\nexplicitly somewhere, and the `should_start_http_server` takes care of\nonly starting it once.\nThe [examples](https://github.com/rycus86/prometheus_flask_exporter/tree/master/examples) folder\nhas some working examples on this.\n\nPlease also note, that the Prometheus client library does not collect process level\nmetrics, like memory, CPU and Python GC stats when multiprocessing is enabled.\nSee the [prometheus_flask_exporter#18](https://github.com/rycus86/prometheus_flask_exporter/issues/18)\nissue for some more context and details.\n\nA final caveat is that the metrics HTTP server will listen on __any__ paths\non the given HTTP port, not only on `/metrics`, and it is not implemented\nat the moment to be able to change this.\n\n### uWSGI lazy-apps\n\nWhen [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) is configured \nto run with [lazy-apps]([lazy-apps](https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#preforking-vs-lazy-apps-vs-lazy)),\nexposing the metrics endpoint on a separate HTTP server (and port) is not functioning yet.\nA workaround is to register the endpoint on the main Flask application.\n\n```python\napp = Flask(__name__)\nmetrics = UWsgiPrometheusMetrics(app)\nmetrics.register_endpoint('/metrics')\n# instead of metrics.start_http_server(port)\n```\n\nSee [#31](https://github.com/rycus86/prometheus_flask_exporter/issues/31)\nfor context, and please let me know if you know a better way!\n\n## Connexion integration\n\nThe [Connexion](https://connexion.readthedocs.io/) library has some\nsupport to automatically deal with certain response types, for example\ndataclasses, which a plain Flask application would not accept.\nTo ease the integration, you can use `ConnexionPrometheusMetrics` in\nplace of `PrometheusMetrics` that has the `response_converter` set\nappropriately to be able to deal with whatever Connexion supports for\nFlask integrations.\n\n```python\nimport connexion\nfrom prometheus_flask_exporter import ConnexionPrometheusMetrics\n\napp = connexion.App(__name__)\nmetrics = ConnexionPrometheusMetrics(app)\n```\n\nSee a working sample app in the `examples` folder, and also the\n[prometheus_flask_exporter#61](https://github.com/rycus86/prometheus_flask_exporter/issues/61) issue. \n\nThere's a caveat about this integration, where any endpoints that\ndo not return JSON responses need to be decorated with\n`@metrics.content_type('...')` as this integration would force them\nto be `application/json` otherwise.\n\n```python\nmetrics = ConnexionPrometheusMetrics(app)\n\n@metrics.content_type('text/plain')\ndef plain_response():\n    return 'plain text'\n```\n\nSee the [prometheus_flask_exporter#64](https://github.com/rycus86/prometheus_flask_exporter/issues/64) issue for more details.\n\n## Flask-RESTful integration\n\nThe [Flask-RESTful library](https://flask-restful.readthedocs.io/) has\nsome custom response handling logic, which can be helpful in some cases.\nFor example, returning `None` would fail on plain Flask, but it\nworks on Flask-RESTful.\nTo ease the integration, you can use `RESTfulPrometheusMetrics` in\nplace of `PrometheusMetrics` that sets the `response_converter` to use\nthe Flask-RESTful `API` response utilities.\n\n```python\nfrom flask import Flask\nfrom flask_restful import Api\nfrom prometheus_flask_exporter import RESTfulPrometheusMetrics\n\napp = Flask(__name__)\nrestful_api = Api(app)\nmetrics = RESTfulPrometheusMetrics(app, restful_api)\n```\n\nSee a working sample app in the `examples` folder, and also the\n[prometheus_flask_exporter#62](https://github.com/rycus86/prometheus_flask_exporter/issues/62) issue.\n\n## License\n\nMIT\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Prometheus metrics exporter for Flask",
    "version": "0.23.0",
    "project_urls": {
        "Download": "https://github.com/rycus86/prometheus_flask_exporter/archive/0.23.0.tar.gz",
        "Homepage": "https://github.com/rycus86/prometheus_flask_exporter"
    },
    "split_keywords": [
        "prometheus",
        "flask",
        "monitoring",
        "exporter"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2cf7ad9ad5bdab5af0bc2dca568687234f0bac5484dcb3666c5d9da43e46b93d",
                "md5": "13928abf668c763556265e37b1942682",
                "sha256": "7a026b4fdd54ebeddb77589333efe3a1ec43c7c717468825b0b3e9b6c33f7e9e"
            },
            "downloads": -1,
            "filename": "prometheus_flask_exporter-0.23.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "13928abf668c763556265e37b1942682",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 18936,
            "upload_time": "2023-10-27T00:04:02",
            "upload_time_iso_8601": "2023-10-27T00:04:02.275176Z",
            "url": "https://files.pythonhosted.org/packages/2c/f7/ad9ad5bdab5af0bc2dca568687234f0bac5484dcb3666c5d9da43e46b93d/prometheus_flask_exporter-0.23.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "055a7b4346cdd1273ef2875b2aa478ffd97a47cb132d3c7de443a31338cda8ee",
                "md5": "18fe2bfb88bf784e972e5c5b22f2eea7",
                "sha256": "e4e6beb1b8e1e164da6d70fe1edefc95ef184f113b5047f66f4b7262233da9c0"
            },
            "downloads": -1,
            "filename": "prometheus_flask_exporter-0.23.0.tar.gz",
            "has_sig": false,
            "md5_digest": "18fe2bfb88bf784e972e5c5b22f2eea7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 31580,
            "upload_time": "2023-10-27T00:04:03",
            "upload_time_iso_8601": "2023-10-27T00:04:03.889379Z",
            "url": "https://files.pythonhosted.org/packages/05/5a/7b4346cdd1273ef2875b2aa478ffd97a47cb132d3c7de443a31338cda8ee/prometheus_flask_exporter-0.23.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-27 00:04:03",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "rycus86",
    "github_project": "prometheus_flask_exporter",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "flask",
            "specs": []
        },
        {
            "name": "prometheus_client",
            "specs": []
        },
        {
            "name": "werkzeug",
            "specs": [
                [
                    ">=",
                    "3.0.1"
                ]
            ]
        }
    ],
    "lcname": "prometheus-flask-exporter"
}
        
Elapsed time: 0.14315s