Work has moved to a fork to continue on https://github.com/lingster/drf-api-tracking
drf-tracking provides a Django model and DRF view mixin that work together to log Django Rest Framework requests to the database. You'll get these attributes for every request/response cycle to a view that uses the mixin:
Model field name | Description | Model field type |
---|---|---|
user |
User if authenticated, None if not | Foreign Key |
requested_at |
Date-time that the request was made | DateTimeField |
response_ms |
Number of milliseconds spent in view code | PositiveIntegerField |
path |
Target URI of the request, e.g., "/api/" |
CharField |
view |
Target VIEW of the request, e.g., "views.api.ApiView" |
CharField |
view_method |
Target METHOD of the VIEW of the request, e.g., "get" |
CharField |
remote_addr |
IP address where the request originated (X_FORWARDED_FOR if available, REMOTE_ADDR if not), e.g., "127.0.0.1" |
GenericIPAddressField |
host |
Originating host of the request, e.g., "example.com" |
URLField |
method |
HTTP method, e.g., "GET" |
CharField |
query_params |
Dictionary of request query parameters, as text | TextField |
data |
Dictionary of POST data (JSON or form), as text | TextField |
response |
JSON response data | TextField |
status_code |
HTTP status code, e.g., 200 or 404 |
PositiveIntegerField |
- Django 1.11, 2.0, 2.1, 2.2, 3.0
- Django REST Framework and Python release supporting the version of Django you are using
Django | Python | DRF |
---|---|---|
1.11 | 2.7, 3.4, 3.5, 3.6 | 3.5, 3.6, 3.7, 3.8, 3.9 |
2.0 | 3.4, 3.5, 3.6, 3.7 | 3.7, 3.8, 3.9 |
2.1 | 3.5, 3.6, 3.7 | 3.7, 3.8, 3.9 |
2.2 | 3.5, 3.6, 3.7 | 3.7, 3.8, 3.9 |
3.0 | 3.5, 3.6, 3.7 | 3.7, 3.8, 3.9 |
Install using pip
...
$ pip install drf-tracking
Register with your Django project by adding rest_framework_tracking
to the INSTALLED_APPS
list in your project's settings.py
file.
Then run the migrations for the APIRequestLog
model:
$ python manage.py migrate
Add the rest_framework_tracking.mixins.LoggingMixin
to any DRF view
to create an instance of APIRequestLog
every time the view is called.
For instance:
# views.py
from rest_framework import generics
from rest_framework.response import Response
from rest_framework_tracking.mixins import LoggingMixin
class LoggingView(LoggingMixin, generics.GenericAPIView):
def get(self, request):
return Response('with logging')
For performance enhancement, explicitly choose methods to be logged using logging_methods
attribute:
class LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIView):
logging_methods = ['POST', 'PUT']
model = ...
Moreover, you could define your own rules by overriding should_log
method.
If should_log
evaluates to True a log is created.
class LoggingView(LoggingMixin, generics.GenericAPIView):
def should_log(self, request, response):
"""Log only errors"""
return response.status_code >= 400
At the example above, logging_methods
attribute will be ignored. If you want to provide some extra rules
on top of the http method filtering you should rewrite the should_log
method.
class LoggingView(LoggingMixin, generics.GenericAPIView):
def should_log(self, request, response):
"""Log only errors with respect on `logging_methods` attributes"""
should_log_method = super(LoggingView, self).should_log(request, response)
if not should_log_method:
return False
return response.status_code >= 400
A bit simpler.
class LoggingView(LoggingMixin, generics.GenericAPIView):
def should_log(self, request, response):
"""Log only errors with respect on `logging_methods` attributes"""
if not request.method in self.logging_methods:
return False
return response.status_code >= 400
Finally, you can also apply your customizations by overriding handle_log
method.
By default, all requests that satisfy should_log
method are saved on the database.
class LoggingView(LoggingMixin, generics.GenericAPIView):
def handle_log(self):
# Do some stuff before saving.
super(MockCustomLogHandlerView, self).handle_log()
# Do some stuff after saving.
Though, you could define your own handling. For example save on an in-memory data structure store, remote logging system etc.
class LoggingView(LoggingMixin, generics.GenericAPIView):
def handle_log(self):
cache.set('my_key', self.log, 86400)
Or you could omit save a request to the database. For example,
class LoggingView(LoggingMixin, generics.GenericAPIView):
def handle_log(self):
"""
Save only very slow requests. Requests that took more than a second.
"""
if self.log['response_ms'] > 1000:
super(MockCustomLogHandlerView, self).handle_log()
By default drf-tracking is hiding the values of those fields {'api', 'token', 'key', 'secret', 'password', 'signature'}
.
The default list hast been taken from Django itself (https://github.com/django/django/blob/stable/1.11.x/django/contrib/auth/init.py#L50).
You can complet this list with your own list by putting the fields you want to be hidden in the sensitive_fields
parameter of your view.
class LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIView):
sensitive_fields = {'my_secret_key', 'my_secret_recipe'}
Install testing requirements.
$ pip install -r requirements.txt
Run with runtests.
$ ./runtests.py
You can also use the excellent tox testing tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:
$ tox
To build the documentation, you'll need to install mkdocs
.
$ pip install mkdocs
To preview the documentation:
$ mkdocs serve
Running at: http://127.0.0.1:8000/
To build the documentation:
$ mkdocs build