【问题标题】:Django log filter for slow SQL queries用于慢速 SQL 查询的 Django 日志过滤器
【发布时间】: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 部分,以及执行过滤的类是什么样的?

【问题讨论】:

    标签: sql django logging


    【解决方案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,但需要自定义格式化程序 也可以用。

    【讨论】:

      猜你喜欢
      • 2012-02-28
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 2018-11-01
      • 2021-05-26
      • 2012-11-05
      • 2014-04-18
      相关资源
      最近更新 更多