Package: drf-api-tracking
drf-api-trackingOverviewdrf-api-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 nameDescriptionModel field typeuserUser if authenticated, None if notForeign Keyusername_persistentStatic field that persists the username even if the User model object is deletedCharFieldrequested_atDate-time that the request was madeDateTimeFieldresponse_msNumber of milliseconds spent in view codePositiveIntegerFieldpathTarget URI of the request, e.g.,"/api/"CharFieldviewTarget VIEW of the request, e.g.,"views.api.ApiView"CharFieldview_methodTarget METHOD of the VIEW of the request, e.g.,"get"CharFieldremote_addrIP address where the request originated (X_FORWARDED_FOR if available, REMOTE_ADDR if not), e.g.,"127.0.0.1"GenericIPAddressFieldhostOriginating host of the request, e.g.,"example.com"URLFieldmethodHTTP method, e.g.,"GET"CharFieldquery_paramsDictionary of request query parameters, as textTextFielddataDictionary of POST data (JSON or form), as textTextFieldresponseJSON response dataTextFieldstatus_codeHTTP status code, e.g.,200or404PositiveIntegerFieldRequirementsDjango 1.11, 2.0, 2.1, 2.2, 3.0Django REST Framework and Python release supporting the version of Django you are usingDjangoPythonDRF1.112.7, 3.5, 3.63.5, 3.6, 3.7, 3.8, 3.92.03.5, 3.6, 3.73.7, 3.8, 3.92.13.5, 3.6, 3.7, 3.83.7, 3.8, 3.92.23.5, 3.6, 3.7, 3.83.7, 3.8, 3.93.03.5, 3.6, 3.7, 3.83.7, 3.8, 3.9InstallationInstall usingpip...$pipinstalldrf-api-trackingRegister with your Django project by addingrest_framework_trackingto theINSTALLED_APPSlist in your project'ssettings.pyfile.
Then run the migrations for theAPIRequestLogmodel:$pythonmanage.pymigrateUsageAdd therest_framework_tracking.mixins.LoggingMixinto any DRF view
to create an instance ofAPIRequestLogevery time the view is called.For instance:# views.pyfromrest_frameworkimportgenericsfromrest_framework.responseimportResponsefromrest_framework_tracking.mixinsimportLoggingMixinclassLoggingView(LoggingMixin,generics.GenericAPIView):defget(self,request):returnResponse('with logging')For performance enhancement, explicitly choose methods to be logged usinglogging_methodsattribute:classLoggingView(LoggingMixin,generics.CreateModelMixin,generics.GenericAPIView):logging_methods=['POST','PUT']model=...Moreover, you could define your own rules by overridingshould_logmethod.
Ifshould_logevaluates to True a log is created.classLoggingView(LoggingMixin,generics.GenericAPIView):defshould_log(self,request,response):"""Log only errors"""returnresponse.status_code>=400At the example above,logging_methodsattribute will be ignored. If you want to provide some extra rules
on top of the http method filtering you should rewrite theshould_logmethod.classLoggingView(LoggingMixin,generics.GenericAPIView):defshould_log(self,request,response):"""Log only errors with respect on `logging_methods` attributes"""should_log_method=super(LoggingView,self).should_log(request,response)ifnotshould_log_method:returnFalsereturnresponse.status_code>=400A bit simpler.classLoggingView(LoggingMixin,generics.GenericAPIView):defshould_log(self,request,response):"""Log only errors with respect on `logging_methods` attributes"""ifnotrequest.methodinself.logging_methods:returnFalsereturnresponse.status_code>=400Finally, you can also apply your customizations by overridinghandle_logmethod.
By default, all requests that satisfyshould_logmethod are saved on the database.classLoggingView(LoggingMixin,generics.GenericAPIView):defhandle_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.classLoggingView(LoggingMixin,generics.GenericAPIView):defhandle_log(self):cache.set('my_key',self.log,86400)Or you could omit save a request to the database. For example,classLoggingView(LoggingMixin,generics.GenericAPIView):defhandle_log(self):"""Save only very slow requests. Requests that took more than a second."""ifself.log['response_ms']>1000:super(MockCustomLogHandlerView,self).handle_log()If your endpoint accepts large file uploads, drf-api-tracking's default behavior to decode the request body may cause aRequestDataTooBigexception. This behavior can be disabled globally by settingDRF_TRACKING_DECODE_REQUEST_BODY = Falsein yoursettings.pyfile.You can also customize this behavior for individual views by setting thedecode_request_bodyattribute:classLoggingView(LoggingMixin,generics.GenericAPIView):decode_request_body=FalseSecurityBy default drf-api-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 complete this list with your own list by putting the fields you want to be hidden in thesensitive_fieldsparameter of your view.classLoggingView(LoggingMixin,generics.CreateModelMixin,generics.GenericAPIView):sensitive_fields={'my_secret_key','my_secret_recipe'}By default drf-tracking allows API request log entries to be modified from Django admin. This can present a data integrity issue in production environments. In order to change this behavior, you can setDRF_TRACKING_ADMIN_LOG_READONLYtoTruein yoursettings.pyfile.DevelopmentIn the folder there is a sample drf project:drf_api_sampleif changes are made to this packages models, use this project
to help generate new migrations, which should be checked in.TestingInstall testing requirements.$pipinstall-rrequirements.txtRun with runtests.$./runtests.pyYou can also use the excellenttoxtesting tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:$toxyou can also use pyenv to install multiple versions of python and ensure they are found by tox by issuing:pyenvinstall3.8.4
pyenvinstall3.7.7
pyenvinstall3.6.11
pyenvlocal3.8.43.7.73.6.11
pyenvglobal3.8.43.7.73.6.11Also ensure that you don't have a virtualenv activated when you run the tests else you might get the following error, or similar:ERROR: InterpreterNotFound: python3.6ContributingIn order to make changes to the package itself, providing migrations or something else,
make sure to install the current package with pip, otherwise using thedrf_api_samplewon't work.pipinstall-e.After this, you can edit models and creating migrations withpythondrf_api_sample/manage.pymakemigrationsDocumentationTo build the documentation, you'll need to installmkdocs.$pipinstallmkdocsTo preview the documentation:$mkdocsserve
Runningat:http://127.0.0.1:8000/To build the documentation:$mkdocsbuildtravisInstall RVM to have a local user version of ruby/gem:https://rvm.io/rvm/installThen install travis like this:gem install travisadd your secret key as per the link below:https://docs.travis-ci.com/user/encryption-keys/pyenvusing pyenv you can install multiple versions of python so that tox can run tests against all installed versions of pythonpyenvglobal3.6.83.7.73.8.2ensure that before running tox you don't have a virtualenv created and tox has been installed globally or via pipx