问题 如何在gunicorn中运行时从django应用程序获取覆盖数据


如何从Django项目的视图代码(以及视图代码调用的代码)中获取代码覆盖率?

coverage gunicorn <params> 没有显示任何线被击中。


12970
2017-09-26 10:09


起源



答案:


coverage gunicorn <params> 不起作用,因为gunicorn创造了工人流程,而且 coverage 模块无法跨叉工作(基本上,创建新进程)。您可以使用 覆盖API但是,例如在包含WSGI应用程序的python模块中:

# wsgi_with_coverage.py
import atexit
import sys
import coverage
cov = coverage.coverage()
cov.start()

from wsgi import application  # adjust to python module containing your wsgi application


def save_coverage():
    print >> sys.stderr, "saving coverage"
    cov.stop()
    cov.save()

atexit.register(save_coverage)

然后跑 gunicorn -w 1 wsgi_with_coverage:application <other params>

问题是, atexit 如果你杀死了gunicorn进程,例如通过CTRL + C,则不会调用函数。但他们  拜访 SIGHUP,所以如果你这样做 kill -HUP $(cat <gunicorn_pidfile_here>),应保存覆盖率数据(默认为当前目录中的“.coverage”)。

一个可能的警告是,这不适用于多个gunicorn工作者,因为他们都会覆盖“.coverage”文件。如果你绝对需要一个以上的工人,你可以写信给 ".coverage-%d" % os.getpid() (设置文件名 通过 data_file 参数 coverage 构造函数)并使用 combine() 方法 合并各个测量值。

这应该也适用于其他WSGI服务器,具体取决于它们是否允许其工作进程通过其进行清理 atexit 方法。


12
2017-12-19 19:14



SIGHUP建议不太好:)。 Gunicorn在检索SIGHUP时重新加载工作进程。也就是说,收集的覆盖数据确实没有保存,而是被仅在加载时发生的那些事件覆盖。另一方面,发送SIGTER会正确触发atexit处理程序并干净地关闭Gunicorn。 - Jan-Philip Gehrcke
更新。设置 data_suffix=True 在打电话的时候 Coverage 构造函数会自动将机器名和PID添加到coverage文件名中。而不是使用 data_file 如上所述。 - Sean Perry


答案:


coverage gunicorn <params> 不起作用,因为gunicorn创造了工人流程,而且 coverage 模块无法跨叉工作(基本上,创建新进程)。您可以使用 覆盖API但是,例如在包含WSGI应用程序的python模块中:

# wsgi_with_coverage.py
import atexit
import sys
import coverage
cov = coverage.coverage()
cov.start()

from wsgi import application  # adjust to python module containing your wsgi application


def save_coverage():
    print >> sys.stderr, "saving coverage"
    cov.stop()
    cov.save()

atexit.register(save_coverage)

然后跑 gunicorn -w 1 wsgi_with_coverage:application <other params>

问题是, atexit 如果你杀死了gunicorn进程,例如通过CTRL + C,则不会调用函数。但他们  拜访 SIGHUP,所以如果你这样做 kill -HUP $(cat <gunicorn_pidfile_here>),应保存覆盖率数据(默认为当前目录中的“.coverage”)。

一个可能的警告是,这不适用于多个gunicorn工作者,因为他们都会覆盖“.coverage”文件。如果你绝对需要一个以上的工人,你可以写信给 ".coverage-%d" % os.getpid() (设置文件名 通过 data_file 参数 coverage 构造函数)并使用 combine() 方法 合并各个测量值。

这应该也适用于其他WSGI服务器,具体取决于它们是否允许其工作进程通过其进行清理 atexit 方法。


12
2017-12-19 19:14



SIGHUP建议不太好:)。 Gunicorn在检索SIGHUP时重新加载工作进程。也就是说,收集的覆盖数据确实没有保存,而是被仅在加载时发生的那些事件覆盖。另一方面,发送SIGTER会正确触发atexit处理程序并干净地关闭Gunicorn。 - Jan-Philip Gehrcke
更新。设置 data_suffix=True 在打电话的时候 Coverage 构造函数会自动将机器名和PID添加到coverage文件名中。而不是使用 data_file 如上所述。 - Sean Perry