Skip to content

Commit f95b40d

Browse files
authored
Async compatible SQLPanel (#1993)
* ASGI check approach with added test and docs * asynchronize instrumentation internally in panel logic rather than middleware * mark aenable_instrumentation as method * add asgi and aenable_instrumentation in wordlist * add instrumentation in spelling list
1 parent c401513 commit f95b40d

File tree

5 files changed

+21
-5
lines changed

5 files changed

+21
-5
lines changed

debug_toolbar/middleware.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ async def __acall__(self, request):
112112

113113
# Activate instrumentation ie. monkey-patch.
114114
for panel in toolbar.enabled_panels:
115-
panel.enable_instrumentation()
115+
if hasattr(panel, "aenable_instrumentation"):
116+
await panel.aenable_instrumentation()
117+
else:
118+
panel.enable_instrumentation()
116119
try:
117120
# Run panels like Django middleware.
118121
response = await toolbar.process_request(request)

debug_toolbar/panels/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ def enable_instrumentation(self):
154154
155155
Unless the toolbar or this panel is disabled, this method will be
156156
called early in ``DebugToolbarMiddleware``. It should be idempotent.
157+
158+
Add the ``aenable_instrumentation`` method to a panel subclass
159+
to support async logic for instrumentation.
157160
"""
158161

159162
def disable_instrumentation(self):

debug_toolbar/panels/sql/panel.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from collections import defaultdict
33
from copy import copy
44

5+
from asgiref.sync import sync_to_async
56
from django.db import connections
67
from django.urls import path
78
from django.utils.translation import gettext_lazy as _, ngettext
@@ -113,7 +114,7 @@ class SQLPanel(Panel):
113114
the request.
114115
"""
115116

116-
is_async = False
117+
is_async = True
117118

118119
def __init__(self, *args, **kwargs):
119120
super().__init__(*args, **kwargs)
@@ -192,6 +193,13 @@ def get_urls(cls):
192193
path("sql_profile/", views.sql_profile, name="sql_profile"),
193194
]
194195

196+
async def aenable_instrumentation(self):
197+
"""
198+
Async version of enable instrumentation.
199+
For async capable panels having async logic for instrumentation.
200+
"""
201+
await sync_to_async(self.enable_instrumentation)()
202+
195203
def enable_instrumentation(self):
196204
# This is thread-safe because database connections are thread-local.
197205
for connection in connections.all():

docs/architecture.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ Problematic Parts
8181
the main benefit of the toolbar
8282
- Support for async and multi-threading: ``debug_toolbar.middleware.DebugToolbarMiddleware``
8383
is now async compatible and can process async requests. However certain
84-
panels such as ``SQLPanel``, ``TimerPanel``,
85-
``RequestPanel`` and ``ProfilingPanel`` aren't fully
86-
compatible and currently being worked on. For now, these panels
84+
panels such as ``TimerPanel``, ``RequestPanel`` and ``ProfilingPanel`` aren't
85+
fully compatible and currently being worked on. For now, these panels
8786
are disabled by default when running in async environment.
8887
follow the progress of this issue in `Async compatible toolbar project <https://github.com/orgs/jazzband/projects/9>`_.

docs/spelling_wordlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ Pympler
66
Roboto
77
Transifex
88
Werkzeug
9+
aenable
910
ajax
11+
asgi
1012
async
1113
backend
1214
backends
@@ -21,6 +23,7 @@ flatpages
2123
frontend
2224
htmx
2325
inlining
26+
instrumentation
2427
isort
2528
jQuery
2629
jinja

0 commit comments

Comments
 (0)