{"id":13765661,"url":"https://github.com/lingster/drf-api-tracking","last_synced_at":"2025-05-16T03:04:15.468Z","repository":{"id":40695445,"uuid":"241950356","full_name":"lingster/drf-api-tracking","owner":"lingster","description":"Fork of aschn/drf-tracking so that we can maintain and release newer versions","archived":false,"fork":false,"pushed_at":"2024-07-26T23:30:58.000Z","size":434,"stargazers_count":282,"open_issues_count":39,"forks_count":60,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-08T13:09:16.685Z","etag":null,"topics":["django","drf-tracking","hacktoberfest","logging","python3","rest-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lingster.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-20T17:43:43.000Z","updated_at":"2025-04-05T07:30:24.000Z","dependencies_parsed_at":"2024-04-18T17:58:04.261Z","dependency_job_id":"43118ec8-d5a2-45a6-8bee-9d84936cc20c","html_url":"https://github.com/lingster/drf-api-tracking","commit_stats":{"total_commits":228,"total_committers":56,"mean_commits":4.071428571428571,"dds":0.8070175438596492,"last_synced_commit":"6e35f99e3f2ba56014cee5ddf180d037e3ae5663"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lingster%2Fdrf-api-tracking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lingster%2Fdrf-api-tracking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lingster%2Fdrf-api-tracking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lingster%2Fdrf-api-tracking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lingster","download_url":"https://codeload.github.com/lingster/drf-api-tracking/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254459088,"owners_count":22074605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","drf-tracking","hacktoberfest","logging","python3","rest-api"],"created_at":"2024-08-03T16:00:43.636Z","updated_at":"2025-05-16T03:04:10.411Z","avatar_url":"https://github.com/lingster.png","language":"Python","readme":"# drf-api-tracking\n\n[![build-status-image]][travis]\n[![pypi-version]][pypi]\n[![Requirements Status](https://requires.io/github/lingster/drf-api-tracking/requirements.svg?branch=master)](https://requires.io/github/lingster/drf-api-tracking/requirements/?branch=master)\n[![Coverage Status](https://coveralls.io/repos/github/lingster/drf-api-tracking/badge.svg?branch=master)](https://coveralls.io/github/lingster/drf-api-tracking?branch=master)\n\n## Overview\n\ndrf-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:\n\n\n Model field name | Description | Model field type\n------------------|-------------|-----------------\n`user` | User if authenticated, None if not | Foreign Key\n`username_persistent` | Static field that persists the username even if the User model object is deleted | CharField\n`requested_at` | Date-time that the request was made | DateTimeField\n`response_ms` | Number of milliseconds spent in view code | PositiveIntegerField\n`path` | Target URI of the request, e.g., `\"/api/\"` | CharField\n`view` | Target VIEW of the request, e.g., `\"views.api.ApiView\"` | CharField\n`view_method` | Target METHOD of the VIEW of the request, e.g., `\"get\"` | CharField\n`remote_addr` | IP address where the request originated (X_FORWARDED_FOR if available, REMOTE_ADDR if not), e.g., `\"127.0.0.1\"` | GenericIPAddressField\n`host` | Originating host of the request, e.g., `\"example.com\"` | URLField\n`method` | HTTP method, e.g., `\"GET\"` | CharField\n`query_params` | Dictionary of request query parameters, as text | TextField\n`data` | Dictionary of POST data (JSON or form), as text | TextField\n`response` | JSON response data | TextField\n`status_code` | HTTP status code, e.g., `200` or `404` | PositiveIntegerField\n\n\n## Requirements\n\n* Django 1.11, 2.0, 2.1, 2.2, 3.0\n* Django REST Framework and Python release supporting the version of Django you are using\n\nDjango | Python | DRF\n-------|--------|----\n1.11 | 2.7, 3.5, 3.6 | 3.5, 3.6, 3.7, 3.8, 3.9\n2.0 | 3.5, 3.6, 3.7 | 3.7, 3.8, 3.9\n2.1 | 3.5, 3.6, 3.7, 3.8 | 3.7, 3.8, 3.9\n2.2 | 3.5, 3.6, 3.7, 3.8 | 3.7, 3.8, 3.9\n3.0 | 3.5, 3.6, 3.7, 3.8 | 3.7, 3.8, 3.9\n\n## Installation\n\nInstall using `pip`...\n\n``` bash\n$ pip install drf-api-tracking\n```\n\nRegister with your Django project by adding `rest_framework_tracking`\nto the `INSTALLED_APPS` list in your project's `settings.py` file.\nThen run the migrations for the `APIRequestLog` model:\n\n``` bash\n$ python manage.py migrate\n```\n\n## Usage\n\nAdd the `rest_framework_tracking.mixins.LoggingMixin` to any DRF view\nto create an instance of `APIRequestLog` every time the view is called.\n\nFor instance:\n``` python\n# views.py\nfrom rest_framework import generics\nfrom rest_framework.response import Response\nfrom rest_framework_tracking.mixins import LoggingMixin\n\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    def get(self, request):\n        return Response('with logging')\n```\n\nFor performance enhancement, explicitly choose methods to be logged using `logging_methods` attribute:\n\n``` python\nclass LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIView):\n    logging_methods = ['POST', 'PUT']\n    model = ...\n```\n\nMoreover, you could define your own rules by overriding `should_log` method.\nIf `should_log` evaluates to True a log is created.\n\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    def should_log(self, request, response):\n        \"\"\"Log only errors\"\"\"\n        return response.status_code \u003e= 400\n```\n\nAt the example above, `logging_methods` attribute will be ignored. If you want to provide some extra rules\non top of the http method filtering you should rewrite the `should_log` method.\n\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    def should_log(self, request, response):\n        \"\"\"Log only errors with respect on `logging_methods` attributes\"\"\"\n        should_log_method = super(LoggingView, self).should_log(request, response)\n        if not should_log_method:\n            return False\n        return response.status_code \u003e= 400\n```\n\n A bit simpler.\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    def should_log(self, request, response):\n        \"\"\"Log only errors with respect on `logging_methods` attributes\"\"\"\n        if not request.method in self.logging_methods:\n            return False\n        return response.status_code \u003e= 400\n```\n\nFinally, you can also apply your customizations by overriding `handle_log` method.\nBy default, all requests that satisfy `should_log` method are saved on the database.\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    def handle_log(self):\n        # Do some stuff before saving.\n        super(MockCustomLogHandlerView, self).handle_log()\n        # Do some stuff after saving.\n```\n\n\nThough, you could define your own handling. For example save on an in-memory data structure store, remote logging system etc.\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n\n    def handle_log(self):\n        cache.set('my_key', self.log, 86400)\n```\n\nOr you could omit save a request to the database. For example,\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    def handle_log(self):\n        \"\"\"\n        Save only very slow requests. Requests that took more than a second.\n        \"\"\"\n        if self.log['response_ms'] \u003e 1000:\n            super(MockCustomLogHandlerView, self).handle_log()\n```\n\nIf your endpoint accepts large file uploads, drf-api-tracking's default behavior to decode the request body may cause a `RequestDataTooBig` exception. This behavior can be disabled globally by setting `DRF_TRACKING_DECODE_REQUEST_BODY = False` in your `settings.py`file.\n\nYou can also customize this behavior for individual views by setting the `decode_request_body` attribute:\n\n``` python\nclass LoggingView(LoggingMixin, generics.GenericAPIView):\n    decode_request_body = False\n```\n\n## Security\n\nBy default drf-api-tracking is hiding the values of those fields `{'api', 'token', 'key', 'secret', 'password', 'signature'}`.\nThe default list hast been taken from Django itself ([https://github.com/django/django/blob/stable/1.11.x/django/contrib/auth/__init__.py#L50](https://github.com/django/django/blob/stable/1.11.x/django/contrib/auth/__init__.py#L50)).\n\nYou can complete this list with your own list by putting the fields you want to be hidden in the `sensitive_fields` parameter of your view.\n\n``` python\nclass LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIView):\n    sensitive_fields = {'my_secret_key', 'my_secret_recipe'}\n```\n\nBy 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 set `DRF_TRACKING_ADMIN_LOG_READONLY` to `True` in your `settings.py` file.\n\n## Development\nIn the folder there is a sample drf project: `drf_api_sample` if changes are made to this packages models, use this project\nto help generate new migrations, which should be checked in.\n\n## Testing\n\nInstall testing requirements.\n\n``` bash\n$ pip install -r requirements.txt\n```\n\nRun with runtests.\n\n``` bash\n$ ./runtests.py\n```\n\nYou can also use the excellent [tox](http://tox.readthedocs.org/en/latest/) testing tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:\n\n``` bash\n$ tox\n```\nyou can also use pyenv to install multiple versions of python and ensure they are found by tox by issuing:\n``` bash\npyenv install 3.8.4\npyenv install 3.7.7\npyenv install 3.6.11\npyenv local 3.8.4 3.7.7 3.6.11\npyenv global 3.8.4 3.7.7 3.6.11\n```\nAlso ensure that you don't have a virtualenv activated when you run the tests else you might get the following error, or similar:\n`\nERROR: InterpreterNotFound: python3.6\n`\n\n## Contributing\n\nIn order to make changes to the package itself, providing migrations or something else,\nmake sure to install the current package with pip, otherwise using the `drf_api_sample` won't work.\n\n``` bash\npip install -e .\n```\n\nAfter this, you can edit models and creating migrations with\n\n``` bash\npython drf_api_sample/manage.py makemigrations\n```\n\n## Documentation\n\nTo build the documentation, you'll need to install `mkdocs`.\n\n``` bash\n$ pip install mkdocs\n```\n\nTo preview the documentation:\n\n``` bash\n$ mkdocs serve\nRunning at: http://127.0.0.1:8000/\n```\n\nTo build the documentation:\n\n``` bash\n$ mkdocs build\n```\n\n\n[build-status-image]: https://secure.travis-ci.org/lingster/drf-api-tracking.png?branch=master\n[travis]: http://travis-ci.org/lingster/drf-api-tracking?branch=master\n[pypi-version]: https://img.shields.io/pypi/v/drf-api-tracking.svg\n[pypi]: https://pypi.python.org/pypi/drf-api-tracking\n\n\n# travis\nInstall RVM to have a local user version of ruby/gem:\n`https://rvm.io/rvm/install`\nThen install travis like this:\n`gem install travis`\nadd your secret key as per the link below:\n`https://docs.travis-ci.com/user/encryption-keys/`\n\npyenv\n---\nusing pyenv you can install multiple versions of python so that tox can run tests against all installed versions of python\n``` bash\npyenv global 3.6.8 3.7.7 3.8.2\n```\nensure that before running tox you don't have a virtualenv created and tox has been installed globally or via pipx\n","funding_links":[],"categories":["Packages"],"sub_categories":["Logging"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flingster%2Fdrf-api-tracking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flingster%2Fdrf-api-tracking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flingster%2Fdrf-api-tracking/lists"}