Skip to main content

django-dev-insights

PyPI version CI

Lightweight, real-time performance diagnostics for Django development — per-request metrics printed to your console, emitted as structured JSON, or viewed in a built-in HTML panel.


Why this project

In real-world Django apps a single view can inadvertently issue dozens or hundreds of SQL queries. Finding the source of those queries is time-consuming. django-dev-insights gives you an immediate, per-request snapshot so you can find and fix hot spots during development.

Real results:

  • Page load reduced from 28s → 3.8s by identifying and removing 200+ duplicated queries.
  • Page load reduced from 8s → 1.8s by locating an N+1 pattern visible only with large datasets.

Features

  • Per-request metrics: total time, DB time, query count.
  • Duplicate SQL detection with optional stack traces — finds N+1 patterns instantly.
  • Slow query detection (configurable threshold) with optional stack traces.
  • Connection collector: detects setup queries (SET search_path, SELECT VERSION) and connection reopens.
  • Template collector: measures render time of each Django template per request.
  • HTML panel: browse recent request metrics at /__devinsights__/ — dark theme, severity colors, expandable detail rows, path filtering.
  • Path filtering: skip noisy requests (/static/, /favicon.ico) via EXCLUDE_PATHS.
  • Two output modes: colored text for interactive development and structured json for logs/CI.
  • Logging integration: emit JSON to Python's logging system with optional file rotation.

Installation

pip install django-dev-insights

Quickstart

Add the middleware to settings.py — place it high in the stack to measure the full request lifecycle:

# settings.py
MIDDLEWARE = [
    'dev_insights.middleware.DevInsightsMiddleware',
    # ... other middleware
]

Run python manage.py runserver and you will see per-request reports in your console (requires DEBUG = True).


HTML Panel

Browse recent request metrics in a visual dashboard:

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

urlpatterns = [
    path('__devinsights__/', include('dev_insights.urls')),
    # ... your other urls
]

Then visit http://localhost:8000/__devinsights__/ in your browser.

The panel shows a table of recent requests with:

  • Severity indicators (green/yellow/red) based on configurable thresholds
  • Click on any row to expand duplicate queries, slow queries, and template details
  • Filter by path to focus on specific endpoints
  • Only available when DEBUG = True

Output modes

Text output (default)

Colored, human-readable lines with expandable detail sections:

[DevInsights] Path: /users/45 | Total: 4821.37ms | DB Queries: 36 | DB Time: 4120.5ms | !! DUPLICATES: 12 !!
    [Duplicated SQLs]:
      -> (4x) SELECT "users"."id", ...
         Traceback:
         app/views.py:123 in user_detail -> User.objects.filter(...)
    [Slow Queries (> 100ms)]:
      -> [732.1ms] SELECT "reports"."id", ...
    [Templates]: 3 rendered in 45.2ms
      -> [30.1ms] templates/base.html
      -> [12.0ms] templates/users/detail.html

JSON output

Structured payload per request — useful for logs, CI, or tooling:

{
  "path": "/api/users/",
  "total_time_ms": 281.93,
  "db_metrics": {
    "query_count": 12,
    "total_db_time_ms": 266.0,
    "duplicate_sqls": [],
    "slow_queries": []
  },
  "connection_metrics": {
    "total_setup_query_count": 1,
    "setup_queries": {
      "default": [{"sql": "SET search_path = 'public'"}]
    }
  },
  "template_metrics": {
    "template_count": 2,
    "total_render_time_ms": 15.3,
    "templates": [
      {"name": "base.html", "time_ms": 10.1},
      {"name": "home.html", "time_ms": 5.2}
    ]
  }
}

Configuration

All settings go in DEV_INSIGHTS_CONFIG in your settings.py. Defaults shown below:

DEV_INSIGHTS_CONFIG = {
    # Thresholds for severity colors (text mode) and panel indicators
    'THRESHOLDS': {
        'total_time_ms': {'warn': 1000, 'crit': 3000},
        'query_count': {'warn': 20, 'crit': 50},
        'duplicate_query_count': {'warn': 5, 'crit': 10},
    },
    'SLOW_QUERY_THRESHOLD_MS': 100,

    # Stack traces for slow/duplicate/setup queries (adds overhead)
    'ENABLE_TRACEBACKS': False,
    'TRACEBACK_DEPTH': 5,

    # Collectors to enable
    'ENABLED_COLLECTORS': ['db', 'connection'],  # add 'template' to enable

    # Output
    'OUTPUT_FORMAT': 'text',        # 'text' or 'json'
    'DISPLAY_LIMIT': 100,           # max items per list
    'JSON_PRETTY': True,
    'JSON_INDENT': 2,

    # Logging integration
    'OUTPUT_LOGGER_NAME': None,     # logger name for JSON output
    'OUTPUT_LOG_FILE': None,        # auto-attach FileHandler if logger has no handlers

    # Path filtering
    'EXCLUDE_PATHS': [],            # e.g. ['/static/', '/favicon.ico']

    # HTML panel
    'PANEL_HISTORY_SIZE': 50,       # number of recent requests to keep in memory
}

Collectors

Collector Config key What it does
DBCollector 'db' Query count, DB time, duplicate detection (N+1), slow query detection. Optional stack traces.
ConnectionCollector 'connection' Detects setup queries (SET search_path, SELECT VERSION, SHOW) and connection reopens.
TemplateCollector 'template' Measures render time of each Django template. Opt-in — add 'template' to ENABLED_COLLECTORS.

Logging integration

Send structured JSON to your logging system instead of stdout:

# settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'dev_insights_file': {
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': '/var/log/myapp/dev_insights.json',
            'when': 'midnight',
            'backupCount': 7,
            'formatter': 'json_message',
        },
    },
    'formatters': {
        'json_message': {'format': '%(message)s'}
    },
    'loggers': {
        'dev_insights': {
            'handlers': ['dev_insights_file'],
            'level': 'INFO',
            'propagate': False,
        }
    }
}

DEV_INSIGHTS_CONFIG = {
    'OUTPUT_FORMAT': 'json',
    'OUTPUT_LOGGER_NAME': 'dev_insights',
}

Or use the simpler auto-attach pattern:

DEV_INSIGHTS_CONFIG = {
    'OUTPUT_FORMAT': 'json',
    'OUTPUT_LOGGER_NAME': 'dev_insights',
    'OUTPUT_LOG_FILE': '/var/log/myapp/dev_insights.json',
}

Multi-tenant / django-tenants

If you use django-tenants, place the tenant middleware before DevInsights to avoid repeated SET search_path queries:

MIDDLEWARE = [
    'django_tenants.middleware.main.TenantMainMiddleware',
    'dev_insights.middleware.DevInsightsMiddleware',
    # ...
]

Enable ENABLE_TRACEBACKS temporarily to locate the code path causing repeated schema switches.


Tips

  • Only runs when DEBUG = True — the middleware depends on connection.queries.
  • Keep ENABLE_TRACEBACKS disabled by default — enable only when actively debugging.
  • Use EXCLUDE_PATHS to filter static files and health checks from the output.
  • The HTML panel stores metrics in memory only — data is cleared on server restart.

Contributing

Contributions are welcome. Please open an issue or PR with a clear description and tests.


License

MIT — see LICENSE for details.

Release files for django-dev-insights 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-dev-insights 0.3.0
File Size Uploaded
django_dev_insights-0.3.0.tar.gz 26.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-dev-insights 0.3.0
File Interpreter ABI Platform
django_dev_insights-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 47.5 kB

Release files / django_dev_insights-0.3.0.tar.gz

Download URL django_dev_insights-0.3.0.tar.gz
Size 26.8 kB
Tags Source
SHA-256 checksum
How to use checksums
461e74e7229e1a15d4a72d9e3cc93d489323153fb4fc8f46144b4ddb81c0280c
BLAKE2b-256 checksum
How to use checksums
92650fc591b492182139bb40ca8ae361fc60644a3d0433ad7a6e5442db370dbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / django_dev_insights-0.3.0-py3-none-any.whl

Download URL django_dev_insights-0.3.0-py3-none-any.whl
Size 20.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
70e5113757867e1de3978a80ed0d8f1c44ca8d53aa46b719f8a0839721ab4f70
BLAKE2b-256 checksum
How to use checksums
0a4b923215e06eec75d3a5c8c354c75c71b2591a465b8f8eec2f8dc2c7baaa4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page