Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ workflows:
- "3.11"
- "3.12"
- "3.13"
- "3.14"
- test_nooptionals:
matrix:
parameters:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
name: "Build debian package"
runs-on: ubuntu-latest
container:
image: "debian:latest"
image: "debian:testing"
steps:
- name: Install dependencies
run: |
Expand Down
2 changes: 2 additions & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Build-Depends: debhelper (>= 11),
Build-Depends-Indep: dh-python,
pybuild-plugin-pyproject,
python3-all,
python3-aiohttp,
python3-asgiref,
python3-decorator (>= 4.0.10),
python3-pytest,
python3-pytest-benchmark,
Expand Down
4 changes: 2 additions & 2 deletions debian/patches/0002-Update-pyproject.toml.patch
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Index: python3-prometheus-client/pyproject.toml
--- python3-prometheus-client.orig/pyproject.toml
+++ python3-prometheus-client/pyproject.toml
@@ -7,11 +7,7 @@ name = "prometheus_client"
version = "0.23.1"
version = "0.24.1"
description = "Python client for the Prometheus monitoring system."
readme = "README.md"
-license = "Apache-2.0 AND BSD-2-Clause"
Expand All @@ -15,7 +15,7 @@ Index: python3-prometheus-client/pyproject.toml
requires-python = ">=3.9"
authors = [
{ name = "The Prometheus Authors", email = "[email protected]" },
@@ -50,3 +46,17 @@ Documentation = "https://prometheus.gith
@@ -57,3 +53,17 @@ Documentation = "https://prometheus.gith

[tool.setuptools.package-data]
prometheus_client = ['py.typed']
Expand Down
23 changes: 23 additions & 0 deletions docs/content/exporting/http/aiohttp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: AIOHTTP
weight: 6
---

To use Prometheus with a [AIOHTTP server](https://docs.aiohttp.org/en/stable/web.html),
there is `make_aiohttp_handler` which creates a handler.

```python
from aiohttp import web
from prometheus_client.aiohttp import make_aiohttp_handler

app = web.Application()
app.router.add_get("/metrics", make_aiohttp_handler())
```

By default, this handler will instruct AIOHTTP to automatically compress the
response if requested by the client. This behaviour can be disabled by passing
`disable_compression=True` when creating the app, like this:

```python
app.router.add_get("/metrics", make_aiohttp_handler(disable_compression=True))
```
47 changes: 47 additions & 0 deletions docs/content/exporting/http/django.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: Django
weight: 5
---

To use Prometheus with [Django](https://www.djangoproject.com/) you can use the provided view class
to add a metrics endpoint to your app.

```python
# urls.py

from django.urls import path
from prometheus_client.django import PrometheusDjangoView

urlpatterns = [
# ... any other urls that you want
path("metrics/", PrometheusDjangoView.as_view(), name="prometheus-metrics"),
# ... still more urls
]
```

By default, Multiprocessing support is activated if environment variable `PROMETHEUS_MULTIPROC_DIR` is set.
You can override this through the view arguments:

```python
from django.conf import settings

urlpatterns = [
path(
"metrics/",
PrometheusDjangoView.as_view(
multiprocess_mode=settings.YOUR_SETTING # or any boolean value
),
name="prometheus-metrics",
),
]
```

Full multiprocessing instructions are provided [here]({{< ref "/multiprocess" >}}).

# django-prometheus

The included `PrometheusDjangoView` is useful if you want to define your own metrics from scratch.

An external package called [django-prometheus](https://github.com/django-commons/django-prometheus/)
can be used instead if you want to get a bunch of ready-made monitoring metrics for your Django application
and easily benefit from utilities such as models monitoring.
14 changes: 14 additions & 0 deletions docs/content/exporting/pushgateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ g.set_to_current_time()
push_to_gateway('localhost:9091', job='batchA', registry=registry, handler=my_auth_handler)
```

# Compressing data before sending to pushgateway
Pushgateway (version >= 1.5.0) supports gzip and snappy compression (v > 1.6.0). This can help in network constrained environments.
To compress a push request, set the `compression` argument to `'gzip'` or `'snappy'`:
```python
push_to_gateway(
'localhost:9091',
job='batchA',
registry=registry,
handler=my_auth_handler,
compression='gzip',
)
```
Snappy compression requires the optional [`python-snappy`](https://github.com/andrix/python-snappy) package.

TLS Auth is also supported when using the push gateway with a special handler.

```python
Expand Down
2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[mypy]
exclude = prometheus_client/decorator.py|prometheus_client/twisted|tests/test_twisted.py
exclude = prometheus_client/decorator.py|prometheus_client/twisted|tests/test_twisted.py|prometheus_client/django|tests/test_django.py
implicit_reexport = False
disallow_incomplete_defs = True

Expand Down
5 changes: 5 additions & 0 deletions prometheus_client/aiohttp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .exposition import make_aiohttp_handler

__all__ = [
"make_aiohttp_handler",
]
39 changes: 39 additions & 0 deletions prometheus_client/aiohttp/exposition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from __future__ import annotations

from aiohttp import hdrs, web
from aiohttp.typedefs import Handler

from ..exposition import _bake_output
from ..registry import Collector, REGISTRY


def make_aiohttp_handler(
registry: Collector = REGISTRY,
disable_compression: bool = False,
) -> Handler:
"""Create a aiohttp handler which serves the metrics from a registry."""

async def prometheus_handler(request: web.Request) -> web.Response:
# Prepare parameters
params = {key: request.query.getall(key) for key in request.query.keys()}
accept_header = ",".join(request.headers.getall(hdrs.ACCEPT, []))
accept_encoding_header = ""
# Bake output
status, headers, output = _bake_output(
registry,
accept_header,
accept_encoding_header,
params,
# use AIOHTTP's compression
disable_compression=True,
)
response = web.Response(
status=int(status.split(" ")[0]),
headers=headers,
body=output,
)
if not disable_compression:
response.enable_compression()
return response

return prometheus_handler
4 changes: 2 additions & 2 deletions prometheus_client/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from urllib.parse import parse_qs

from .exposition import _bake_output
from .registry import CollectorRegistry, REGISTRY
from .registry import Collector, REGISTRY


def make_asgi_app(registry: CollectorRegistry = REGISTRY, disable_compression: bool = False) -> Callable:
def make_asgi_app(registry: Collector = REGISTRY, disable_compression: bool = False) -> Callable:
"""Create a ASGI app which serves the metrics from a registry."""

async def prometheus_app(scope, receive, send):
Expand Down
4 changes: 2 additions & 2 deletions prometheus_client/bridge/graphite.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from timeit import default_timer
from typing import Callable, Tuple

from ..registry import CollectorRegistry, REGISTRY
from ..registry import Collector, REGISTRY

# Roughly, have to keep to what works as a file name.
# We also remove periods, so labels can be distinguished.
Expand Down Expand Up @@ -48,7 +48,7 @@ def run(self):
class GraphiteBridge:
def __init__(self,
address: Tuple[str, int],
registry: CollectorRegistry = REGISTRY,
registry: Collector = REGISTRY,
timeout_seconds: float = 30,
_timer: Callable[[], float] = time.time,
tags: bool = False,
Expand Down
5 changes: 5 additions & 0 deletions prometheus_client/django/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .exposition import PrometheusDjangoView

__all__ = [
"PrometheusDjangoView",
]
43 changes: 43 additions & 0 deletions prometheus_client/django/exposition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import os

from django.http import HttpResponse
from django.views import View

import prometheus_client
from prometheus_client import multiprocess
from prometheus_client.exposition import _bake_output


class PrometheusDjangoView(View):
multiprocess_mode: bool = "PROMETHEUS_MULTIPROC_DIR" in os.environ or "prometheus_multiproc_dir" in os.environ
registry: prometheus_client.CollectorRegistry = None

def get(self, request, *args, **kwargs):
if self.registry is None:
if self.multiprocess_mode:
self.registry = prometheus_client.CollectorRegistry()
multiprocess.MultiProcessCollector(self.registry)
else:
self.registry = prometheus_client.REGISTRY
accept_header = request.headers.get("Accept")
accept_encoding_header = request.headers.get("Accept-Encoding")
# Bake output
status, headers, output = _bake_output(
registry=self.registry,
accept_header=accept_header,
accept_encoding_header=accept_encoding_header,
params=request.GET,
disable_compression=False,
)
status = int(status.split(" ")[0])
return HttpResponse(
output,
status=status,
headers=headers,
)

def options(self, request, *args, **kwargs):
return HttpResponse(
status=200,
headers={"Allow": "OPTIONS,GET"},
)
Loading