一个django中间件,记录慢请求的回溯。

dogslow的Python项目详细描述


概述

dogslow是一个django看门狗中间件类,它记录slow的回溯 请求。

它以帮助跟踪的internal project inside Bitbucket开头 操作问题。

安装

安装dogslow:

$ pip install dogslow

然后将dogslow.WatchdogMiddleware添加到 您的django settings.py文件:

MIDDLEWARE_CLASSES = (
    'dogslow.WatchdogMiddleware',
    ...
)

它还可以用作django 2.0风格的中间件功能:

MIDDLEWARE = (
    'dogslow.WatchdogMiddleware',
    ...
)

为了获得最佳效果,请将其作为第一批运行的中间产品之一。

配置

您可以在^{tt2}中使用以下配置属性$ 要调谐监视程序的文件:

# Watchdog is enabled by default, to temporarily disable, set to False:
DOGSLOW = True

# By default, Watchdog will create log files with the backtraces.
# You can also set the location of where it stores them:
DOGSLOW_LOG_TO_FILE = True
DOGSLOW_OUTPUT = '/tmp'

# Log requests taking longer than 25 seconds:
DOGSLOW_TIMER = 25

# When both specified, emails backtraces:
# (DOGSLOW_EMAIL_TO can also be a list of addresses)
DOGSLOW_EMAIL_TO = 'errors@atlassian.com'
DOGSLOW_EMAIL_FROM = 'no-reply@atlassian.com'

# Also log to this logger (defaults to none):
DOGSLOW_LOGGER = 'syslog_logger'
DOGSLOW_LOG_LEVEL = 'WARNING'

# Tuple of url pattern names that should not be monitored:
# (defaults to none -- everything monitored)
# Note: this option is not compatible with Django < 1.3
DOGSLOW_IGNORE_URLS = ('some_view', 'other_view')

# Print (potentially huge!) local stack variables (off by default, use
# True for more detailed, but less manageable reports)
DOGSLOW_STACK_VARS = True

用法

每个传入的http请求都会在监视程序中获得25秒的超时。如果 请求在该时间内未返回,监视程序将激活并获取 查看请求线程的堆栈并写入回溯(包括所有 本地堆栈变量–django样式)到日志文件。

每个慢速请求都记录在一个单独的文件中,该文件如下所示:

Undead request intercepted at: 16-05-2011 02:10:12 UTC

GET http://localhost:8000/?delay=2
Thread ID:  140539485042432
Process ID: 18010
Started:    16-05-2011 02:10:10 UTC

  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 107, in inner_run
    run(self.addr, int(self.port), handler, ipv6=self.use_ipv6)
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 696, in run
    httpd.serve_forever()
  File "/usr/lib/python2.7/SocketServer.py", line 227, in serve_forever
    self._handle_request_noblock()
  File "/usr/lib/python2.7/SocketServer.py", line 284, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 310, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 570, in __init__
    BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
  File "/usr/lib/python2.7/SocketServer.py", line 639, in __init__
    self.handle()
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 615, in handle
    handler.run(self.server.get_app())
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 283, in run
    self.result = application(self.environ, self.start_response)
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 68, in __call__
    return self.application(environ, start_response)
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 273, in __call__
    response = self.get_response(request)
  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/home/erik/work/middleware/middleware/sleep/views.py", line 6, in sleep
    time.sleep(float(request.GET.get('delay', 1)))

Full backtrace with local variables:

  File "/home/erik/work/virtualenv/bit/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 107, in inner_run
    run(self.addr, int(self.port), handler, ipv6=self.use_ipv6)

  ...loads more...

上面的示例显示请求线程在 time.sleep()dogslow拍摄快照时。

dogslow超时过期之前返回的请求不会被记录。

注意dogslow只查看线程的堆栈。它没有 中断请求,或以任何其他方式影响请求。使用dogslow是 因此在生产中使用是安全的。

岗哨整合

多格斯洛天生就和哨兵结合在一起。您可以通过配置 dogslow使用DOGSLOW_LOGGERDOGSLOW_LOG_TO_SENTRYconfiguring Raven收集Dogslow的报告。

DOGSLOW_LOGGER = 'dogslow' # can be anything, but must match `logger` below
DOGSLOW_LOG_TO_SENTRY = True

DOGSLOW_LOG_LEVEL = 'WARNING' # optional, defaults to 'WARNING'

# Add a new sentry handler to handle WARNINGs. It's not recommended to
# modify the existing sentry handler, as you'll probably start seeing
# other warnings unnecessarily sent to Sentry.
LOGGING = {
    ...
    'handlers': {
        ...
        'dogslow': {
            'level': 'WARNING',
            'class': 'raven.contrib.django.handlers.SentryHandler',
        }
        ...
    }
    'loggers': {
        ...
        'dogslow': {
            'level': 'WARNING',
            'handlers': ['dogslow'], # or whatever you named your handler
        }
        ...
    }
    ...
}

注意事项

dogslow使用多线程。它有一个单独的后台线程来处理 监视程序超时并接受回溯,以便原始请求 线程不会中断。这有一些后果。

多线程和gil

在cpython中,gil(全局解释器锁)防止多个线程 同时执行python代码。只有当线程显式释放 它的锁在gil上,可以有第二个线程运行。

每当python程序 阻止解释器外部的调用,例如在执行IO时。

对于dogslow,这意味着它只能可靠地拦截 很慢,因为他们正在进行IO、呼叫睡眠或忙着等待获取 自锁。

在大多数情况下这是好的。Django请求缓慢的一个重要原因是 昂贵的数据库查询。因为这是io,dogslow可以截获那些 好的。cpython的gil有问题的场景是 线程在python代码(或合法的python,即 非常昂贵,需要很长时间来执行),从不释放 吉尔。尽管dogslow的看门狗计时器线程确实可以运行,但是 无法记录堆栈。

联合程序和greenlet

Dogslow用于同步工作机配置。一个 使用专用线程(或单线程专用工作线程)的Web服务器 处理)以满足请求。django的内置wsgi服务器这样做,就像 在默认同步工作模式下,Gunicorn

当使用“共同例程框架”运行时,其中提供多个请求 同时由一条线,回溯可能会变得毫无意义。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java有可能让Glassfish JAAS领域与一个已安装的应用程序共享一些类吗?   卸载weblogic时发生java log4j错误   java如何读取信息并将这些信息放入对象数组中   java线程池执行器。创建新线程时执行(Runnable命令)   java无法将project facet动态Web模块的版本更改为2.5   未添加到ArrayList Java Android的元素   javajavax。xml。绑定UnmarshaleException:意外元素(uri:,local:“ProcessCreditApplication”)。预期的元素是   java如何通过youtube API获取已删除视频的列表   如何在JavaBean验证中停止级联   java为什么我的ListView使我的应用程序崩溃,而不是列出我的条目?   java Guice多数据库自动切换   java(JDA)Mute命令在代码的第四行中断   推荐一种可通过Java中的随机访问进行更新的索引文件格式   java将arrayList添加到2x2 arrayList   java json对象数据发生变化,有时没有值   java使用Jedis库在redis中一次存储字符串列表   java快速排序分区   java setDaemon(false)是冗余的吗?   Java中的itext格式pdf