From 92c6b96c7227bccd0638721e3d61f5cb74c64829 Mon Sep 17 00:00:00 2001 From: Matt Mayfield Date: Thu, 21 Nov 2024 12:38:27 -0500 Subject: [PATCH 1/6] Add debug toolbar config and documentation --- Dockerfile-django-dev | 2 + Dockerfile-grader-dev | 1 + README.md | 11 +++++ autograder/settings/development.py | 65 +++++++++++++----------------- autograder/urls.py | 9 ++--- requirements.txt | 2 +- 6 files changed, 46 insertions(+), 44 deletions(-) diff --git a/Dockerfile-django-dev b/Dockerfile-django-dev index 1cb41b5c..feb14d2f 100644 --- a/Dockerfile-django-dev +++ b/Dockerfile-django-dev @@ -4,6 +4,8 @@ RUN pip install pip-tools COPY ./requirements.txt . RUN pip-sync requirements.txt +# IMPORTANT: Also update version in Dockerfile-grader-dev +RUN pip install django-debug-toolbar==3.5.0 WORKDIR /usr/src/app diff --git a/Dockerfile-grader-dev b/Dockerfile-grader-dev index 1da53db8..763712b0 100644 --- a/Dockerfile-grader-dev +++ b/Dockerfile-grader-dev @@ -8,5 +8,6 @@ RUN pip install pip-tools COPY ./requirements.txt . RUN pip-sync requirements.txt +RUN pip install django-debug-toolbar==3.5.0 WORKDIR /usr/src/app diff --git a/README.md b/README.md index f4949dc7..ebef3848 100644 --- a/README.md +++ b/README.md @@ -144,3 +144,14 @@ In addition to running pycodestyle, pydocstyle, and mypy, this will also check t Note that validating the API schema requires Node 16 (newer versions may work as well). You can install Node 16 with [NVM](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating). + +# Profiling +You can use django-debug-toolbar to profile API requests. + +1. Follow the [dev stack setup tutorial](https://github.com/eecs-autograder/autograder-full-stack/blob/master/docs/development_setup.md) for the [autograder-full-stack repo](https://github.com/eecs-autograder/autograder-full-stack). +2. Populate the database with benchmark data. +Benchmark scripts should be added to autograder-server/benchmarks and should include: + - Instructions on how to run them on the development stack. + - Results from the last time they were run (and specifying what machine). +3. Visit the API URL in your browser with the query parameter `debug=true` appended. +For example: `https://localhost:/api/users/current/?debug=true` diff --git a/autograder/settings/development.py b/autograder/settings/development.py index 72f81b86..bbfbaf6d 100644 --- a/autograder/settings/development.py +++ b/autograder/settings/development.py @@ -21,44 +21,33 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -# !!! IMPORTANT !!! -# As of 22 April, 2020, django-debug-toolbar 2.2 (required when using Django 3) -# causes a memory leak, which in turn causes MemoryError in tests that create -# subprocesses. If you need to profile something, install the library manually -# and then uncomment the settings below to enable it. Also uncomment the -# "__debug__" url pattern in urls.py. -# Once you are finished profiling, UNINSTALL the library an RE-COMMENT -# the settings. -# -# INSTALLED_APPS += [ -# 'debug_toolbar', -# ] -# def show_toolbar_callback(request): -# return DEBUG -# DEBUG_TOOLBAR_CONFIG = { -# 'SHOW_TOOLBAR_CALLBACK': show_toolbar_callback -# } -# DEBUG_TOOLBAR_PANELS = [ -# 'debug_toolbar.panels.versions.VersionsPanel', -# 'debug_toolbar.panels.timer.TimerPanel', -# 'debug_toolbar.panels.settings.SettingsPanel', -# 'debug_toolbar.panels.headers.HeadersPanel', -# 'debug_toolbar.panels.request.RequestPanel', -# 'debug_toolbar.panels.sql.SQLPanel', -# 'debug_toolbar.panels.profiling.ProfilingPanel', -# # 'debug_toolbar.panels.staticfiles.StaticFilesPanel', -# # 'debug_toolbar.panels.templates.TemplatesPanel', -# 'debug_toolbar.panels.cache.CachePanel', -# 'debug_toolbar.panels.signals.SignalsPanel', -# 'debug_toolbar.panels.logging.LoggingPanel', -# 'debug_toolbar.panels.redirects.RedirectsPanel', -# ] -# MIDDLEWARE += ( -# 'debug_toolbar.middleware.DebugToolbarMiddleware', -# 'autograder.non_html_debug_toolbar_middleware.NonHtmlDebugToolbarMiddleware', -# ) -# -# /IMPORTANT +INSTALLED_APPS += [ + 'debug_toolbar', +] +def show_toolbar_callback(request): + return DEBUG +DEBUG_TOOLBAR_CONFIG = { + 'SHOW_TOOLBAR_CALLBACK': show_toolbar_callback +} +DEBUG_TOOLBAR_PANELS = [ + 'debug_toolbar.panels.versions.VersionsPanel', + 'debug_toolbar.panels.timer.TimerPanel', + 'debug_toolbar.panels.settings.SettingsPanel', + 'debug_toolbar.panels.headers.HeadersPanel', + 'debug_toolbar.panels.request.RequestPanel', + 'debug_toolbar.panels.sql.SQLPanel', + 'debug_toolbar.panels.profiling.ProfilingPanel', + # 'debug_toolbar.panels.staticfiles.StaticFilesPanel', + # 'debug_toolbar.panels.templates.TemplatesPanel', + 'debug_toolbar.panels.cache.CachePanel', + 'debug_toolbar.panels.signals.SignalsPanel', + 'debug_toolbar.panels.logging.LoggingPanel', + 'debug_toolbar.panels.redirects.RedirectsPanel', +] +MIDDLEWARE += ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', + 'autograder.non_html_debug_toolbar_middleware.NonHtmlDebugToolbarMiddleware', +) REST_FRAMEWORK.update({ 'TEST_REQUEST_DEFAULT_FORMAT': 'json' diff --git a/autograder/urls.py b/autograder/urls.py index f22fe6be..b951b580 100644 --- a/autograder/urls.py +++ b/autograder/urls.py @@ -30,8 +30,7 @@ url(r'^static/(?P.*)$', views.serve), ] - # See note in autograder/settings/development.py - # import debug_toolbar - # urlpatterns = [ - # url(r'^__debug__/', include(debug_toolbar.urls)), - # ] + urlpatterns + import debug_toolbar + urlpatterns = [ + url(r'^__debug__/', include(debug_toolbar.urls)), + ] + urlpatterns diff --git a/requirements.txt b/requirements.txt index 9d6acfce..10af4de0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ celery==4.4.7 # via -r requirements.in decorator==4.4.2 # via ipython -django==3.2.2 +django==3.2.25 # via # -r requirements.in # django-redis From 7ff60275058d91e38671539a207dd1433b01d8d9 Mon Sep 17 00:00:00 2001 From: Matt Mayfield Date: Thu, 21 Nov 2024 12:49:02 -0500 Subject: [PATCH 2/6] recompile requirements-dev.txt --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 7e447556..6a2d77a3 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -16,7 +16,7 @@ coreapi==2.3.3 # via djangorestframework-stubs coreschema==0.0.4 # via coreapi -django==3.2.2 +django==3.2.25 # via # -c requirements.txt # django-stubs From a984290c26bfcb0ed9880a732150adb20f04be45 Mon Sep 17 00:00:00 2001 From: Matt Mayfield Date: Thu, 21 Nov 2024 13:14:46 -0500 Subject: [PATCH 3/6] Only import toolbar on dev server --- Dockerfile-grader-dev | 1 - autograder/settings/base.py | 5 +++ autograder/settings/development.py | 57 ++++++++++++++++-------------- autograder/urls.py | 4 ++- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/Dockerfile-grader-dev b/Dockerfile-grader-dev index 763712b0..1da53db8 100644 --- a/Dockerfile-grader-dev +++ b/Dockerfile-grader-dev @@ -8,6 +8,5 @@ RUN pip install pip-tools COPY ./requirements.txt . RUN pip-sync requirements.txt -RUN pip install django-debug-toolbar==3.5.0 WORKDIR /usr/src/app diff --git a/autograder/settings/base.py b/autograder/settings/base.py index d9e2f6e1..4f07dc94 100644 --- a/autograder/settings/base.py +++ b/autograder/settings/base.py @@ -256,3 +256,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' from autograder.settings.celery_settings import * # noqa + + +# Indicates that the Django service is running as part of the web development stack +# (specifically the web server rather than the graders or running linters). +IS_DEV_SERVER = os.environ.get('IS_DEV_SERVER', 'false') == 'true' diff --git a/autograder/settings/development.py b/autograder/settings/development.py index bbfbaf6d..ec964d1e 100644 --- a/autograder/settings/development.py +++ b/autograder/settings/development.py @@ -21,33 +21,36 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -INSTALLED_APPS += [ - 'debug_toolbar', -] -def show_toolbar_callback(request): - return DEBUG -DEBUG_TOOLBAR_CONFIG = { - 'SHOW_TOOLBAR_CALLBACK': show_toolbar_callback -} -DEBUG_TOOLBAR_PANELS = [ - 'debug_toolbar.panels.versions.VersionsPanel', - 'debug_toolbar.panels.timer.TimerPanel', - 'debug_toolbar.panels.settings.SettingsPanel', - 'debug_toolbar.panels.headers.HeadersPanel', - 'debug_toolbar.panels.request.RequestPanel', - 'debug_toolbar.panels.sql.SQLPanel', - 'debug_toolbar.panels.profiling.ProfilingPanel', - # 'debug_toolbar.panels.staticfiles.StaticFilesPanel', - # 'debug_toolbar.panels.templates.TemplatesPanel', - 'debug_toolbar.panels.cache.CachePanel', - 'debug_toolbar.panels.signals.SignalsPanel', - 'debug_toolbar.panels.logging.LoggingPanel', - 'debug_toolbar.panels.redirects.RedirectsPanel', -] -MIDDLEWARE += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', - 'autograder.non_html_debug_toolbar_middleware.NonHtmlDebugToolbarMiddleware', -) +if IS_DEV_SERVER: + INSTALLED_APPS += [ + 'debug_toolbar', + ] + + def show_toolbar_callback(request): + return DEBUG + + DEBUG_TOOLBAR_CONFIG = { + 'SHOW_TOOLBAR_CALLBACK': show_toolbar_callback + } + DEBUG_TOOLBAR_PANELS = [ + 'debug_toolbar.panels.versions.VersionsPanel', + 'debug_toolbar.panels.timer.TimerPanel', + 'debug_toolbar.panels.settings.SettingsPanel', + 'debug_toolbar.panels.headers.HeadersPanel', + 'debug_toolbar.panels.request.RequestPanel', + 'debug_toolbar.panels.sql.SQLPanel', + 'debug_toolbar.panels.profiling.ProfilingPanel', + # 'debug_toolbar.panels.staticfiles.StaticFilesPanel', + # 'debug_toolbar.panels.templates.TemplatesPanel', + 'debug_toolbar.panels.cache.CachePanel', + 'debug_toolbar.panels.signals.SignalsPanel', + 'debug_toolbar.panels.logging.LoggingPanel', + 'debug_toolbar.panels.redirects.RedirectsPanel', + ] + MIDDLEWARE += ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', + 'autograder.non_html_debug_toolbar_middleware.NonHtmlDebugToolbarMiddleware', + ) REST_FRAMEWORK.update({ 'TEST_REQUEST_DEFAULT_FORMAT': 'json' diff --git a/autograder/urls.py b/autograder/urls.py index b951b580..5f165e35 100644 --- a/autograder/urls.py +++ b/autograder/urls.py @@ -25,7 +25,9 @@ url(r'^api/', include('autograder.mutant_hints.urls')), ] -if settings.DEBUG: +if settings.IS_DEV_SERVER: + import sys + print(sys.argv, flush=True) urlpatterns += [ url(r'^static/(?P.*)$', views.serve), ] From 313b6147c4274ee290a012a7ca1eadbbd4a1d279 Mon Sep 17 00:00:00 2001 From: James Perretta Date: Thu, 21 Nov 2024 14:11:52 -0500 Subject: [PATCH 4/6] Cleanup sys import. --- autograder/urls.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/autograder/urls.py b/autograder/urls.py index 5f165e35..efbeaeda 100644 --- a/autograder/urls.py +++ b/autograder/urls.py @@ -26,8 +26,6 @@ ] if settings.IS_DEV_SERVER: - import sys - print(sys.argv, flush=True) urlpatterns += [ url(r'^static/(?P.*)$', views.serve), ] From 3b71b3019c9507f0ba31437e2d06d8f9aa6a3236 Mon Sep 17 00:00:00 2001 From: James Perretta Date: Thu, 21 Nov 2024 15:46:24 -0500 Subject: [PATCH 5/6] Removed obsolete comment. --- Dockerfile-django-dev | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile-django-dev b/Dockerfile-django-dev index feb14d2f..593bdfdc 100644 --- a/Dockerfile-django-dev +++ b/Dockerfile-django-dev @@ -4,7 +4,6 @@ RUN pip install pip-tools COPY ./requirements.txt . RUN pip-sync requirements.txt -# IMPORTANT: Also update version in Dockerfile-grader-dev RUN pip install django-debug-toolbar==3.5.0 WORKDIR /usr/src/app From 2d0c71767226618fc3a2e921f5644b0d503194cb Mon Sep 17 00:00:00 2001 From: James Perretta Date: Thu, 21 Nov 2024 15:48:18 -0500 Subject: [PATCH 6/6] Disabled logging panel in debug toolbar settings. --- autograder/settings/development.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autograder/settings/development.py b/autograder/settings/development.py index ec964d1e..9cd61744 100644 --- a/autograder/settings/development.py +++ b/autograder/settings/development.py @@ -44,7 +44,7 @@ def show_toolbar_callback(request): # 'debug_toolbar.panels.templates.TemplatesPanel', 'debug_toolbar.panels.cache.CachePanel', 'debug_toolbar.panels.signals.SignalsPanel', - 'debug_toolbar.panels.logging.LoggingPanel', + # 'debug_toolbar.panels.logging.LoggingPanel', 'debug_toolbar.panels.redirects.RedirectsPanel', ] MIDDLEWARE += (