Django日志过滤器用于慢速SQL查询

时间:2021-09-07 22:00:57

I am currently logging all SQL queries thanks to the following LOGGING settings:

由于以下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
        },
    }
}

What I actually get in my logfile is:

我在日志文件中实际得到的是:

[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',)

I'd like to filter only queries that takes above 300ms to complete.

我想仅过滤需要300毫秒以上才能完成的查询。

How should I write the filters section of my logging configuration, and what would look like the class that do the filtering?

我应该如何编写日志配置的过滤器部分,以及进行过滤的类看起来像什么?

2 个解决方案

#1


6  

So far, I've tried to use a CallbackFilter but I would prefer having a logging class.

到目前为止,我已经尝试使用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,
        },
    }
}

#2


0  

You can use a filter to attach the stack_info:

您可以使用过滤器附加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

Add it to your filters list and then use it with the logger:

将其添加到您的过滤器列表,然后将其与记录器一起使用:

LOGGING = {
    'filters': {
        'slow_queries': {
            '()': 'app.log_filters.SlowQueriesFilter',
        },
    },
    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'filters': ['slow_queries'],
        }
    }

Might require Python 3 for the stack_info handling, but a custom formatter could also be used.

可能需要Python 3进行stack_info处理,但也可以使用自定义格式化程序。

#1


6  

So far, I've tried to use a CallbackFilter but I would prefer having a logging class.

到目前为止,我已经尝试使用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,
        },
    }
}

#2


0  

You can use a filter to attach the stack_info:

您可以使用过滤器附加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

Add it to your filters list and then use it with the logger:

将其添加到您的过滤器列表,然后将其与记录器一起使用:

LOGGING = {
    'filters': {
        'slow_queries': {
            '()': 'app.log_filters.SlowQueriesFilter',
        },
    },
    'loggers': {
        'django.db.backends': {
            'level': 'DEBUG',
            'filters': ['slow_queries'],
        }
    }

Might require Python 3 for the stack_info handling, but a custom formatter could also be used.

可能需要Python 3进行stack_info处理,但也可以使用自定义格式化程序。