用于慢速 SQL 查询的 Django 日志过滤器
Posted
技术标签:
【中文标题】用于慢速 SQL 查询的 Django 日志过滤器【英文标题】:Django log filter for slow SQL queries 【发布时间】:2013-06-11 02:55:39 【问题描述】:由于以下 LOGGING 设置,我目前正在记录所有 SQL 查询:
LOGGING =
'version': 1,
'disable_existing_loggers': False,
'filters':
'require_debug_false':
'()': 'django.utils.log.RequireDebugFalse'
,
'formatters':
'standard':
'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt' : "%d/%b/%Y %H:%M:%S"
,
,
'handlers':
'mail_admins':
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
,
'console':
# logging handler that outputs log messages to terminal
'class': 'logging.StreamHandler',
'level': 'DEBUG', # message level to be written to console
,
'logfile':
'level':'DEBUG',
'class':'logging.handlers.RotatingFileHandler',
'filename': os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "log", "logfile"),
'maxBytes': 50000,
'backupCount': 2,
'formatter': 'standard',
,
,
'loggers':
'django.request':
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
,
'django.db':
'handlers': ['logfile'],
'level': 'DEBUG',
'propagate': False, # django also has database level logging
,
我在日志文件中实际得到的是:
[14/Jun/2013 13:54:19] DEBUG [django.db.backends:51] (0.000) SELECT "django_content_type"."id", "django_content_type"."name", "django_content_type"."app_label", "django_content_type"."model" FROM "django_content_type" WHERE "django_content_type"."app_label" = sites ORDER BY "django_content_type"."name" ASC; args=(u'sites',)
我想只过滤完成时间超过 300 毫秒的查询。
我应该如何编写日志配置的filters
部分,以及执行过滤的类是什么样的?
【问题讨论】:
【参考方案1】:到目前为止,我已经尝试使用 CallbackFilter,但我更喜欢使用日志记录类。
LOGGING =
'version': 1,
'disable_existing_loggers': False,
'filters':
'queries_above_300ms':
'()': 'django.utils.log.CallbackFilter',
'callback': lambda record: record.duration > 0.3 # output slow queries only
,
,
'formatters':
'standard':
'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt' : "%d/%b/%Y %H:%M:%S"
,
,
'handlers':
'logfile':
'level':'DEBUG',
'class':'logging.handlers.RotatingFileHandler',
'filename': os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "log", "logfile"),
'maxBytes': 50000,
'backupCount': 2,
'formatter': 'standard',
'filters': ['queries_above_300ms'],
,
,
'loggers':
'django.db':
'handlers': ['logfile'],
'level': 'DEBUG',
'propagate': False,
,
【讨论】:
这很有帮助!我所做的唯一修改是set the filter on the logger(在我的例子中是'django.db.backends')而不是处理程序。 还有什么方法可以构建堆栈跟踪吗?所以我们知道查询发生在哪里? 值得注意的是,如果settings.DEBUG
为真,Django 只会发出每个查询的日志记录(以及需要多长时间),所以这在开发/调试期间效果很好,但如果你想记录慢则不行生产中的查询也是如此。【参考方案2】:
您可以使用过滤器来附加 stack_info:
class SlowQueriesFilter(logging.Filter):
"""Filter slow queries and attach stack_info."""
def filter(self, record):
duration = record.duration
if duration > 0.1:
# Same as in _log for when stack_info=True is used.
fn, lno, func, sinfo = logging.Logger.findCaller(None, True)
record.stack_info = sinfo
return True
return False
将其添加到您的 filters
列表中,然后将其与记录器一起使用:
LOGGING =
'filters':
'slow_queries':
'()': 'app.log_filters.SlowQueriesFilter',
,
,
'loggers':
'django.db.backends':
'level': 'DEBUG',
'filters': ['slow_queries'],
stack_info
处理可能需要 Python 3,但需要自定义格式化程序
也可以用。
【讨论】:
以上是关于用于慢速 SQL 查询的 Django 日志过滤器的主要内容,如果未能解决你的问题,请参考以下文章
Django 慢查询:将 django 过滤语句连接到数据库日志中的慢查询