Skip to content

Commit

Permalink
Async compatible SQLPanel (#1993)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
salty-ivy authored Sep 2, 2024
1 parent c401513 commit f95b40d
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 5 deletions.
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

0 comments on commit f95b40d

Please sign in to comment.