From 5ff7b5ed8776d8aa236f26e84e4f04ff7f10b40d Mon Sep 17 00:00:00 2001
From: Petr Stribny <petr@stribny.name>
Date: Mon, 21 Feb 2022 13:03:35 +0000
Subject: [PATCH] Add dev dependencies for debugging

---
 backend/requirements/dev.txt               |  4 ++
 backend/src/baserow/config/settings/dev.py | 12 +++-
 backend/src/baserow/config/urls.py         |  7 ++-
 docs/development/debugging.md              | 64 ++++++++++++++++++++++
 docs/index.md                              |  1 +
 5 files changed, 85 insertions(+), 3 deletions(-)
 create mode 100644 docs/development/debugging.md

diff --git a/backend/requirements/dev.txt b/backend/requirements/dev.txt
index 0f1c98596..b5a47106d 100644
--- a/backend/requirements/dev.txt
+++ b/backend/requirements/dev.txt
@@ -4,6 +4,7 @@ pytest-env==0.6.2
 pytest-asyncio==0.15.1
 pytest-ordering==0.6
 pytest-mock==3.6.1
+pytest-icdiff==0.5
 freezegun==1.1.0
 responses==0.13.4
 watchdog==2.1.4
@@ -13,3 +14,6 @@ pyinstrument==4.0.3
 pyfakefs==4.5.0
 pytest-xdist==2.3.0
 responses==0.13.4
+django-silk==4.2.0
+django-extensions==3.1.5
+snoop==0.4.1
\ No newline at end of file
diff --git a/backend/src/baserow/config/settings/dev.py b/backend/src/baserow/config/settings/dev.py
index 2a081c8e6..0eae0f403 100644
--- a/backend/src/baserow/config/settings/dev.py
+++ b/backend/src/baserow/config/settings/dev.py
@@ -1,11 +1,21 @@
 from .base import *  # noqa: F403, F401
-
+import snoop
 
 DEBUG = True
 CELERY_EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
 WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES = 4
 WEBHOOKS_MAX_RETRIES_PER_CALL = 4
 
+INSTALLED_APPS += ["django_extensions", "silk"]  # noqa: F405
+
+MIDDLEWARE += [  # noqa: F405
+    "silk.middleware.SilkyMiddleware",
+]
+
+SILKY_ANALYZE_QUERIES = True
+
+snoop.install()
+
 try:
     from .local import *  # noqa: F403, F401
 except ImportError:
diff --git a/backend/src/baserow/config/urls.py b/backend/src/baserow/config/urls.py
index ae3299e9f..08ca18cb6 100644
--- a/backend/src/baserow/config/urls.py
+++ b/backend/src/baserow/config/urls.py
@@ -1,9 +1,8 @@
 from django.urls import include
-from django.urls import re_path
+from django.urls import re_path, path
 from django.http import HttpResponse
 from django.conf import settings
 from django.conf.urls.static import static
-
 from baserow.core.registries import plugin_registry
 
 
@@ -19,3 +18,7 @@ urlpatterns = (
     + plugin_registry.urls
     + static(settings.MEDIA_URL_PATH, document_root=settings.MEDIA_ROOT)
 )
+
+
+if settings.DEBUG:
+    urlpatterns += [path("silk/", include("silk.urls", namespace="silk"))]
diff --git a/docs/development/debugging.md b/docs/development/debugging.md
new file mode 100644
index 000000000..5693b2191
--- /dev/null
+++ b/docs/development/debugging.md
@@ -0,0 +1,64 @@
+# Debugging Tools
+
+Baserow development dependencies include some useful tools for debugging that you can use.
+
+## snoop
+
+[snoop](https://github.com/alexmojaki/snoop) is a powerful set of Python debugging tools.
+
+### Automatic tracing
+
+One of the common things to do is to use the `@snoop` decorator or the `snoop` context manager to trace the execution of a piece of Python code and show how variable values change over time:
+
+```python
+@snoop
+def test():
+    for i in range(5):
+        a = i*2
+
+# or
+
+with snoop:
+    for i in range(5):
+        a = i*2
+```
+
+The depth can be controlled with `depth` parameter, e.g. `@snoop(depth=2)` for tracing functions that go deep.
+
+Objects and dictionaries can be expanded automatically to show all their items or attributes using the `watch_explode` parameter taking a list of watched variable names:
+
+```python
+@snoop(watch_explode=['d'])
+def test():
+    d = {'key1': 0, 'key2': 1}
+    for i in range(5):
+        d["key1"] += 1
+```
+
+### Pretty printing
+
+Besides automatic tracing, variables can be pretty printed manually with `pp` function:
+
+```python
+d = {'key1': 0, 'key2': 1}
+pp(d)
+```
+
+Note that `import snoop` or `from snoop import pp` is not necessary as snoop is installed and available automatically.
+
+## django-extensions
+
+[django-extensions](https://github.com/django-extensions/django-extensions) is available to provide a variety of features like a shell with auto-imported Django models or a command to list all registered urls.
+
+You can use django-extensions commands inside backend docker containers:
+
+* `django-admin shell_plus` starts an interactive Python shell with loaded Django contexts and imported models.
+* `django-admin show_urls` lists all registered urls in the Baserow. 
+
+## django-silk
+
+[django-silk](https://github.com/jazzband/django-silk) is a live profiling and inspection tool for executed requests and database queries.
+
+The interface can be accessed at http://localhost:8000/silk/ after Baserow is started in the debug mode. Every request is logged and can be analyzed, including the list of performed database queries.
+
+django-silk can be also configured and used for profiling using the Python's built-in profiler, see the official documentation for details.
diff --git a/docs/index.md b/docs/index.md
index 325263132..7b0fd753d 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -51,6 +51,7 @@ Everything related to contributing and developing for Baserow.
   use them.
 * [Code quality](./development/code-quality.md): More information about the code style,
   quality, choices we made, and how we enforce them.
+* [Debugging](./development/debugging.md): Debugging tools and how to use them.
 * [Create a template](./development/create-a-template.md): Create a template that can be
   previewed and installed by others.
 * [dev.sh](./development/dev_sh.md): Further details on how to use Baserow's `./dev.sh`