Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion debug_toolbar/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ async def __acall__(self, request):

# Activate instrumentation ie. monkey-patch.
for panel in toolbar.enabled_panels:
panel.enable_instrumentation()
if hasattr(panel, "aenable_instrumentation"):
await panel.aenable_instrumentation()
else:
panel.enable_instrumentation()
try:
# Run panels like Django middleware.
response = await toolbar.process_request(request)
Expand Down
3 changes: 3 additions & 0 deletions debug_toolbar/panels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ def enable_instrumentation(self):

Unless the toolbar or this panel is disabled, this method will be
called early in ``DebugToolbarMiddleware``. It should be idempotent.

Add the ``aenable_instrumentation`` method to a panel subclass
to support async logic for instrumentation.
"""

def disable_instrumentation(self):
Expand Down
10 changes: 9 additions & 1 deletion debug_toolbar/panels/sql/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from collections import defaultdict
from copy import copy

from asgiref.sync import sync_to_async
from django.db import connections
from django.urls import path
from django.utils.translation import gettext_lazy as _, ngettext
Expand Down Expand Up @@ -113,7 +114,7 @@ class SQLPanel(Panel):
the request.
"""

is_async = False
is_async = True

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -192,6 +193,13 @@ def get_urls(cls):
path("sql_profile/", views.sql_profile, name="sql_profile"),
]

async def aenable_instrumentation(self):
"""
Async version of enable instrumentation.
For async capable panels having async logic for instrumentation.
"""
await sync_to_async(self.enable_instrumentation)()

def enable_instrumentation(self):
# This is thread-safe because database connections are thread-local.
for connection in connections.all():
Expand Down
5 changes: 2 additions & 3 deletions docs/architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ Problematic Parts
the main benefit of the toolbar
- Support for async and multi-threading: ``debug_toolbar.middleware.DebugToolbarMiddleware``
is now async compatible and can process async requests. However certain
panels such as ``SQLPanel``, ``TimerPanel``,
``RequestPanel`` and ``ProfilingPanel`` aren't fully
compatible and currently being worked on. For now, these panels
panels such as ``TimerPanel``, ``RequestPanel`` and ``ProfilingPanel`` aren't
fully compatible and currently being worked on. For now, these panels
are disabled by default when running in async environment.
follow the progress of this issue in `Async compatible toolbar project <https://github.com/orgs/jazzband/projects/9>`_.
3 changes: 3 additions & 0 deletions docs/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ Pympler
Roboto
Transifex
Werkzeug
aenable
ajax
asgi
async
backend
backends
Expand All @@ -21,6 +23,7 @@ flatpages
frontend
htmx
inlining
instrumentation
isort
jQuery
jinja
Expand Down