diff --git a/.gitignore b/.gitignore index 1b23b0a2d..1bb868787 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ coverage.xml venv .direnv/ .envrc -venv +.venv .vscode diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index 6ef9f0d7c..f766d6db0 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -17,6 +17,8 @@ class TimerPanel(Panel): Panel that displays the time a response took in milliseconds. """ + is_async = True + def nav_subtitle(self): stats = self.get_stats() if stats.get("utime"): diff --git a/docs/architecture.rst b/docs/architecture.rst index 54b3b9318..f3bae60df 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -81,7 +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 ``TimerPanel``, ``RequestPanel`` and ``ProfilingPanel`` aren't + panels such as ``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 `_. diff --git a/docs/changes.rst b/docs/changes.rst index 6a58f7e77..452242279 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -4,6 +4,7 @@ Change log Pending ------- +* Added support for async to timer panel. * Added a note about the default password in ``make example``. * Removed logging about the toolbar failing to serialize a value into JSON. * Moved the the import statement of ``debug_toolbar.urls`` to within the if diff --git a/tests/test_integration_async.py b/tests/test_integration_async.py index 3cc2889c5..a9cfbb28a 100644 --- a/tests/test_integration_async.py +++ b/tests/test_integration_async.py @@ -1,3 +1,4 @@ +import re import unittest from unittest.mock import patch @@ -506,6 +507,29 @@ async def test_intercept_redirects(self): # Link to LOCATION header. self.assertIn(b'href="/regular/redirect/"', response.content) + async def test_server_timing_headers(self): + response = await self.async_client.get("/execute_sql/") + server_timing = response["Server-Timing"] + expected_partials = [ + r'TimerPanel_utime;dur=(\d)*(\.(\d)*)?;desc="User CPU time", ', + r'TimerPanel_stime;dur=(\d)*(\.(\d)*)?;desc="System CPU time", ', + r'TimerPanel_total;dur=(\d)*(\.(\d)*)?;desc="Total CPU time", ', + r'TimerPanel_total_time;dur=(\d)*(\.(\d)*)?;desc="Elapsed time", ', + r'SQLPanel_sql_time;dur=(\d)*(\.(\d)*)?;desc="SQL 1 queries", ', + r'CachePanel_total_time;dur=0;desc="Cache 0 Calls"', + ] + for expected in expected_partials: + self.assertTrue(re.compile(expected).search(server_timing)) + + @override_settings(DEBUG_TOOLBAR_CONFIG={"RENDER_PANELS": True}) + async def test_timer_panel(self): + response = await self.async_client.get("/regular/basic/") + self.assertEqual(response.status_code, 200) + self.assertContains( + response, + '