logger.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import logging
  2. from django.conf import settings
  3. from django.db import OperationalError, transaction
  4. from dj_cqrs.constants import (
  5. DB_VENDOR_MYSQL,
  6. DB_VENDOR_PG,
  7. MYSQL_TIMEOUT_ERROR_CODE,
  8. PG_TIMEOUT_FLAG,
  9. SUPPORTED_TIMEOUT_DB_VENDORS,
  10. )
  11. def install_last_query_capturer(model_cls):
  12. conn = _connection(model_cls)
  13. if not _get_last_query_capturer(conn):
  14. conn.execute_wrappers.append(_LastQueryCaptureWrapper())
  15. def log_timed_out_queries(error, model_cls): # pragma: no cover
  16. log_q = bool(settings.CQRS['replica'].get('CQRS_LOG_TIMED_OUT_QUERIES', False))
  17. if not (log_q and isinstance(error, OperationalError) and error.args):
  18. return
  19. conn = _connection(model_cls)
  20. conn_vendor = getattr(conn, 'vendor', '')
  21. if conn_vendor not in SUPPORTED_TIMEOUT_DB_VENDORS:
  22. return
  23. e_arg = error.args[0]
  24. is_timeout_error = bool(
  25. (conn_vendor == DB_VENDOR_MYSQL and e_arg == MYSQL_TIMEOUT_ERROR_CODE)
  26. or (conn_vendor == DB_VENDOR_PG and isinstance(e_arg, str) and PG_TIMEOUT_FLAG in e_arg)
  27. )
  28. if is_timeout_error:
  29. query = getattr(_get_last_query_capturer(conn), 'query', None)
  30. if query:
  31. logger_name = settings.CQRS['replica'].get('CQRS_QUERY_LOGGER', '') or 'django-cqrs'
  32. logger = logging.getLogger(logger_name)
  33. logger.error('Timed out query:\n%s', query)
  34. class _LastQueryCaptureWrapper:
  35. def __init__(self):
  36. self.query = None
  37. def __call__(self, execute, sql, params, many, context):
  38. try:
  39. execute(sql, params, many, context)
  40. finally:
  41. self.query = sql
  42. def _get_last_query_capturer(conn):
  43. return next((w for w in conn.execute_wrappers if isinstance(w, _LastQueryCaptureWrapper)), None)
  44. def _connection(model_cls):
  45. return transaction.get_connection(using=model_cls._default_manager.db)