Profiling mit Django Silk

Für den reibunglosen Ablauf einer Applikation ist es notwendig, ein Profiling der Anwendung zu machen. Dafür bietet sich das Djanjo-Paket django-silk an.

Silk ist ein Live-Profilerstellungs- und Inspektionstool für Django. Silk fängt HTTP-Requests und Datenbankabfragen ab und speichert sie, bevor sie in einer Benutzeroberfläche zur weiteren Untersuchung angezeigt werden können.

Installation

Wir müssen django-silk via pip installieren:

(eventenv) pip install django-silk

und dann in der Middlewar in den Settings registieren. Dafür öffnen wir event_manager/event_manager/settings/base.py und fügen die Silk-Middleware am Besten ganz oben ein:

MIDDLEWARE = [
  "silk.middleware.SilkyMiddleware",
  "whitenoise.middleware.WhiteNoiseMiddleware",
  "django.middleware.security.SecurityMiddleware",
  "django.contrib.sessions.middleware.SessionMiddleware",
  "django.middleware.locale.LocaleMiddleware",
  "django.middleware.common.CommonMiddleware",
  "django.middleware.csrf.CsrfViewMiddleware",
  "django.contrib.auth.middleware.AuthenticationMiddleware",
  "django.contrib.messages.middleware.MessageMiddleware",
  "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

Darüberhinaus müssen wir silk noch in den INSTALLED_APPS registrieren, damit das System die App auch erkennt.

INSTALLED_APPS = [
    [..]
    "rest_framework",
    "rest_framework.authtoken",
    "silk",
]

Um das Silk-Backend via Browser aufrufen zu können, legen wir nun die URLs fest. Dazu öffnen wir event_manager/event_manager/urls.py und fügen die URLs zum Silk-backend hinzu:

urlpatterns = [
  ...
  path('silk/', include('silk.urls', namespace='silk')),
]

Nun können wir die Datenmigration durchführen:

python manage.py migrate
python manage.py collectstatic

Wir können das Backend nun unter http://127.0.0.1:8000/silk aufrufe aufrufen.

Was kann Silk?

Die Hauptaufgaben von Silk sind:

  • Middleware zum Abfangen von HTTP-Requests und Responses

  • Ein SQL-Wrapper um Datenbankanfragen zu profilen

  • Ein Context Manager/decorator um Code-Blocks und Funktionen zu profilen

  • Ein graphisches User Interface für die Visualisierung des Profilings

Live-Profiling

Bevor das Profiling im Produktiv-Betrieb eingesetzt wird, sollte es erstmal im lokalen Betrieb getestet werden. Bei sehr vielen Anfagen kann sich Profiling auf diese Art negativ auf die Performance auswirken.

Datenbank-Abfragen analysieren

Unter Summary finden sich alle durchgeführten Anfragen an das System. Mit Klick auf eine dieser Anfragen lässt sich die Datenbank-Performance und die Anzahl der Joins untersuchen:

../_images/silk_1.png ../_images/silk_2.png ../_images/silk_3.png ../_images/silk_4.png

Code-Abschnitte profilen

Interessanter wird es, wenn wir Codebereiche und Funktionen profilen wollen. Dazu bietet Silk mehrere möglichkeiten: einen Kontext-Manager, einen Decorator und dynamisches Profing über die Settings.

In den Einstellung muss SILKY_PYTHON_PROFILER aktiviert werden, um den integrierten cProfile-Profiler von Python zu verwenden. Jede Anfrage wird separat untersucht und die Ausgabe des Profilers ist auf der Seite „Profiling“ der Anfrage in der Silk-Benutzeroberfläche verfügbar.

in die event_manager/event_manager/settings/base.py tragen wir folgenes ein:

SILKY_PYTHON_PROFILER = True
SILKY_PYTHON_PROFILER_BINARY = True

Zusätzlich dekorieren wir die categories aus den event_manager/events/views.py mit dem silk_profile-Dekorator, um das sogenannte Silk-Profiling für diese View zu erstellen. Ohne den Dekorator würde standardmäßig nur das cProfiling gemacht.

# importieren des silk_profile Decorators
from silk.profiling.profiler import silk_profile

# anderer code
...

@silk_profile()
def categories(request):
  ..

Wenn wir jetzt erneut die Route http://127.0.0.1:8000/events/categories/ aufrufen, finden wir im Silk-Backend das Profiling für diese Funktion (categories).

../_images/silk_5.png ../_images/silk_6.png

Zusätzlich sollte ein Graph zu sehen sein:

../_images/silk_7.png

Zusätzliche Settings

Um zu verhindern, dass das Silk-Backend öffentlich aufrufbar ist, müssen wir noch folgende Einträge in der event_manager/event_manager/settings/base.py machen:

SILKY_AUTHENTICATION = True  # User must login
SILKY_AUTHORISATION = True  # User must have permissions

Nun können nur noch eingeloggte User mit Staff-Status das Silk-Backend aufrufen.

Silk speichert immer den kompletten Response-Body ab. Das ist ist im Live-Betrieb unperformant. Deshalb sollte man das im Livebetrieb verhinden. Wir wollen nur einen Teil des Response-Bodys speichern, und zwar die ersten 1024 Byte. Ebenfalls in der event_manager/event_manager/settings/prod.py tragen wir ein:

# der Defaultwert ist -1 und bedeutet: kein Limit.
SILKY_MAX_RESPONSE_BODY_SIZE = 1024

Ein weiteres Problem im Live-Betrieb ist, dass wir bei vielen Anfragen nicht alle Anfragen untersuchen können. Oft reicht es, nur einen Teil der Anfragen zu loggen. Ebenso brauchen wir nicht alle Request speichern, sondern können einen Maximalwert an gespeicherten Requests angeben. Zwei weitere Settings in den Produktiv-Settings unter event_manager/event_manager/settings/prod.py sind also:

# 20% der Anfragen loggen
SILKY_INTERCEPT_PERCENT = 20
SILKY_MAX_RECORDED_REQUESTS = 10_000

Geloggte Daten löschen

mit dem folgenden Management-Command können alle geloggten Daten gelöscht werden:

(eventenv) python manage.py silk_clear_request_log

Weiterführende Informationen

weiterführende Infos zu django-silk findet man hier: