Satellite Observability for Django
A modern debugging and observability tool that orbits your Django application without touching it.
- ๐ Request Tracking - Capture HTTP requests with headers, body, and response
- ๐๏ธ SQL Recording - Log queries with N+1 detection and slow query alerts
- ๐ Log Aggregation - Automatically capture Python logging output
- ๐จ Exception Tracking - Full traceback capture for errors
- โฑ๏ธ Performance Metrics - Duration tracking for requests and queries
- ๐ฃ Management Commands - Track
python manage.pyexecutions - ๐ Cache Operations - Monitor hits, misses, sets, deletes
- ๐ต Model Events - ORM create/update/delete auditing
- ๐ฉท HTTP Client - Outgoing API request monitoring
- ๐ง Mail Capture - Track sent emails
- โก Django Signals - Event dispatch monitoring
- โฐ Background Jobs - Celery, Django-Q, RQ, APScheduler monitoring
- ๐ด Redis Operations - Track GET, SET, DEL, and more
- ๐ก๏ธ Gates/Permissions - Authorization check auditing
- ๐ Stats Dashboard - Apdex score, percentiles, interactive charts
- ๐ Database Transactions - Track atomic blocks, commits, rollbacks
- ๐ Storage Operations - Monitor file saves, reads, deletes (S3/Local)
- ๐ Health Dashboard (
/orbit/health/) - Visual module status with green/red/yellow indicators - ๐ Modular Architecture - Each watcher operates independently; failures don't crash your app
- ๐ Diagnostics API -
get_watcher_status(),get_failed_watchers()for programmatic checks - ๐ ๏ธ Graceful Degradation - Failed modules auto-disable while others continue working
- ๐ Beautiful Dark UI - Space-themed mission control
- โก Live Updates - HTMX-powered real-time feed
- ๐ Event Correlation - Link related events with family grouping
- ๐ Zero DOM Injection - Lives at its own URL, no template pollution
"Satellite Observability" - Like a satellite, Orbit observes your application from a distance without interfering with it.
Unlike Django Debug Toolbar which injects HTML into your templates, Django Orbit runs on its own isolated URL (/orbit/). This means:
- โ No DOM pollution
- โ No CSS conflicts
- โ Works with any frontend (React, Vue, HTMX, etc.)
- โ API-friendly debugging
- โ Clean separation of concerns
pip install django-orbitgit clone https://github.com/astro-stack/django-orbit.git
cd django-orbit
pip install -e .
python demo.py setup # Creates sample data with ALL entry types
python manage.py runserverThen visit:
- Demo app: http://localhost:8000/
- Orbit Dashboard: http://localhost:8000/orbit/
- Stats Dashboard: http://localhost:8000/orbit/stats/
# settings.py
INSTALLED_APPS = [
# ...
'orbit',
]# settings.py
MIDDLEWARE = [
'orbit.middleware.OrbitMiddleware', # Add early
# ...
]# urls.py
from django.urls import path, include
urlpatterns = [
path('orbit/', include('orbit.urls')),
# ...
]python manage.py migrate orbitNavigate to http://localhost:8000/orbit/ ๐
# settings.py
ORBIT_CONFIG = {
'ENABLED': True,
'SLOW_QUERY_THRESHOLD_MS': 500,
'STORAGE_LIMIT': 1000,
# Core watchers
'RECORD_REQUESTS': True,
'RECORD_QUERIES': True,
'RECORD_LOGS': True,
'RECORD_EXCEPTIONS': True,
# Extended watchers
'RECORD_COMMANDS': True,
'RECORD_CACHE': True,
'RECORD_MODELS': True,
'RECORD_HTTP_CLIENT': True,
'RECORD_MAIL': True,
'RECORD_SIGNALS': True,
# Advanced watchers (v0.5.0+)
'RECORD_JOBS': True,
'RECORD_REDIS': True,
'RECORD_GATES': True,
# v0.6.0 watchers
'RECORD_TRANSACTIONS': True,
'RECORD_STORAGE': True,
# Security
'AUTH_CHECK': lambda request: request.user.is_staff,
'IGNORE_PATHS': ['/orbit/', '/static/', '/media/'],
}The new Stats Dashboard (/orbit/stats/) provides advanced analytics:
| Metric | Description |
|---|---|
| Apdex Score | User satisfaction index (0-1) |
| Percentiles | P50, P75, P95, P99 response times |
| Error Rate | Failure percentage with trend |
| Throughput | Requests per minute/hour |
| Database | Slow queries, N+1 detection |
| Cache | Hit rate with sparkline chart |
| Jobs | Success rate, failure tracking |
| Permissions | Top denied permissions |
The Health Dashboard (/orbit/health/) shows the status of all Orbit modules:
- ๐ข Green - Module is healthy and working
- ๐ด Red - Module failed to initialize (click for details)
- ๐ก Yellow - Module is disabled via configuration
Each watcher/module operates independently:
- If Celery isn't installed, the Celery watcher fails gracefully
- Other watchers continue working normally
- Failed modules are logged and visible in the Health dashboard
from orbit import get_watcher_status, get_failed_watchers
# Get status of all watchers
status = get_watcher_status()
# {'cache': {'installed': True, 'error': None, 'disabled': False}, ...}
# Get only failed watchers
failed = get_failed_watchers()
# {'celery': 'ModuleNotFoundError: No module named celery'}ORBIT_CONFIG = {
# Control error behavior
'WATCHER_FAIL_SILENTLY': True, # Default: log errors but continue
# Disable specific watchers
'RECORD_CACHE': False,
'RECORD_REDIS': False,
# ... etc
}Orbit automatically detects and monitors:
| Backend | Integration |
|---|---|
| Celery | Via signals (automatic) |
| Django-Q | Via signals (automatic) |
| RQ | Worker patching (automatic) |
| APScheduler | register_apscheduler(scheduler) |
| django-celery-beat | Via model signals (automatic) |
# Restrict access to staff users
ORBIT_CONFIG = {
'AUTH_CHECK': lambda request: request.user.is_staff,
}
# Or disable in production
ORBIT_CONFIG = {
'ENABLED': DEBUG,
}Orbit automatically hides sensitive data (passwords, tokens, API keys).
- Request/Query/Log/Exception tracking
- N+1 detection with duplicate navigation
- Management Commands, Cache, Models, HTTP Client
- Mail, Signals watchers
- Jobs (Celery, Django-Q, RQ, APScheduler)
- Redis operations
- Gates/Permissions
- Stats Dashboard with Apdex, charts
- Dashboard authentication
- Search, Export, Pagination
- External storage backends (Redis, PostgreSQL)
- Performance recommendations
- Custom dashboards
- Webhook integrations
If Django Orbit helps you debug faster, consider buying me a coffee!
We welcome contributions! See CONTRIBUTING.md.
MIT License - see LICENSE.
Inspired by Laravel Telescope, Spatie Ray, and Django Debug Toolbar.
Built with โค๏ธ for the Django community