Skip to content

Commit

Permalink
Add ASGI middleware support
Browse files Browse the repository at this point in the history
  • Loading branch information
claws committed Sep 19, 2021
1 parent 8f2cbb5 commit 3f1fdf8
Show file tree
Hide file tree
Showing 26 changed files with 1,247 additions and 229 deletions.
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
@@ -1,4 +1,4 @@
name: Python Package Workflow
name: CI Pipeline

on:
push:
Expand Down Expand Up @@ -39,9 +39,17 @@ jobs:
- name: Check code style
run: |
make check-style
- name: Install package on Python 3.6
# Quart is not supported on Python 3.6
if: ${{ matrix.python-version == '3.6' }}
run: |
echo "Python version is: ${{ matrix.python-version }}"
pip install .[aiohttp,binary,starlette] --use-feature=in-tree-build
- name: Install package
if: ${{ matrix.python-version != '3.6' }}
run: |
pip install .[aiohttp,binary] --use-feature=in-tree-build
echo "Python version is: ${{ matrix.python-version }}"
pip install .[aiohttp,binary,starlette,quart] --use-feature=in-tree-build
- name: Run unit tests
run: |
make test
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yml
@@ -1,6 +1,6 @@
build:
image: latest
python:
version: 3.6
version: 3.9
pip_install: true
formats: []
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -16,3 +16,6 @@
- Updated documentation to improve clarity and to use the sphinx_material theme.

- Improved test coverage. Removed unused code.

- Updated unit tests to gracefully handle when optional extras are not installed.
This specifically helps run tests on Python 3.6 where Quart is not supported.
8 changes: 3 additions & 5 deletions Makefile
@@ -1,6 +1,6 @@
# This makefile has been created to help developers perform common actions.
# It assumes it is operating in an environment, such as a virtual env,
# where the python command links to the Python3.6 executable.
# where the python command links to the Python3.7 executable.


# Do not remove this block. It is used by the 'help' rule when
Expand All @@ -9,8 +9,7 @@
# help: aioprometheus Makefile help
# help:

VENVS_DIR := $(HOME)/.venvs
VENV_DIR := $(VENVS_DIR)/vap
VENV_DIR := venv

# help: help - display this makefile's help information
.PHONY: help
Expand All @@ -21,11 +20,10 @@ help:
# help: venv - create a virtual environment for development
.PHONY: venv
venv:
@test -d "$(VENVS_DIR)" || mkdir -p "$(VENVS_DIR)"
@rm -Rf "$(VENV_DIR)"
@python3 -m venv "$(VENV_DIR)"
@/bin/bash -c "source $(VENV_DIR)/bin/activate && pip install pip --upgrade && pip install -r requirements.dev.txt"
@/bin/bash -c "source $(VENV_DIR)/bin/activate && pip install -e ."
@/bin/bash -c "source $(VENV_DIR)/bin/activate && pip install -e .[aiohttp,binary,starlette,quart]"
@echo "Enter virtual environment using:\n\n\t$ source $(VENV_DIR)/bin/activate\n"


Expand Down
122 changes: 76 additions & 46 deletions README.rst
@@ -1,25 +1,16 @@
.. image:: https://github.com/claws/aioprometheus/workflows/Python%20Package%20Workflow/badge.svg?branch=master
:target: https://github.com/claws/aioprometheus/actions?query=branch%3Amaster

.. image:: https://img.shields.io/pypi/v/aioprometheus.svg
:target: https://pypi.python.org/pypi/aioprometheus

.. image:: https://readthedocs.org/projects/aioprometheus/badge/?version=latest
:target: https://aioprometheus.readthedocs.io/en/latest

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black

aioprometheus
=============

|ci status| |pypi| |python| |docs| |license|

`aioprometheus` is a Prometheus Python client library for asyncio-based
applications. It provides metrics collection and serving capabilities for
use with Prometheus and compatible monitoring systems. It supports exporting
metrics into text and binary formats and pushing metrics to a gateway.

`aioprometheus` can be used in applications built with FastAPI/Starlette,
Quart, aiohttp as well as networking apps built upon asyncio.
The ASGI middleware in `aioprometheus` can be used in FastAPI/Starlette and
Quart applications. `aioprometheus` can also be used in other kinds of asyncio
applications too.

The project documentation can be found on
`ReadTheDocs <http://aioprometheus.readthedocs.org/>`_.
Expand All @@ -32,9 +23,28 @@ Install
$ pip install aioprometheus
The ASGI middleware does not have any external dependencies but the Starlette
and Quart convenience functions that handle metrics requests do.

If you plan on using the ASGI middleware in a Starlette / FastAPI application
then you can install the extra dependencies alongside `aioprometheus` by adding
extras to the install.

.. code-block:: console
$ pip install aioprometheus[starlette]
If you plan on using the ASGI middleware in a Quart application then you can
install the extra dependencies alongside `aioprometheus` by adding extras
to the install.

.. code-block:: console
$ pip install aioprometheus[quart]
A Prometheus Push Gateway client and a HTTP service are included, but their
dependencies are not installed by default. You can install them alongside
`aioprometheus` by adding optional extras to the install.
`aioprometheus` by adding extras to the install.

.. code-block:: console
Expand All @@ -53,7 +63,7 @@ Multiple optional dependencies can be listed at once, such as:

.. code-block:: console
$ pip install aioprometheus[aiohttp,binary]
$ pip install aioprometheus[aiohttp,binary,starlette,quart]
Usage
Expand Down Expand Up @@ -91,55 +101,59 @@ expose them to Prometheus or a compatible metrics collector. There are
multiple strategies available for this and the right choice depends on the
kind of thing being instrumented.

An example showing how aioprometheus can be used within a FastAPI app to
export metrics is shown below.

.. code-block:: python
"""
This example uses adds some simple Prometheus instrumentation to a FastAPI
application. In this example a counter metric is instantiated and gets
updated whenever the "/" route is accessed. A '/metrics' route is added to
the application using the standard web framework method. The metrics route
renders Prometheus metrics from the default collector registry into the
appropriate format.
If you are instrumenting a Starlette, FastAPI or Quart application then the
easiest option for adding Prometheus metrics is to use the ASGI Middleware
provided by `aioprometheus`.

Run:
The ASGI middleware provides a default set of metrics that include counters
for total requests received, total responses sent, exceptions raised and
response status codes for route handlers.

(venv) $ pip install fastapi uvicorn
(venv) $ python fastapi_example.py
The example below shows how to use the aioprometheus ASGI middleware in a
FastAPI application. FastAPI is built upon Starlette so using the middleware
in Starlette would be the same.

"""
.. code-block:: python
from typing import List
from fastapi import FastAPI, Request, Response
from fastapi import FastAPI, Header, Request, Response
from aioprometheus import Counter, MetricsMiddleware
from aioprometheus.asgi.starlette import metrics
from aioprometheus import Counter, REGISTRY, render
app = FastAPI()
# Any custom application metrics are automatically included in the exposed
# metrics. It is a good idea to attach the metrics to 'app.state' so they
# can easily be accessed in the route handler - as metrics are often
# created in a different module than where they are used.
app.state.users_events_counter = Counter("events", "Number of events.")
app = FastAPI()
app.state.events_counter = Counter("events", "Number of events.")
app.add_middleware(MetricsMiddleware)
app.add_route("/metrics", metrics)
@app.get("/")
async def hello(request: Request):
request.app.state.events_counter.inc({"path": "/"})
return "FastAPI Hello"
async def root(request: Request):
return Response("FastAPI Middleware Example")
@app.get("/metrics")
async def handle_metrics(request: Request, accept: List[str] = Header(None)):
content, http_headers = render(REGISTRY, accept)
return Response(content=content, media_type=http_headers["Content-Type"])
@app.get("/users/{user_id}")
async def get_user(
request: Request,
user_id: str,
):
request.app.state.users_events_counter.inc({"path": request.scope["path"]})
return Response(f"{user_id}")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app)
Examples in the ``examples/frameworks`` directory show how aioprometheus can
be used within various web application frameworks.
Other examples in the ``examples/frameworks`` directory show how aioprometheus
can be used within various web application frameworks.

The next example shows how to use the Service HTTP endpoint to provide a
dedicated metrics endpoint for other applications such as long running
Expand Down Expand Up @@ -230,3 +244,19 @@ License
was released under the MIT license. `aioprometheus` continues to use the MIT
license and contains a copy of the original MIT license from the
`prometheus-python` project as instructed by the original license.


.. |ci status| image:: https://github.com/claws/aioprometheus/workflows/CI%20Pipeline/badge.svg?branch=master
:target: https://github.com/claws/aioprometheus/actions?query=branch%3Amaster

.. |pypi| image:: https://img.shields.io/pypi/v/aioprometheus.svg
:target: https://pypi.python.org/pypi/aioprometheus

.. |python| image:: https://img.shields.io/pypi/pyversions/aioprometheus.svg
:target: https://pypi.python.org/pypi/aioprometheus/

.. |docs| image:: https://readthedocs.org/projects/aioprometheus/badge/?version=latest
:target: https://aioprometheus.readthedocs.io/en/latest

.. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg
:target: https://github.com/claws/aioprometheus/License/LICENSE
55 changes: 29 additions & 26 deletions docs/index.rst
@@ -1,18 +1,8 @@
.. image:: https://github.com/claws/aioprometheus/workflows/Python%20Package%20Workflow/badge.svg?branch=master
:target: https://github.com/claws/aioprometheus/actions?query=branch%3Amaster

.. image:: https://img.shields.io/pypi/v/aioprometheus.svg
:target: https://pypi.python.org/pypi/aioprometheus

.. image:: https://readthedocs.org/projects/aioprometheus/badge/?version=latest
:target: https://aioprometheus.readthedocs.io/en/latest

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black

aioprometheus
=============

|ci status| |pypi| |python| |docs| |license|

.. toctree::
:maxdepth: 1
:hidden:
Expand All @@ -36,23 +26,36 @@ use this package.
License
-------

`aioprometheus` is released under the MIT license.

`aioprometheus` originates from the (now deprecated)
`prometheus python <https://github.com/slok/prometheus-python>`_ package which
was released under the MIT license. `aioprometheus` continues to use the MIT
license and contains a copy of the orignal MIT license from the
`prometheus-python` project as instructed by the original license.
`aioprometheus` is released under the MIT license. It is based upon the (now
deprecated) `prometheus python <https://github.com/slok/prometheus-python>`_
package which was released under the MIT license. A copy of the original MIT
license from the `prometheus-python` project is included as instructed by the
original license.


Origins
-------

`aioprometheus` originates from the (now deprecated)
`prometheus python <https://github.com/slok/prometheus-python>`_ package.
Many thanks to `slok <https://github.com/slok>`_ for developing
prometheus-python. I have taken the original work and modified it to meet
the needs of my asyncio-based applications, added the histogram metric,
integrated support for binary format, updated and extended tests, added docs,
decorators, etc.
`aioprometheus` originates from the (now deprecated) `prometheus python`
package. Many thanks to `slok <https://github.com/slok>`_ for developing
`prometheus-python`.

The original work has been modified and updated it to meet the needs of asyncio
applications by adding the histogram metric, binary format support, docs,
decorators, ASGI middleware, etc.


.. |ci status| image:: https://github.com/claws/aioprometheus/workflows/CI%20Pipeline/badge.svg?branch=master
:target: https://github.com/claws/aioprometheus/actions?query=branch%3Amaster

.. |pypi| image:: https://img.shields.io/pypi/v/aioprometheus.svg
:target: https://pypi.python.org/pypi/aioprometheus

.. |python| image:: https://img.shields.io/pypi/pyversions/aioprometheus.svg
:target: https://pypi.python.org/pypi/aioprometheus/

.. |docs| image:: https://readthedocs.org/projects/aioprometheus/badge/?version=latest
:target: https://aioprometheus.readthedocs.io/en/latest

.. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg
:target: https://github.com/claws/aioprometheus/License/LICENSE

0 comments on commit 3f1fdf8

Please sign in to comment.