Monitor Django applications with Prometheus and Grafana for comprehensive performance insights

Intermediate 45 min Apr 16, 2026 17 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up comprehensive Django application monitoring using Prometheus metrics collection and Grafana dashboards. Configure django-prometheus middleware to track request metrics, database queries, and application performance with real-time alerting.

Prerequisites

  • Django application running
  • Python 3.8+
  • 500MB free disk space
  • 2GB RAM
  • sudo privileges

What this solves

Django applications in production need comprehensive monitoring to track performance bottlenecks, database query efficiency, and user experience metrics. This tutorial sets up Prometheus to collect Django application metrics and Grafana to visualize performance data with automated alerting for critical issues.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions of all dependencies.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install system dependencies

Install Python development tools and system packages required for Prometheus and monitoring components.

sudo apt install -y python3-pip python3-venv wget curl gnupg2 software-properties-common
sudo dnf install -y python3-pip python3-virtualenv wget curl gnupg2

Install Prometheus server

Create a prometheus user and download the latest Prometheus release for metrics collection.

sudo useradd --no-create-home --shell /bin/false prometheus
sudo mkdir /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz
tar xf prometheus-2.45.0.linux-amd64.tar.gz
cd prometheus-2.45.0.linux-amd64
sudo cp prometheus promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
sudo cp -r consoles console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus/consoles /etc/prometheus/console_libraries

Configure Prometheus

Create the main Prometheus configuration file with Django application scrape targets.

global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "django_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - localhost:9093

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'django-app'
    static_configs:
      - targets: ['localhost:8000']
    metrics_path: '/metrics'
    scrape_interval: 5s

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml

Create Prometheus systemd service

Set up systemd service file to manage Prometheus as a system service with proper user permissions.

[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
    --config.file /etc/prometheus/prometheus.yml \
    --storage.tsdb.path /var/lib/prometheus/ \
    --web.console.templates=/etc/prometheus/consoles \
    --web.console.libraries=/etc/prometheus/console_libraries \
    --web.listen-address=0.0.0.0:9090 \
    --web.enable-lifecycle

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus

Install Node Exporter

Install Node Exporter to collect system-level metrics alongside Django application metrics.

cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xf node_exporter-1.6.1.linux-amd64.tar.gz
sudo cp node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/node_exporter
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now node-exporter

Install django-prometheus

Install the django-prometheus package to instrument your Django application with Prometheus metrics.

cd /path/to/your/django/project
pip install django-prometheus

Configure Django settings

Add django-prometheus to your Django application settings to enable metrics collection middleware.

# Add to INSTALLED_APPS
INSTALLED_APPS = [
    # ... your other apps
    'django_prometheus',
]

Add prometheus middleware (order matters)

MIDDLEWARE = [ 'django_prometheus.middleware.PrometheusBeforeMiddleware', # ... your other middleware 'django_prometheus.middleware.PrometheusAfterMiddleware', ]

Database monitoring

DATABASES = { 'default': { 'ENGINE': 'django_prometheus.db.backends.postgresql', # or mysql, sqlite3 'NAME': 'your_database_name', 'USER': 'your_db_user', 'PASSWORD': 'your_db_password', 'HOST': 'localhost', 'PORT': '5432', } }

Cache monitoring (if using cache)

CACHES = { 'default': { 'BACKEND': 'django_prometheus.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/1', } }

Add metrics URL pattern

Configure URL routing to expose Prometheus metrics endpoint for scraping.

from django.urls import path, include
from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('metrics/', include('django_prometheus.urls')),
    # ... your other URL patterns
]

Install Grafana

Install Grafana for visualizing Django metrics with comprehensive dashboards and alerting.

wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo rpm --import https://packages.grafana.com/gpg.key
echo '[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key' | sudo tee /etc/yum.repos.d/grafana.repo
sudo dnf install -y grafana

Configure Grafana

Configure Grafana with security settings and enable it as a systemd service.

[server]
http_port = 3000
domain = localhost
root_url = http://localhost:3000

[security]
admin_user = admin
admin_password = secure_password_here
secret_key = your_secret_key_here

[database]
type = sqlite3
path = grafana.db

[session]
provider = file
provider_config = sessions

[analytics]
reporting_enabled = false
check_for_updates = true
sudo systemctl daemon-reload
sudo systemctl enable --now grafana-server

Create Django alerting rules

Configure Prometheus alerting rules for Django application performance monitoring and error detection.

groups:
  - name: django_alerts
    rules:
      - alert: DjangoHighErrorRate
        expr: rate(django_http_requests_total{status=~"4..|5.."}[5m]) > 0.1
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "High error rate in Django application"
          description: "Error rate is {{ $value }} errors per second"

      - alert: DjangoHighResponseTime
        expr: histogram_quantile(0.95, rate(django_http_request_duration_seconds_bucket[5m])) > 2
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High response time in Django application"
          description: "95th percentile response time is {{ $value }} seconds"

      - alert: DjangoHighDatabaseConnections
        expr: django_db_connections > 80
        for: 3m
        labels:
          severity: warning
        annotations:
          summary: "High database connection count"
          description: "Database connections: {{ $value }}"

      - alert: DjangoCacheHitRateLow
        expr: rate(django_cache_get_hits_total[5m]) / rate(django_cache_get_total[5m]) < 0.8
        for: 5m
        labels:
          severity: info
        annotations:
          summary: "Low cache hit rate"
          description: "Cache hit rate is {{ $value | humanizePercentage }}"

      - alert: DjangoHighMemoryUsage
        expr: django_cache_memory_usage > 0.9
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "Django cache memory usage high"
          description: "Memory usage at {{ $value | humanizePercentage }}"

      - alert: DjangoSlowDatabaseQueries
        expr: histogram_quantile(0.95, rate(django_db_query_duration_seconds_bucket[5m])) > 1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Slow database queries detected"
          description: "95th percentile query time: {{ $value }} seconds"
sudo chown prometheus:prometheus /etc/prometheus/django_rules.yml
sudo systemctl reload prometheus

Install Alertmanager

Install Prometheus Alertmanager for handling and routing alerts from Django monitoring rules.

cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.25.0/alertmanager-0.25.0.linux-amd64.tar.gz
tar xf alertmanager-0.25.0.linux-amd64.tar.gz
sudo cp alertmanager-0.25.0.linux-amd64/alertmanager /usr/local/bin/
sudo cp alertmanager-0.25.0.linux-amd64/amtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/alertmanager /usr/local/bin/amtool
sudo mkdir /etc/alertmanager /var/lib/alertmanager
sudo chown prometheus:prometheus /etc/alertmanager /var/lib/alertmanager

Configure Alertmanager

Set up Alertmanager configuration for email notifications when Django application issues are detected.

global:
  smtp_smarthost: 'localhost:587'
  smtp_from: 'alerts@example.com'
  smtp_auth_username: 'your-smtp-username'
  smtp_auth_password: 'your-smtp-password'

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'django-alerts'

receivers:
  - name: 'django-alerts'
    email_configs:
      - to: 'admin@example.com'
        subject: 'Django Alert: {{ .GroupLabels.alertname }}'
        body: |
          {{ range .Alerts }}
          Alert: {{ .Annotations.summary }}
          Description: {{ .Annotations.description }}
          {{ end }}
sudo chown prometheus:prometheus /etc/alertmanager/alertmanager.yml

Create Alertmanager service

Configure systemd service for Alertmanager to handle Django monitoring alerts.

[Unit]
Description=Alertmanager
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/alertmanager \
    --config.file /etc/alertmanager/alertmanager.yml \
    --storage.path /var/lib/alertmanager/ \
    --web.external-url=http://localhost:9093

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager

Create custom Django metrics

Add custom metrics to track specific Django application business logic and performance indicators.

from prometheus_client import Counter, Histogram, Gauge
from django.utils.deprecation import MiddlewareMixin
import time

Custom metrics for Django application

user_registrations = Counter('django_user_registrations_total', 'Total user registrations') active_users = Gauge('django_active_users', 'Currently active users') order_value = Histogram('django_order_value_dollars', 'Order values in dollars') background_tasks = Gauge('django_background_tasks_running', 'Running background tasks') api_requests = Counter('django_api_requests_total', 'API requests', ['method', 'endpoint', 'status']) class CustomMetricsMiddleware(MiddlewareMixin): def process_request(self, request): request.start_time = time.time() return None def process_response(self, request, response): if hasattr(request, 'start_time'): if request.path.startswith('/api/'): api_requests.labels( method=request.method, endpoint=request.path, status=response.status_code ).inc() return response

Configure firewall rules

Open firewall ports for Prometheus, Grafana, and metrics endpoints access.

sudo ufw allow 3000/tcp comment 'Grafana'
sudo ufw allow 9090/tcp comment 'Prometheus'
sudo ufw allow 9093/tcp comment 'Alertmanager'
sudo ufw allow 9100/tcp comment 'Node Exporter'
sudo firewall-cmd --permanent --add-port=3000/tcp --add-port=9090/tcp --add-port=9093/tcp --add-port=9100/tcp
sudo firewall-cmd --reload

Restart Django application

Restart your Django application to load the prometheus middleware and begin collecting metrics.

cd /path/to/your/django/project
python manage.py collectstatic --noinput
python manage.py migrate
sudo systemctl restart your-django-app

Configure Grafana dashboards

Access Grafana web interface

Open your web browser and navigate to Grafana to begin dashboard configuration.

http://your-server-ip:3000

Login with username admin and the password you set in the configuration file.

Add Prometheus data source

Configure Prometheus as a data source in Grafana for Django metrics visualization.

  1. Click "Add data source" or go to Configuration > Data Sources
  2. Select "Prometheus" from the list
  3. Set URL to http://localhost:9090
  4. Set Access to "Server (default)"
  5. Click "Save & Test" to verify connection

Import Django dashboard

Create a comprehensive Django monitoring dashboard with performance metrics and alerts.

{
  "dashboard": {
    "title": "Django Application Monitoring",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [{
          "expr": "rate(django_http_requests_total[5m])",
          "legendFormat": "{{ method }} {{ handler }}"
        }]
      },
      {
        "title": "Response Time (95th percentile)",
        "type": "graph",
        "targets": [{
          "expr": "histogram_quantile(0.95, rate(django_http_request_duration_seconds_bucket[5m]))",
          "legendFormat": "95th percentile"
        }]
      },
      {
        "title": "Error Rate",
        "type": "graph",
        "targets": [{
          "expr": "rate(django_http_requests_total{status=~\"4..|5..\"}[5m])",
          "legendFormat": "Errors"
        }]
      },
      {
        "title": "Database Query Time",
        "type": "graph",
        "targets": [{
          "expr": "histogram_quantile(0.95, rate(django_db_query_duration_seconds_bucket[5m]))",
          "legendFormat": "95th percentile"
        }]
      },
      {
        "title": "Active Database Connections",
        "type": "singlestat",
        "targets": [{
          "expr": "django_db_connections",
          "legendFormat": "Connections"
        }]
      },
      {
        "title": "Cache Hit Rate",
        "type": "graph",
        "targets": [{
          "expr": "rate(django_cache_get_hits_total[5m]) / rate(django_cache_get_total[5m])",
          "legendFormat": "Hit Rate"
        }]
      }
    ]
  }
}

Import this dashboard by going to Dashboards > Import and pasting the JSON configuration.

Verify your setup

# Check service status
sudo systemctl status prometheus grafana-server alertmanager node-exporter

Verify Django metrics endpoint

curl http://localhost:8000/metrics

Check Prometheus targets

curl http://localhost:9090/api/v1/targets

Test Grafana API

curl http://admin:your_password@localhost:3000/api/health
# Check Django metrics collection
python manage.py shell -c "from django_prometheus.models import *; print('Metrics collected successfully')"

Verify database monitoring

grep -i "django_db" /var/log/prometheus.log

Test alerting rules

curl http://localhost:9090/api/v1/rules

Common issues

SymptomCauseFix
Metrics endpoint returns 404URL pattern not configuredAdd path('metrics/', include('django_prometheus.urls')) to urls.py
No database metrics visibleWrong database engineUse django_prometheus.db.backends.postgresql instead of django.db.backends.postgresql
Grafana shows no dataPrometheus data source misconfiguredVerify Prometheus URL is http://localhost:9090 in data source settings
High memory usage from metricsToo many metric labelsReduce cardinality by limiting dynamic labels in custom metrics
Alerts not firingAlertmanager not connectedCheck /etc/prometheus/prometheus.yml alerting section points to port 9093
Permission denied accessing metricsMiddleware not in correct orderPlace PrometheusBeforeMiddleware first and PrometheusAfterMiddleware last

Next steps

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.