{"id":20285407,"url":"https://github.com/mramshaw/prometheus_django","last_synced_at":"2025-04-11T08:39:02.236Z","repository":{"id":48962601,"uuid":"124126661","full_name":"mramshaw/Prometheus_Django","owner":"mramshaw","description":"Instrument a Python WebApp","archived":false,"fork":false,"pushed_at":"2024-09-04T20:56:37.000Z","size":151,"stargazers_count":5,"open_issues_count":9,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-25T06:11:16.957Z","etag":null,"topics":["django","django-prometheus","postgres","postgresql","prometheus","psycopg2","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mramshaw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-06T19:16:34.000Z","updated_at":"2023-05-22T05:29:19.000Z","dependencies_parsed_at":"2024-09-06T05:36:04.891Z","dependency_job_id":"a186425d-6540-48fd-b911-73b27895e8ba","html_url":"https://github.com/mramshaw/Prometheus_Django","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPrometheus_Django","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPrometheus_Django/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPrometheus_Django/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPrometheus_Django/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mramshaw","download_url":"https://codeload.github.com/mramshaw/Prometheus_Django/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248362186,"owners_count":21091065,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","django-prometheus","postgres","postgresql","prometheus","psycopg2","python"],"created_at":"2024-11-14T14:26:30.379Z","updated_at":"2025-04-11T08:39:02.215Z","avatar_url":"https://github.com/mramshaw.png","language":"Python","readme":"# Prometheus Django\n\n[![Known Vulnerabilities](https://snyk.io/test/github/mramshaw/Prometheus_Django/badge.svg?style=plastic\u0026targetFile=requirements.txt)](https://snyk.io/test/github/mramshaw/Prometheus_Django?style=plastic\u0026targetFile=requirements.txt)\n\nInstrumenting a Django server with [Prometheus](https://prometheus.io/).\n\n[Amazon customers seeking distributed tracing should probably have a look at [X-Ray](https://aws.amazon.com/xray/) first.]\n\n## Motivation\n\nPrometheus is a monitoring and visualization tool that can easily be used to instrument Kubernetes.\n\nThis follows on from my [Cloud Django](https://github.com/mramshaw/Cloud_Django) exercise.\n\n## Prometheus Installation\n\n1. Download the [latest stable release for your platform](https://prometheus.io/download/).\n\n    [At the time of writing this is `prometheus-2.1.0.linux-amd64.tar.gz`]\n\n2. Note the checksum.\n\n    [At the time of writing this is `f181f619c9a8e0750c1ac940eb00a0881cc50386d896f06f159e9a5b68db60a0`]\n\n3. Verify the checksum (SHA 256 Checksum):\n\n    $ sha256sum prometheus-2.1.0.linux-amd64.tar.gz\n\n4. Uncompress it (using `tar` or `ark` or whatever floats your boat).\n\nThere is also a [Docker image](https://hub.docker.com/r/prom/prometheus/):\n\n    prom/prometheus:v2.1.0\n\n## Install Django dependencies\n\nAs usual, I do not recommend global installs:\n\n    $ pip install --user -r requirements.txt\n\n[Replace `pip` with `pip3` for Python3.]\n\n## Instrument Django\n\n1. Change INSTALLED_APPS and MIDDLEWARE in `polls/polls/settings.py` as follows:\n\n    ```\n    $ diff -uw ../Cloud_Django/polls/polls/settings.py polls/polls/settings.py\n    --- ../Cloud_Django/polls/polls/settings.py\t2018-03-05 19:44:19.563484080 -0800\n    +++ polls/polls/settings.py\t2018-03-06 13:52:20.469803146 -0800\n    @@ -39,9 +39,11 @@\n         'django.contrib.sessions',\n         'django.contrib.messages',\n         'django.contrib.staticfiles',\n    +    'django_prometheus',\n     ]\n     \n     MIDDLEWARE = [\n    +    'django_prometheus.middleware.PrometheusBeforeMiddleware',\n         'django.middleware.security.SecurityMiddleware',\n         'django.contrib.sessions.middleware.SessionMiddleware',\n         'django.middleware.common.CommonMiddleware',\n    @@ -49,6 +51,7 @@INSTALLED_APPS\n         'django.contrib.auth.middleware.AuthenticationMiddleware',\n         'django.contrib.messages.middleware.MessageMiddleware',\n         'django.middleware.clickjacking.XFrameOptionsMiddleware',\n    +    'django_prometheus.middleware.PrometheusAfterMiddleware',\n     ]\n     \n     ROOT_URLCONF = 'polls.urls'\n    $\n    ```\n\n    Note that `PrometheusBeforeMiddleware` and `PrometheusAfterMiddleware` must sandwich the middleware exactly as shown.\n\n2. Change `polls/polls/urls.py` as follows:\n\n    ```\n    $ diff -uw ../Cloud_Django/polls/polls/urls.py polls/polls/urls.py\n    --- ../Cloud_Django/polls/polls/urls.py\t2018-02-11 14:45:15.909210000 -0800\n    +++ polls/polls/urls.py\t2018-03-06 13:40:28.043185705 -0800\n    @@ -20,4 +20,5 @@\n     urlpatterns = [\n         url(r'^polls/', include('polls_app.urls')),\n         url(r'^admin/', admin.site.urls),\n    +    url('', include('django_prometheus.urls')),\n     ]\n    $\n    ```\n\n    [This will create a `/metrics` endpoint for Prometheus to query.]\n\n## Instrument Django backend (Postgres)\n\nChange DATABASES in `polls/polls/urls.py` as follows:\n\n    $ diff -uw ../Cloud_Django/polls/polls/settings.py polls/polls/settings.py\n    --- ../Cloud_Django/polls/polls/settings.py\t2018-03-05 19:44:19.563484080 -0800\n    +++ polls/polls/settings.py\t2018-03-06 13:52:20.469803146 -0800\n    @@ -77,11 +80,11 @@\n     \n     DATABASES = {\n         'default': {\n    -        'ENGINE': 'django.db.backends.postgresql_psycopg2',\n    +        'ENGINE': 'django_prometheus.db.backends.postgresql',\n             'NAME': 'polls',\n             'USER': 'postgres',\n             'PASSWORD': 'postgres',\n             'HOST': '127.0.0.1',\n             'PORT': 5432\n         }\n     }\n    $\n\n## Instrument Django models\n\nChange `polls/polls_app/models.py` as follows:\n\n    $ diff -uw ../Cloud_Django/polls/polls_app/models.py polls/polls_app/models.py\n    --- ../Cloud_Django/polls/polls_app/models.py\t2018-02-11 16:46:40.063097000 -0800\n    +++ polls/polls_app/models.py\t2018-03-06 13:44:18.300155164 -0800\n    @@ -4,9 +4,12 @@\n     from django.db import models\n     from django.utils.encoding import python_2_unicode_compatible\n     \n    +from django_prometheus.models import ExportModelOperationsMixin\n    +\n     \n     @python_2_unicode_compatible\n    -class Question(models.Model):\n    +#class Question(models.Model):\n    +class Question(ExportModelOperationsMixin('question'), models.Model):\n         question_text = models.CharField(max_length=200)\n         pub_date = models.DateTimeField('date published')\n         def __str__(self):\n    @@ -14,7 +17,8 @@\n     \n     \n     @python_2_unicode_compatible\n    -class Choice(models.Model):\n    +#class Choice(models.Model):\n    +class Choice(ExportModelOperationsMixin('choice'), models.Model):\n         question = models.ForeignKey(Question, on_delete=models.CASCADE)\n         choice_text = models.CharField(max_length=200)\n         votes = models.IntegerField(default=0)\n    $\n\nThis will export 6 counters:\n\n    django_model_inserts_total{model=\"question\"}\n    django_model_updates_total{model=\"question\"}\n    django_model_deletes_total{model=\"question\"}\n\n    django_model_inserts_total{model=\"choice\"}\n    django_model_updates_total{model=\"choice\"}\n    django_model_deletes_total{model=\"choice\"}\n\nThese will show in the Prometheus UI grouped as `django_model_inserts_total`, `django_model_updates_total`\nand `django_model_deletes_total`.\n\nDjango migrations are also monitored. Two gauges are exported, `django_migrations_applied_by_connection`\nand `django_migrations_unapplied_by_connection`. It may be desirable to alert if there are unapplied migrations.\n\n## Instrument Django application code\n\nAt this point we could instrument our application code, however we have already managed to get quite a lot\nof visibility into our application with a fairly minimal effort. We can instrument our application code\n___as needed___ from this point forward.\n\n## Launch Prometheus\n\nRun it as follows (as usual, Ctrl-C to kill):\n\n    $ ./prometheus-2.1.0.linux-amd64/prometheus --config.file=prometheus.yaml\n\nThis will launch a web server at:\n\n    0.0.0.0:9090\n\n[It will also create a `data` directory for the prometheus stats.]\n\nAt this point, Prometheus should show our app as `DOWN`:\n\n![App_not_running](images/Django_not_running.png)\n\n## Run our app\n\nLets launch our web app so Prometheus has something to track:\n\n    $ python manage.py runserver\n\nAt this point, Prometheus should show our app as `UP`:\n\n![App_running](images/Django_running.png)\n\nAnd there are 14 migrations unapplied:\n\n![Migrations_unapplied](images/Django_migrations_unapplied.png)\n\nLets run them:\n\n    $ python manage.py migrate\n\n![Migrations_applied](images/Django_migrations_applied.png)\n\nIt's possible to do quite a bit with Prometheus, but for dashboarding [Grafana](http://grafana.com/) may be a better choice.\n\n## Prometheus best practices:\n\nNaming:\n\n    https://prometheus.io/docs/practices/naming/\n\nInstrumentation:\n\n    https://prometheus.io/docs/practices/instrumentation/\n\n## Training\n\nRobust Perception offers a free introduction to Prometheus:\n\n    https://training.robustperception.io/p/introduction-to-prometheus\n\nPrometheus has a sophisticated Query Language. The following articles from Prometheus\nco-creator Julius Volz provide a deep dive into this:\n\n    https://www.digitalocean.com/community/tutorials/how-to-query-prometheus-on-ubuntu-14-04-part-1\n\n    https://www.digitalocean.com/community/tutorials/how-to-query-prometheus-on-ubuntu-14-04-part-2\n\n## Versions\n\n* Prometheus __2.1.0__\n* Django __1.11.10__\n* Docker __17.12.1-ce__ (Client and Server)\n* kubectl (Client: __v1.8.6__, Server: __v1.9.0__)\n* Kubernetes __v1.9.0__\n* minikube __v0.25.0__\n* psycopg2 __2.7.4__\n* Python __2.7.12__\n* PostgreSQL __10.2__\n\n## To Do\n\n* [ ] Learn Prometheus's Query Language\n\n## Credits\n\nBased on:\n\n    https://github.com/korfuri/django-prometheus\n\nAnd:\n\n    https://github.com/prometheus/client_python\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmramshaw%2Fprometheus_django","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmramshaw%2Fprometheus_django","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmramshaw%2Fprometheus_django/lists"}