diff --git a/connect/api/prometheus/view.py b/connect/api/prometheus/view.py new file mode 100644 index 00000000..0f9fa12a --- /dev/null +++ b/connect/api/prometheus/view.py @@ -0,0 +1,15 @@ +import os + +from django.http import HttpResponseForbidden +from django_prometheus.exports import ExportToDjangoView + + +def metrics_view(request): + auth_token = request.headers.get("Authorization") + prometheus_auth_token = os.environ.get("PROMETHEUS_AUTH_TOKEN") + + expected_token = f"Bearer {prometheus_auth_token}" + if not auth_token or auth_token != expected_token: + return HttpResponseForbidden("Access denied") + + return ExportToDjangoView(request) diff --git a/connect/settings.py b/connect/settings.py index 76391d27..5e07f2d2 100644 --- a/connect/settings.py +++ b/connect/settings.py @@ -153,9 +153,11 @@ "corsheaders", "django_grpc_framework", "stripe", + "django_prometheus", ] MIDDLEWARE = [ + "django_prometheus.middleware.PrometheusBeforeMiddleware", "elasticapm.contrib.django.middleware.TracingMiddleware", "elasticapm.contrib.django.middleware.Catch404Middleware", "django.middleware.security.SecurityMiddleware", @@ -168,6 +170,7 @@ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", + "django_prometheus.middleware.PrometheusAfterMiddleware", ] ROOT_URLCONF = "connect.urls" diff --git a/connect/urls.py b/connect/urls.py index c4bfa4ef..7682eb06 100644 --- a/connect/urls.py +++ b/connect/urls.py @@ -30,6 +30,7 @@ ) from connect.billing.views import StripeHandler from connect.api.v2 import routers as api_v2_urls +from connect.api.prometheus.view import metrics_view api_v2_urls = [path("", include(api_v2_urls))] @@ -51,6 +52,7 @@ path("v1/", include(rookly_api_v1_urls)), path("v2/", include(api_v2_urls)), url(r"^handlers/stripe/$", StripeHandler.as_view(), name="handlers.stripe_handler"), + path("api/prometheus/metrics", metrics_view, name="metrics_view"), ] urlpatterns += staticfiles_urlpatterns() diff --git a/poetry.lock b/poetry.lock index 6cf9551f..df7381c6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "amqp" @@ -737,6 +737,20 @@ files = [ [package.dependencies] Django = ">=2.2" +[[package]] +name = "django-prometheus" +version = "2.3.1" +description = "Django middlewares to monitor your application with Prometheus.io." +optional = false +python-versions = "*" +files = [ + {file = "django-prometheus-2.3.1.tar.gz", hash = "sha256:f9c8b6c780c9419ea01043c63a437d79db2c33353451347894408184ad9c3e1e"}, + {file = "django_prometheus-2.3.1-py2.py3-none-any.whl", hash = "sha256:cf9b26f7ba2e4568f08f8f91480a2882023f5908579681bcf06a4d2465f12168"}, +] + +[package.dependencies] +prometheus-client = ">=0.7" + [[package]] name = "django-redis" version = "5.4.0" @@ -1817,6 +1831,20 @@ pyyaml = ">=5.1" toml = "*" virtualenv = ">=20.0.8" +[[package]] +name = "prometheus-client" +version = "0.21.1" +description = "Python client for the Prometheus monitoring system." +optional = false +python-versions = ">=3.8" +files = [ + {file = "prometheus_client-0.21.1-py3-none-any.whl", hash = "sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301"}, + {file = "prometheus_client-0.21.1.tar.gz", hash = "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb"}, +] + +[package.extras] +twisted = ["twisted"] + [[package]] name = "prompt-toolkit" version = "3.0.43" @@ -2205,7 +2233,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -2875,4 +2902,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "~=3.8" -content-hash = "17d95dd718debf8661247192c011cecac166df99da7870dd88fcf8365a113283" +content-hash = "96f90ab2d271bf5b933b72b90cf69a6bfe508f8a9ab4744a21c5f42f290395f3" diff --git a/pyproject.toml b/pyproject.toml index 54798f3a..447fa5d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ gevent = "22.10.2" setuptools = "*" factory-boy = "^3.3.0" pyjwt = "^2.9.0" +django-prometheus = "^2.3.1" [tool.poetry.dev-dependencies] flake8 = "~=3.9.2"