Skip to content

Commit

Permalink
Added ASGI application
Browse files Browse the repository at this point in the history
Signed-off-by: Emil Madsen <sovende@gmail.com>
  • Loading branch information
Skeen committed Feb 14, 2020
1 parent 484ed71 commit 63eee29
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,32 @@ from prometheus_client import start_wsgi_server
start_wsgi_server(8000)
```

#### ASGI

To use Prometheus with [ASGI](http://asgi.readthedocs.org/en/latest/), there is
`make_asgi_app` which creates an ASGI application.

Save the snippet below in a `myapp.py` file

```python
from prometheus_client import make_asgi_app

app = make_asgi_app()
```
Such an application can be useful when integrating Prometheus metrics with ASGI
apps.

The app can be used to serve the metrics through an ASGI implementation, such
as [daphne](https://github.com/django/daphne) or
[uvicorn](https://www.uvicorn.org/).
```bash
# Install daphne if you do not have it
pip install daphne
daphne myapp:app
```

Visit http://localhost:8000/ to see the metrics

#### Flask

To use Prometheus with [Flask](http://flask.pocoo.org/) we need to serve metrics through a Prometheus WSGI application. This can be achieved using [Flask's application dispatching](http://flask.pocoo.org/docs/latest/patterns/appdispatch/). Below is a working example.
Expand Down
5 changes: 5 additions & 0 deletions prometheus_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
generate_latest = exposition.generate_latest
MetricsHandler = exposition.MetricsHandler
make_wsgi_app = exposition.make_wsgi_app
try:
# Python >3.5 only
make_asgi_app = exposition.make_asgi_app
except:
pass
start_http_server = exposition.start_http_server
start_wsgi_server = exposition.start_wsgi_server
write_to_textfile = exposition.write_to_textfile
Expand Down
34 changes: 34 additions & 0 deletions prometheus_client/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from urllib.parse import parse_qs

from .exposition import choose_encoder
from .registry import REGISTRY


def make_asgi_app(registry=REGISTRY):
"""Create a ASGI app which serves the metrics from a registry."""

async def prometheus_app(scope, receive, send):
assert scope.get("type") == "http"
params = parse_qs(scope.get('query_string', b''))
r = registry
accept_header = "Accept: " + ",".join([
value.decode("utf8") for (name, value) in scope.get('headers')
if name.decode("utf8") == 'accept'
])
encoder, content_type = choose_encoder(accept_header)
if 'name[]' in params:
r = r.restricted_registry(params['name[]'])
output = encoder(r)

payload = await receive()
if payload.get("type") == "http.request":
await send(
{
"type": "http.response.start",
"status": 200,
"headers": [[b"Content-Type", content_type.encode('utf8')]],
}
)
await send({"type": "http.response.body", "body": output})

return prometheus_app
8 changes: 8 additions & 0 deletions prometheus_client/exposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
PYTHON26_OR_OLDER = sys.version_info < (2, 7)
PYTHON376_OR_NEWER = sys.version_info > (3, 7, 5)


def make_wsgi_app(registry=REGISTRY):
"""Create a WSGI app which serves the metrics from a registry."""

Expand Down Expand Up @@ -378,3 +379,10 @@ def instance_ip_grouping_key():
with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
s.connect(('localhost', 0))
return {'instance': s.getsockname()[0]}


try:
# Python >3.5 only
from .asgi import make_asgi_app
except:
pass

0 comments on commit 63eee29

Please sign in to comment.