Skip to main content

Django middleware for capturing and streaming HTTP request metrics via WebSocket

Project description

Cerberus Django

PyPI version Python Versions Django Versions License: MIT

A Django middleware for capturing and streaming HTTP request metrics to a backend analytics server via WebSocket. Designed for high-performance, non-blocking operation in both WSGI and ASGI environments.

Features

  • Non-blocking: Events are queued and sent asynchronously via a background thread
  • WSGI & ASGI Compatible: Works with both synchronous and asynchronous Django deployments
  • Privacy-First: Built-in HMAC-SHA256 hashing for PII (IP addresses) before transmission
  • Custom Metrics: Attach application-specific metrics to any request
  • Automatic Reconnection: WebSocket client handles connection failures gracefully
  • Zero Configuration Required: Sensible defaults with optional customization

Installation

pip install cerberus-django

Quick Start

1. Add to Django Settings

# settings.py

INSTALLED_APPS = [
    # ... your apps
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # ... other middleware
    'cerberus_django.CerberusMiddleware',  # Add Cerberus
]

# Cerberus Configuration
CERBERUS_CONFIG = {
    'ws_url': 'wss://your-analytics-server.com/ws/events',
    'token': 'your-api-key',
    'client_id': 'your-client-id',
}

2. That's It!

Cerberus will now capture metrics for every HTTP request and send them to your analytics backend.

Configuration

All configuration is done via the CERBERUS_CONFIG dictionary in your Django settings:

Key Required Description
ws_url Yes WebSocket URL for the analytics backend
token Yes API key for authentication
client_id Yes Unique identifier for your application
backend_url No HTTP URL to auto-fetch the HMAC secret key
secret_key No HMAC secret key for PII hashing (auto-fetched if backend_url is set)

Example Configurations

Basic (no PII hashing):

CERBERUS_CONFIG = {
    'ws_url': 'wss://analytics.example.com/ws/events',
    'token': 'sk-your-api-key',
    'client_id': 'my-django-app',
}

With automatic secret key fetching:

CERBERUS_CONFIG = {
    'ws_url': 'wss://analytics.example.com/ws/events',
    'token': 'sk-your-api-key',
    'client_id': 'my-django-app',
    'backend_url': 'https://analytics.example.com',  # Will fetch secret from /api/secret-key
}

With manual secret key:

CERBERUS_CONFIG = {
    'ws_url': 'wss://analytics.example.com/ws/events',
    'token': 'sk-your-api-key',
    'client_id': 'my-django-app',
    'secret_key': 'your-hmac-secret-key',  # For consistent PII hashing
}

Custom Metrics

Attach custom metrics to any request by adding them to the response:

from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def my_endpoint(request):
    # Your business logic
    items = process_items()

    response = Response({'items': items})

    # Add custom metrics (will be included in the event)
    response.data['_cerberus_metrics'] = {
        'items_processed': len(items),
        'cache_hit': True,
        'processing_time_ms': 42,
    }

    return response

The _cerberus_metrics key is automatically extracted from the response and included in the event payload. It will not be sent to the client.

Event Payload

Each event sent to your analytics backend includes:

{
    "api_key": "your-api-key",
    "client_id": "your-client-id",
    "token": "your-api-key",
    "source_ip": "hashed-ip-address",
    "endpoint": "/api/users/",
    "scheme": true,
    "method": "GET",
    "custom_data": {
        "items_processed": 10,
        "cache_hit": true
    }
}

Privacy & Security

PII Hashing

When a secret_key is configured, source IP addresses are hashed using HMAC-SHA256 before transmission:

  • Consistent: Same IP always produces the same hash (enabling analytics)
  • Irreversible: Original IP cannot be recovered from the hash
  • Secure: Uses cryptographically strong HMAC-SHA256

What's Captured

Field Description Privacy
source_ip Client IP address Hashed if secret_key configured
endpoint Request path Sent as-is
method HTTP method (GET, POST, etc.) Sent as-is
scheme Whether HTTPS was used Sent as-is
custom_data Your custom metrics Sent as-is

What's NOT Captured

  • Request/response bodies
  • HTTP headers
  • Query parameters
  • Cookies or session data
  • Authentication tokens

Debug Mode

Enable debug logging to troubleshoot issues:

export CERBERUS_DEBUG=true

Or in your Django settings:

import os
os.environ['CERBERUS_DEBUG'] = 'true'

This will log:

  • Middleware initialization
  • WebSocket connection attempts
  • Events being queued and sent
  • Any errors encountered

Architecture

┌─────────────────────────┐     ┌──────────────────────────────┐
│   Django Request        │     │   Background Thread          │
│   (WSGI or ASGI)        │     │   (Daemon)                   │
├─────────────────────────┤     ├──────────────────────────────┤
│ CerberusMiddleware      │     │  Event Loop                  │
│   └── queue.put(event)  │────▶│    └── WebSocket.send()     │
└─────────────────────────┘     └──────────────────────────────┘
         │                                    │
         │  Thread-safe Queue                 │  Async WebSocket
         └────────────────────────────────────┘
  • Middleware: Runs synchronously in the request/response cycle
  • Queue: Thread-safe queue.Queue for passing events
  • Background Thread: Daemon thread with its own event loop for async WebSocket communication

This architecture ensures:

  • No blocking of HTTP requests
  • No event loop conflicts in WSGI mode
  • Automatic cleanup when the process exits (daemon thread)

Requirements

  • Python 3.9+
  • Django 4.0+
  • websockets 12.0+
  • requests 2.28+

Development

# Clone the repository
git clone https://github.com/gpotrock/cerberus.git
cd cerberus

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black src/
ruff check src/ --fix

# Type checking
mypy src/

License

MIT License - see LICENSE for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cerberus_django-0.1.4.tar.gz (10.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cerberus_django-0.1.4-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file cerberus_django-0.1.4.tar.gz.

File metadata

  • Download URL: cerberus_django-0.1.4.tar.gz
  • Upload date:
  • Size: 10.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.13

File hashes

Hashes for cerberus_django-0.1.4.tar.gz
Algorithm Hash digest
SHA256 ad06ee4fb7d8afffc7ba25e4d49e722af3df630975e92667d89e27dd561bd2fb
MD5 a0505092f21f253cec6fc72af75c5044
BLAKE2b-256 1de1a067181ce6ed7a8f6faee5aeb5095345589d81697ef35d1871df2b9068e3

See more details on using hashes here.

File details

Details for the file cerberus_django-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for cerberus_django-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 64da8a60a39cd49e830a14044cb55115449058294fa0d42c9c205ca81886ab8a
MD5 d1a2934a6c72711d6df7ff8b5f00ae07
BLAKE2b-256 a9155e1bb47fcf0b1ff960be6ae455a9451f9251f9f57e6e1a8935885de42013

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page