Как увидеть подробности ошибок Django с Gunicorn?
Я только что развернул проект Django (1.6) с помощью пушки и Nginx.
Кажется, он работает нормально, но у меня есть одна страница, я получаю ошибку HTTP 500, и я не могу найти никаких подробностей об ошибке где-нибудь.
Как я могу получить оружие, чтобы показать мне ошибки?
Здесь все, что я вижу в файле журнала, когда я попал на страницу, давая мне ошибку:
>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/
Здесь мой bash script Я использую, чтобы начать стрельбу:
>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
Дополнительная информация:
Я запускаю/останавливаю пушки с этим init.d script Я скопировал и изменил с помощью sudo service reports start|stop|restart
:
>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
Ответы
Ответ 1
Из вашего комментария я думаю, что это проблема с конфигурацией на вашем сайте django, а не в журнале ружейного оружия, журналы не будут отображаться больше, чем отправить 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,
},
}
}
Прочитайте настройку ведения журнала (он дает очень хорошие объяснения параметров параметров журнала) и изучает файл django/utils/log.py, чтобы настроить django loggin на более подробные сведения о журналах о стрельбе.
Также проверьте этот ответ и , в котором приведены примеры для отправки ошибок журналов непосредственно в файл. И рассмотрите возможность использования Sentry для обработки ошибок журнала, а также Рекомендовано ребятами из django.
Надеюсь, что это поможет.
Ответ 2
1. отправка ошибок на консоль
Это loggers
, которые используют mail_admins
по умолчанию (см. django/utils/log.py
):
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'django.security': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
вам нужно будет изменить обработчики, чтобы перейти к console
, чтобы он отображался в вашем журнале стрельбы, а не отправлял сообщения с помощью 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, то ваш вопрос является дубликатом:
Как вы регистрируете ошибки сервера на сайтах django
Ответ 3
Самое простое решение - настроить переменную ADMINS с адресами электронной почты людей, которые должны получать уведомления об ошибках,
Когда DEBUG = False и представление вызывает исключение, Django отправит эти люди с полной информацией об исключениях.
settings.py
ADMINS = (('John', '[email protected]'), ('Mary', '[email protected]'))
# or only ADMINS = (('John', '[email protected]'),)
Возможно, вам также нужны EMAIL_HOST и EMAIL_PORT, если правильный SMTP-сервер не является localhost
на порту 25
. Это простое решение достаточно хорошо для пробной производственной деятельности, в противном случае оно может привести к появлению слишком большого количества электронных писем.
Ответ 4
Краткий ответ:
При следующей конфигурации ведения журнала ваши ошибки начнут отображаться в выходном файле Gunicorn (undaemonized) или на сервере запуска, даже если DEBUG - False. Они всегда должны появляться, когда 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,
},
}
}
Если вы хотите увидеть ошибки Django в журнале ошибок пушки, запустите gunicorn с -capture-output.
http://docs.gunicorn.org/en/stable/settings.html#capture-output
Длинный ответ
При регистрации: есть два путаницы:
- Если
runserver
обеспечивает лучший журнал, чем gunicorn
- Обеспечивает ли
settings.DEBUG=True
лучший журнал, чем settings.DEBUG=False
Любая запись журнала, которую вы видите с помощью сервера запуска, также видна с помощью 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
запись журнала регистрации в обработчики console
и mail_admins
.
-
Обработчик console
имеет на нем фильтр require_debug_true
. Когда settings.DEBUG имеет значение True, тогда обработчик console
отправляет/распечатывает журнал в потоке (из-за logging.StreamHandler
).
Когда settings.DEBUG является False, обработчик console
игнорирует сообщение журнала, отправленное ему журналом django
.
Если вы хотите, чтобы журналы были напечатаны с помощью DEBUG = False, добавьте handler
и сделайте logger 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',
},
Вы можете увидеть весь фрагмент в коротком ответе.
При этом журналы будут печататься в потоке, независимо от того, используете ли вы серверы или пушки.
Если вы хотите, чтобы журналы отображались в журнале ошибок стрельбы, вам нужно запустить gunicorn с -capture-output.