CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-prometheus

Django middlewares to monitor your application with Prometheus.io

Pending
Overview
Eval results
Files

metrics-export.mddocs/

Metrics Export

Export Prometheus metrics through Django views or standalone HTTP servers, with support for multiprocess environments and flexible deployment configurations.

Capabilities

Django View Export

Export Prometheus metrics as a standard Django HTTP response, integrating with Django's URL routing and middleware stack.

def ExportToDjangoView(request):
    """
    Exports /metrics as a Django view.
    
    You can use django_prometheus.urls to map /metrics to this view.
    Handles multiprocess environments automatically.
    
    Parameters:
    - request: Django HttpRequest object
    
    Returns:
    HttpResponse with Prometheus metrics data and appropriate content type
    """

Standalone HTTP Server Export

Run dedicated HTTP servers for metrics export, independent of Django's application server.

def SetupPrometheusEndpointOnPort(port: int, addr: str = ""):
    """
    Exports Prometheus metrics on HTTPServer running in its own thread.
    
    The server runs on the given port and listens on all interfaces by default.
    This HTTPServer is fully independent of Django and its stack, providing
    metrics even if Django becomes unresponsive.
    
    Cannot be used when Django's autoreloader is active (development mode).
    
    Parameters:
    - port: int, port number to serve metrics on
    - addr: str, address to bind to (default: "" for all interfaces)
    
    Raises:
    AssertionError: When called with Django autoreloader active
    """

def SetupPrometheusEndpointOnPortRange(port_range, addr: str = ""):
    """
    Like SetupPrometheusEndpointOnPort, but tries several ports.
    
    Useful for WSGI applications with multiple processes where each
    worker needs its own metrics port for Prometheus scraping.
    
    Parameters:
    - port_range: iterable, ports to try (e.g., range(8001, 8010))
    - addr: str, address to bind to (default: "" for all interfaces)
    
    Returns:
    int or None: Port number chosen, or None if no port available
    
    Raises:
    AssertionError: When called with Django autoreloader active
    """

def SetupPrometheusExportsFromConfig():
    """
    Exports metrics based on Django settings configuration.
    
    Automatically called by DjangoPrometheusConfig.ready().
    Reads PROMETHEUS_METRICS_EXPORT_* settings and configures appropriate export method.
    """

HTTP Server Thread Management

class PrometheusEndpointServer(threading.Thread):
    """
    A thread class that holds an HTTP server and makes it serve_forever().
    Used internally by port-based export functions.
    """
    
    def __init__(self, httpd, *args, **kwargs):
        """
        Initialize server thread.
        
        Parameters:
        - httpd: HTTPServer instance to run
        - *args, **kwargs: Arguments passed to Thread.__init__
        """
    
    def run(self):
        """Run the HTTP server forever in this thread."""

Configuration

Django Settings

Configure metrics export through Django settings:

# settings.py

# Export metrics on a dedicated port (standalone HTTP server)
PROMETHEUS_METRICS_EXPORT_PORT = 8001

# Or export on a range of ports (for multiprocess deployments)
PROMETHEUS_METRICS_EXPORT_PORT_RANGE = range(8001, 8010)

# Bind to specific address (default: all interfaces)
PROMETHEUS_METRICS_EXPORT_ADDRESS = "127.0.0.1"

# Custom metric namespace
PROMETHEUS_METRIC_NAMESPACE = "myapp"

# Custom latency buckets
PROMETHEUS_LATENCY_BUCKETS = (0.1, 0.5, 1.0, 2.5, 5.0, 10.0, float('inf'))

URL Configuration

Include metrics endpoint in Django URL configuration:

# urls.py
from django.urls import path, include

urlpatterns = [
    # Include django-prometheus URLs (provides /metrics endpoint)
    path('', include('django_prometheus.urls')),
    
    # Or manually configure the endpoint
    path('metrics', ExportToDjangoView, name='prometheus-metrics'),
    
    # Your application URLs
    path('admin/', admin.site.urls),
    path('api/', include('myapp.urls')),
]

Usage Examples

Django View Export

# urls.py
from django.urls import path, include

urlpatterns = [
    path('', include('django_prometheus.urls')),  # Adds /metrics endpoint
    # ... other URLs
]

# The /metrics endpoint will be available at http://your-site.com/metrics
# and will return Prometheus-formatted metrics

Standalone Port Export

# settings.py
PROMETHEUS_METRICS_EXPORT_PORT = 8001

# apps.py or any Django app configuration
from django_prometheus.exports import SetupPrometheusEndpointOnPort

class MyAppConfig(AppConfig):
    def ready(self):
        # Metrics will be available on http://localhost:8001/metrics
        # This happens automatically via DjangoPrometheusConfig.ready()
        pass

Multi-Process Export

# settings.py for WSGI deployment with multiple workers
PROMETHEUS_METRICS_EXPORT_PORT_RANGE = range(8001, 8010)

# Each worker process will grab an available port in the range
# Prometheus can scrape all ports: 
# - job_name: 'django-app'
#   static_configs:
#     - targets: ['localhost:8001', 'localhost:8002', 'localhost:8003']

Manual Export Setup

from django_prometheus.exports import SetupPrometheusEndpointOnPort, SetupPrometheusEndpointOnPortRange

# Manual port setup
def setup_metrics():
    try:
        SetupPrometheusEndpointOnPort(9090)
        print("Metrics available on http://localhost:9090/metrics")
    except AssertionError as e:
        print(f"Cannot setup metrics server: {e}")

# Multi-port setup
def setup_metrics_multiprocess():
    port = SetupPrometheusEndpointOnPortRange(range(9090, 9100))
    if port:
        print(f"Metrics available on http://localhost:{port}/metrics")
    else:
        print("No available ports for metrics server")

Custom View Export

from django.http import HttpResponse
from django_prometheus.exports import ExportToDjangoView
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def custom_metrics_view(request):
    """Custom metrics endpoint with additional logic."""
    if not request.user.is_authenticated:
        return HttpResponse("Unauthorized", status=401)
    
    # Add custom logic before metrics export
    # ... logging, authentication, etc.
    
    return ExportToDjangoView(request)

# urls.py
urlpatterns = [
    path('admin/metrics', custom_metrics_view, name='admin-metrics'),
]

Multiprocess Support

Environment Variables

Django-prometheus automatically detects multiprocess environments:

import os

# Set by gunicorn, uWSGI, or other WSGI servers
os.environ['PROMETHEUS_MULTIPROC_DIR'] = '/tmp/prometheus_metrics'

# Alternative environment variable
os.environ['prometheus_multiproc_dir'] = '/tmp/prometheus_metrics'

Multiprocess Configuration

# When multiprocess directory is set, metrics are aggregated across processes
from prometheus_client import multiprocess, CollectorRegistry

# This happens automatically in ExportToDjangoView
if "PROMETHEUS_MULTIPROC_DIR" in os.environ:
    registry = CollectorRegistry()
    multiprocess.MultiProcessCollector(registry)
else:
    registry = prometheus_client.REGISTRY

Deployment Patterns

Single Process (Development)

# settings.py
PROMETHEUS_METRICS_EXPORT_PORT = 8001

# Metrics available at http://localhost:8001/metrics
# Also available through Django at http://localhost:8000/metrics

Gunicorn Deployment

# Start gunicorn with multiple workers
gunicorn --workers 4 --bind 0.0.0.0:8000 myproject.wsgi

# With multiprocess metrics
export PROMETHEUS_MULTIPROC_DIR=/tmp/prometheus_metrics
mkdir -p $PROMETHEUS_MULTIPROC_DIR
gunicorn --workers 4 --bind 0.0.0.0:8000 myproject.wsgi

Docker Deployment

# Dockerfile
EXPOSE 8000 8001
ENV PROMETHEUS_METRICS_EXPORT_PORT=8001

# Metrics will be available on port 8001
# Application on port 8000

Kubernetes Deployment

# deployment.yaml
spec:
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8001"
        prometheus.io/path: "/metrics"
    spec:
      containers:
      - name: django-app
        ports:
        - containerPort: 8000  # Django app
        - containerPort: 8001  # Metrics
        env:
        - name: PROMETHEUS_METRICS_EXPORT_PORT
          value: "8001"

Security Considerations

  • Metrics may contain sensitive information (response times, error rates, etc.)
  • Consider authentication for metrics endpoints in production
  • Separate metrics ports can be firewalled differently than application ports
  • Monitor access to metrics endpoints in security logs

Troubleshooting

Common Issues

# Django autoreloader conflict
AssertionError: The thread-based exporter can't be safely used when django's autoreloader is active

# Solution: Use --noreload in development or use URL exporter
python manage.py runserver --noreload

# Or use URL-based export instead of port-based export

Port Conflicts

# When port is already in use
OSError: [Errno 48] Address already in use

# Solution: Use port range instead of fixed port
PROMETHEUS_METRICS_EXPORT_PORT_RANGE = range(8001, 8010)

Install with Tessl CLI

npx tessl i tessl/pypi-django-prometheus

docs

cache-monitoring.md

database-monitoring.md

http-monitoring.md

index.md

metrics-export.md

migration-monitoring.md

model-monitoring.md

testing-utilities.md

tile.json