如何使用 Gunicorn 查看 Django 错误的详细信息?
Posted
技术标签:
【中文标题】如何使用 Gunicorn 查看 Django 错误的详细信息?【英文标题】:How to see details of Django errors with Gunicorn? 【发布时间】:2014-03-23 12:43:34 【问题描述】:我刚刚使用 gunicorn 和 nginx 部署了我的 Django (1.6) 项目。
它似乎工作正常,但我有一页是我收到 HTTP 500 错误,我无法在任何地方找到有关该错误的任何详细信息。
如何让 gunicorn 向我显示错误?
这是我当前在日志文件中看到的所有内容,当我点击页面时出现错误:
>tail gunicorn.errors
2014-02-21 14:41:02 [22676] [INFO] Listening at: unix:/opt/djangoprojects/reports/bin/gunicorn.sock (22676)
2014-02-21 14:41:02 [22676] [INFO] Using worker: sync
2014-02-21 14:41:02 [22689] [INFO] Booting worker with pid: 22689
...
2014-02-21 19:41:10 [22691] [DEBUG] GET /reports/2/
这是我用来启动 gunicorn 的 bash 脚本:
>cat gunicorn_start
#!/bin/bash
NAME="reports" # Name of the application
DJANGODIR=/opt/djangoprojects/reports # Django project directory
SOCKFILE=/opt/djangoprojects/reports/bin/gunicorn.sock # we will communicte using this unix socket
USER=reportsuser # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=4 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=reports.settings # which settings file should Django use
DJANGO_WSGI_MODULE=reports.wsgi # WSGI module name
#echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source pythonenv/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec gunicorn $DJANGO_WSGI_MODULE:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--log-level=debug \
--bind=unix:$SOCKFILE \
--error-logfile /opt/djangoprojects/reports/bin/gunicorn.errors \
--log-file /opt/djangoprojects/reports/bin/gunicorn.errors
更多信息:
我正在使用我使用 sudo service reports start|stop|restart
复制和修改的这个 init.d 脚本启动/停止 gunicorn:
>cat /etc/init.d/reports
#!/bin/sh
### BEGIN INIT INFO
# Provides: django_gunicorn
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts django_unicorn reports at boot time.
# Description: Starts django_unicorn reports at boot time.
### END INIT INFO
name=`basename $0`
dir="/opt/djangoprojects/reports"
cmd="$dir/bin/gunicorn_start"
pid_file="/var/run/$name.pid"
log_file="$dir/bin/reports.log"
get_pid()
cat "$pid_file"
is_running()
[ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
case "$1" in
start)
if is_running; then
echo "Already running"
else
echo -n "Starting $name... "
cd "$dir"
#sudo -u "$user" $cmd &>> "$log_file"
$cmd &>> "$log_file" &
echo $! > "$pid_file"
if ! is_running; then
echo "Unable to start; see $log_file"
exit 1
else
echo "[STARTED]"
fi
fi
;;
stop)
if is_running; then
echo -n "Stopping $name... "
kill `get_pid`
for i in 1..10
do
if ! is_running; then
break
fi
echo -n "."
sleep 1
done
echo
if is_running; then
echo "Not stopped; may still be shutting down or shutdown may have failed"
exit 1
else
echo "[STOPPED]"
if [ -f "$pid_file" ]; then
rm "$pid_file"
fi
fi
else
echo "Not running"
fi
;;
restart)
$0 stop
if is_running; then
echo "Unable to stop, will not attempt to start"
exit 1
fi
$0 start
;;
status)
if is_running; then
echo "[RUNNING]"
else
echo "[STOPPED]"
exit 1
fi
;;
*)
echo "Usage: $0 start|stop|restart|status"
exit 1
;;
esac
exit 0
【问题讨论】:
设置 django 设置DEBUG
为 True,然后重新加载,它应该会显示更多的错误细节
好的,我试过了,我确实在页面上看到了有帮助的错误。但我正在寻找一个更通用的解决方案,这是一个生产环境,所以我不能真正离开 debug=True 。它似乎也无助于在 gunicorn 日志文件中显示错误。
【参考方案1】:
在 Heroku 上使用 gunicorn 20.1 运行 Django 3.8,我遇到了应用程序错误未显示在 Papertrail 日志中的问题。
要解决这个问题,我只需将 Django 文档中的 minimal recommended logging configuration 添加到 settings.py:
LOGGING =
'version': 1,
'disable_existing_loggers': False,
'handlers':
'console':
'class': 'logging.StreamHandler',
,
,
'root':
'handlers': ['console'],
'level': 'WARNING',
,
这是必要的,因为在生产中的Django's default logging configuration 中(当DEBUG
是False
时)django 记录器将消息发送到AdminEmailHandler
,而不是控制台。
我在 Procfile 中使用 web: gunicorn my_project.wsgi
启动 gunicorn,我不需要更改它(即我不需要使用 --capture-output
或 --enable-stdio-inheritance
)。
【讨论】:
【参考方案2】:此配置对我有用。使用 gunicorn 命令添加 --capture-output --enable-stdio-inheritance
,如下所示。
/home/ubuntu/inside-env/bin/gunicorn --access-logfile /var/log/access_file_g.log --error-logfile /var/log/error_file_g.log --capture-output --enable-stdio-inheritance --workers 3 --bind unix:/home/ubuntu/path-to-project/webapp.sock project.wsgi:application
使用此设置,请以这种方式启用日志记录
import logging
logging.basicConfig(level='DEBUG')
logging.info('hello world')
这样您也可以看到应用程序中的错误。
【讨论】:
被低估的答案,这就是我一直在寻找的东西。谢谢! 非常感谢,伙计。这对我来说很完美。【参考方案3】:简答:
使用以下日志记录配置,即使 DEBUG 为 False,您的错误也会开始显示在 Gunicorn 输出(未后台处理)或运行服务器中。当 DEBUG 为 True 时,它们无论如何都应该出现。
LOGGING =
'version': 1,
'disable_existing_loggers': False,
'filters':
'require_debug_false':
'()': 'django.utils.log.RequireDebugFalse',
,
'require_debug_true':
'()': 'django.utils.log.RequireDebugTrue',
,
,
'formatters':
'django.server':
'()': 'django.utils.log.ServerFormatter',
'format': '[%(server_time)s] %(message)s',
,
'handlers':
'console':
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
,
# Custom handler which we will use with logger 'django'.
# We want errors/warnings to be logged when DEBUG=False
'console_on_not_debug':
'level': 'WARNING',
'filters': ['require_debug_false'],
'class': 'logging.StreamHandler',
,
'django.server':
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'django.server',
,
'mail_admins':
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
,
'loggers':
'django':
'handlers': ['console', 'mail_admins', 'console_on_not_debug'],
'level': 'INFO',
,
'django.server':
'handlers': ['django.server'],
'level': 'INFO',
'propagate': False,
,
如果您想在 gunicorn 错误日志中查看 Django 错误,请使用 --capture-output 运行 gunicorn。
http://docs.gunicorn.org/en/stable/settings.html#capture-output
长答案
记录时涉及到两个混淆:
runserver
是否提供比gunicorn
更好的日志
settings.DEBUG=True
是否提供比settings.DEBUG=False
更好的日志
只要您有适当的日志配置,您在 runserver 中看到的任何日志记录也可以在 Gunicorn 中看到。
只要您有适当的日志记录配置,您在 DEBUG=True 时看到的任何日志记录都可以在 DEBUG=False 时看到。
您可以在以下位置查看默认的 Django 日志记录配置:
https://github.com/django/django/blob/1.10.8/django/utils/log.py#L18
看起来像:(我已经删除了与此答案无关的部分)
DEFAULT_LOGGING =
'version': 1,
'disable_existing_loggers': False,
'filters':
'require_debug_false':
'()': 'django.utils.log.RequireDebugFalse',
,
'require_debug_true':
'()': 'django.utils.log.RequireDebugTrue',
,
,
'handlers':
'console':
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
,
'mail_admins':
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
,
'loggers':
'django':
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
,
这句话是:
将django
logger 日志记录发送到处理程序console
和mail_admins
。
处理程序console
上有一个过滤器require_debug_true
。当 settings.DEBUG 为 True 时,处理程序 console
在 Stream 上发送/打印日志(因为 logging.StreamHandler
)。
当 settings.DEBUG 为 False 时,处理程序 console
会忽略 logger django
发送给它的日志消息。
如果您也希望使用 DEBUG=False 打印日志,请添加 handler
并使记录器 django
使用它。
处理程序看起来像:
'console_on_not_debug':
'level': 'WARNING',
'filters': ['require_debug_false'],
'class': 'logging.StreamHandler',
,
将此处理程序与记录器django
一起使用:
'django':
'handlers': ['console', 'mail_admins', 'console_on_not_debug'],
'level': 'INFO',
,
您可以在简短的回答中看到整个 sn-p。
这样,无论您使用的是 runserver 还是 gunicorn,日志都将打印在流上。
如果您希望日志显示在 gunicorn 错误日志中,则需要使用 --capture-output 运行 gunicorn。
【讨论】:
【参考方案4】:1。向控制台发送错误
这些是默认使用mail_admins
的loggers
(参见django/utils/log.py
):
'django.request':
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
,
'django.security':
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
,
您需要更改处理程序以转到console
,以便它出现在您的gunicorn 日志中,而不是使用mail_admins
发送电子邮件。请注意,它不像DEBUG=True
那样健谈。
'loggers':
'django':
'level': 'ERROR',
'handlers': ['console'],
,
2。通过mail_admins
发送错误
同样基于配置日志,显式创建一个调用mail_admins
的处理程序;例如基于django/utils/log.py
:
'handlers':
'mail_admins':
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler'
,
,
'loggers':
'django':
'handlers': ['mail_admins'],
,
这需要您设置电子邮件相关的settings
。
3。其他解决方案
如果您不是在寻找解决方案 #1,那么您的问题与以下内容重复: How do you log server errors on django sites
【讨论】:
【参考方案5】:最简单的解决方案是将变量 ADMINS 配置为应收到错误通知的人员的电子邮件地址。 当 DEBUG=False 并且视图引发异常时,Django 将通过电子邮件向这些人发送完整的异常信息。
settings.py
ADMINS = (('John', 'john@example.com'), ('Mary', 'mary@example.com'))
# or only ADMINS = (('John', 'john@example.com'),)
如果正确的 SMTP 服务器不是端口 25
上的 localhost
,也许您还需要 EMAIL_HOST 和 EMAIL_PORT。这个简单的解决方案足以进行试产操作,否则会突然产生过多的电子邮件。
【讨论】:
【参考方案6】:根据您的评论,我认为这是您的 django 站点中的配置问题,而不是 gunicorn 日志的问题,日志不会显示超过 django 发送给它的内容。
这是一个示例,说明如何配置 django 设置以将日志发送到您的文件(而不是默认通过电子邮件将其发送给管理员):
LOGGING =
'version': 1,
'disable_existing_loggers': True,
'formatters':
'verbose':
'format': '%(asctime)s %(levelname)s [%(name)s:%(lineno)s] %(module)s %(process)d %(thread)d %(message)s'
,
'handlers':
'gunicorn':
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'formatter': 'verbose',
'filename': '/opt/djangoprojects/reports/bin/gunicorn.errors',
'maxBytes': 1024 * 1024 * 100, # 100 mb
,
'loggers':
'gunicorn.errors':
'level': 'DEBUG',
'handlers': ['gunicorn'],
'propagate': True,
,
阅读configuring logging(它对日志设置选项提供了很好的解释)并研究文件django/utils/log.py 以配置django loggin 以在gunicorn 日志上显示更详细。
还要检查this answer 和this,它们提供了将日志错误直接发送到文件的设置示例。并考虑使用Sentry 来处理日志错误,就像 django 人的recomended 一样。
希望这会有所帮助。
【讨论】:
哦,所以你是说新版本的 Django 默认不记录错误?在运行内置 Django 服务器时,我一直在看到回溯,所以我假设通过 Gunicorn 运行时我会得到相同的输出。 默认 ERROR 和 CRITICAL 级别通过电子邮件发送给管理员,我认为内置的 Django 开发服务器不使用此功能,因此它会在控制台中显示回溯以上是关于如何使用 Gunicorn 查看 Django 错误的详细信息?的主要内容,如果未能解决你的问题,请参考以下文章
使用 gunicorn 时如何设置 django 测试服务器?
如何使用 gunicorn 为 django 配置 nginx?
如何将新的 django 应用程序添加到已部署的 django 项目(使用 nginx、gunicorn)?
如何调试使用 whitenoise、gunicorn 和 heroku 服务的 django 静态文件?