{ "info": { "author": "Titus Peterson", "author_email": "UNKNOWN", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Django Query Logger\n===================\n\nQuery Logger is a Django mixin class for logging duplicate or slow\nqueries, query execution time, and total execution time. It's useful for\ndebugging specific areas of your code, and since its a mixin, it can be\nadded to any class (class based views, django rest framework\nserializers, celery tasks, etc), and turned on or off based on any\nlogic.\n\nThe logic for detecting duplicate queries and finding long running\nqueries, as well as the structure of the project and even this readme,\nare all inspired by (and in many cases copied over) from Django Query\nInspector (which unfortunately only works as a middleware, which was not\nwhat I needed), which can be found\n`here `__.\n\nWorks with Django (1.4, 1.5, 1.6, 1.7, 1.8, 1.9) and Python (2.7, 3.3,\n3.4, 3.5).\n\nExample log output:\n\n::\n\n [SQL] 17 queries (4 duplicates), 34 ms SQL time, 243 ms total request time\n\nThe duplicate queries can also be shown in the log:\n\n::\n\n [SQL] repeated query (6x): SELECT \"customer_role\".\"id\",\n \"customer_role\".\"contact_id\", \"customer_role\".\"name\"\n FROM \"customer_role\" WHERE \"customer_role\".\"contact_id\" = ?\n\nThe duplicate queries are detected by ignoring any integer values in the\nSQL statement. The reasoning is that most of the duplicate queries in\nDjango are due to results not being cached or pre-fetched properly, so\nDjango needs to look up related fields afterwards. This lookup is done\nby the object ID, which is in most cases an integer.\n\nThe heuristic is not 100% precise so it may have some false positives or\nnegatives, but is a very good starting point for most Django projects.\n\nFor each duplicate query, the Python traceback can also be shown, which\nmay help with identifying why the query has been executed:\n\n::\n\n File \"/vagrant/api/views.py\", line 178, in get\n return self.serialize(self.object_qs)\n File \"/vagrant/customer/views.py\", line 131, in serialize\n return serialize(objs, include=includes)\n File \"/vagrant/customer/serializers.py\", line 258, in serialize_contact\n lambda obj: [r.name for r in obj.roles.all()]),\n File \"/vagrant/customer/serializers.py\", line 258, in \n lambda obj: [r.name for r in obj.roles.all()]),\n\nQuickstart\n----------\n\nInstall from the Python Package Index:\n\n::\n\n pip install django-query-logger\n\nAnd thats it. You can import the mixin with:\n\n::\n\n from query_logger import DatabaseQueryLoggerMixin\n\nAny class can start and stop the debugger using the\nstart\\_query\\_logging and stop\\_query\\_logging methods. The logs are\nactually output when you call stop\\_query\\_logging.\n\n::\n\n class SomeClass(DatabaseQueryLoggerMixin):\n def go_stuff(self):\n self.start_query_logging()\n # ... do some queries\n self.stop_query_logging()\n # ... You can keep doing more stuff, if you want, no more queries will get logged\n\nAdd it to any class, such as a Django Rest Framework serializer, and\nbegin using it. You can even turn it on and off based on your own logic,\nso it doesnt run all the time:\n\n::\n\n from django.core.cache import cache\n from rest_framework import serializers\n from query_logger import DatabaseQueryLoggerMixin\n from .models import MyModel\n\n class MySerializer(serlializers.ModelSerializer, DatabaseQueryLoggerMixin):\n model = MyModel\n \n def save(self, request, *args, **kwargs):\n if cache.get(request.user.id):\n self.start_query_logging()\n # ... stuff happens here, remember to turn it off when your done\n \n\nUpdate your logging configuration so the output from the query\\_logger\napp shows up:\n\n::\n\n LOGGING = {\n ...\n 'handlers': {\n ...\n 'console': {\n 'level': 'DEBUG',\n 'class': 'logging.StreamHandler',\n },\n ...\n },\n\n 'loggers': {\n ...\n 'query_logger': {\n 'handlers': ['console'],\n 'level': 'DEBUG',\n 'propagate': True,\n },\n },\n ...\n }\n\nConfiguration\n-------------\n\nThe behaviour of Django Query Logger can be fine-tuned via the following\nsettings variables:\n\n::\n\n LOG_QUERY_DATABASE_CONNECTION = 'default' # Change this if you want to log from a different db connection\n LOG QUERY_DUPLICATE_QUERIES = True # Turn this off if you dont want to see duplicate query logs\n LOG_QUERY_TRACEBACKS = False # Include the traceback in your query logs. Useful if your not sure where \n # queries are coming from. Caution: turning this on everywhere can be a \n # performance issue\n LOG_QUERY_TIME_ABSOLUTE_LIMIT = 1000 # This is the time in milliseconds to log a long running query. \n # Set to 0 for no long running query logging\n\nDynamic Configuration\n---------------------\n\nIn addition to the settings available above, you can turn these config\noptions on and off at run time. I have done this to, for example, only\nturn on tracebacks for a specific user. Just pass an options dict like\nthis to the start\\_query\\_logging() function. Note: not all of these\nhave to be defined, it will fall back on the defaults if there is a\nmissing config option.\n\n::\n\n configuration_dict = {\n 'connection_name': 'default' # The name of the db connection to log\n 'log_duplicate_queries': True # Log the duplicate SQL queries\n 'log_tracebacks': False # Include the tracebacks for all the queries\n 'log_long_running_time': 1000 # Log long running time for this many milliseconds\n }\n self.start_query_logger(configuration_dict)\n\nTesting\n-------\n\nTo run tests just use ``tox`` command (https://pypi.python.org/pypi/tox)\n\n::\n\n tox # for all supported python and django versions\n\nIf you need you can run tox just for single environment, f.i.:\n\n::\n\n tox -e py27_django17\n\nFor available test environments refer to ``tox.ini`` file.\n\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/4word/django-query-logger", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "django-query-logger", "package_url": "https://pypi.org/project/django-query-logger/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-query-logger/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/4word/django-query-logger" }, "release_url": "https://pypi.org/project/django-query-logger/0.1.2/", "requires_dist": null, "requires_python": null, "summary": "A mixin for logging and debugging Django queries", "version": "0.1.2" }, "last_serial": 2192119, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "ff80c5237fdd4ef44b05683c82682fde", "sha256": "2c7cd15f68c41048706ab0492a7b48306ae3ee207f0cc85015273d504742c598" }, "downloads": -1, "filename": "django-query-logger-0.1.0.tar.gz", "has_sig": false, "md5_digest": "ff80c5237fdd4ef44b05683c82682fde", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4696, "upload_time": "2016-06-20T19:55:20", "url": "https://files.pythonhosted.org/packages/c5/30/2e1dc8221eb9f92070155da66dec019aade82f7a870ca764306c86c1a322/django-query-logger-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "fcd4fbf55198fd6b112c45b88d1e0f5b", "sha256": "b97ac9b8a63bce4674eb998e36f9a587f340fdd3c2668077be1c1a322a17189a" }, "downloads": -1, "filename": "django-query-logger-0.1.1.tar.gz", "has_sig": false, "md5_digest": "fcd4fbf55198fd6b112c45b88d1e0f5b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6997, "upload_time": "2016-06-20T23:43:42", "url": "https://files.pythonhosted.org/packages/e8/1a/5db44fb04afbdfab42c216185f43253d22a3ef8217795ed0c69e992e0f4f/django-query-logger-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "a8030a048e685ba013e05d84159a10d2", "sha256": "25794137a560f08a492c0e67afe8a99f21039c9cbed59e6e4df8efbeedb2ecdd" }, "downloads": -1, "filename": "django-query-logger-0.1.2.tar.gz", "has_sig": false, "md5_digest": "a8030a048e685ba013e05d84159a10d2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7017, "upload_time": "2016-06-28T18:36:05", "url": "https://files.pythonhosted.org/packages/25/66/a429807b9fc29342bdc3fe04ddafa6c434564d17d72e7c0c8e14fe69bf84/django-query-logger-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a8030a048e685ba013e05d84159a10d2", "sha256": "25794137a560f08a492c0e67afe8a99f21039c9cbed59e6e4df8efbeedb2ecdd" }, "downloads": -1, "filename": "django-query-logger-0.1.2.tar.gz", "has_sig": false, "md5_digest": "a8030a048e685ba013e05d84159a10d2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7017, "upload_time": "2016-06-28T18:36:05", "url": "https://files.pythonhosted.org/packages/25/66/a429807b9fc29342bdc3fe04ddafa6c434564d17d72e7c0c8e14fe69bf84/django-query-logger-0.1.2.tar.gz" } ] }