# -*- coding: utf-8 -*- # import re import os from collections import defaultdict from django.conf import settings from django.dispatch import receiver from django.core.signals import request_finished from django.db import connection from django.conf import LazySettings from django.db.utils import ProgrammingError, OperationalError from common.utils import get_logger from .local import thread_local from .signals import django_ready pattern = re.compile(r'FROM `(\w+)`') logger = get_logger(__name__) DEBUG_DB = os.environ.get('DEBUG_DB', '0') == '1' class Counter: def __init__(self): self.counter = 0 self.time = 0 def __gt__(self, other): return self.counter > other.counter def __lt__(self, other): return self.counter < other.counter def __eq__(self, other): return self.counter == other.counter def on_request_finished_logging_db_query(sender, **kwargs): queries = connection.queries counters = defaultdict(Counter) for query in queries: if not query['sql'] or not query['sql'].startswith('SELECT'): continue tables = pattern.findall(query['sql']) table_name = ''.join(tables) time = query['time'] counters[table_name].counter += 1 counters[table_name].time += float(time) counters['total'].counter += 1 counters['total'].time += float(time) counters = sorted(counters.items(), key=lambda x: x[1]) for name, counter in counters: logger.debug("Query {:3} times using {:.2f}s {}".format( counter.counter, counter.time, name) ) @receiver(request_finished) def on_request_finished_release_local(sender, **kwargs): thread_local.__release_local__() if settings.DEBUG and DEBUG_DB: request_finished.connect(on_request_finished_logging_db_query) @receiver(django_ready) def monkey_patch_settings(sender, **kwargs): def monkey_patch_getattr(self, name): val = getattr(self._wrapped, name) if callable(val): val = val() return val try: LazySettings.__getattr__ = monkey_patch_getattr except (ProgrammingError, OperationalError): pass