Оригинальная статья "" рассказывает о приложении Sentry которая заменяет стандартный механизм сообщений об ошибках которые приходят на почту в случае каких-то проблем с Django-проектом.
Я люблю получать сообщения по e-mail, особенно, если они начинаются со слов “[Django] Error…”. Готов поспорить, что 95% всех Django-проектов на промышленных площадках использует для слежения за ошибками именно электронную почту. У нас, в , мы решили, что с этим надо что-то делать, потому что мы теряли сообщения об ошибках в наших почтовых ящиках и часто не знали, что исправлено, а что нет.
К счастью, есть отличный инструментальный пакет, который называется , и который создали люди из - этот пакет позволяет организовать централизованное журналирование ошибок.
Позвольте, я попытаюсь "продать" вам этот пакет, просто перечислив некоторые его характеристики из :
- Интеллектуальная группировка сообщений об ошибках.
- Идентификация ошибок серверов, функций и URL.
- Направление потока ошибок в список по мере их возникновения, без необходимости в ручном обновлении списка.
В данной статье я покажу, как создать и настроить сервер журналирования, и как испытать его на вашем локальном Django-проекте. На моем сервере работает FreeBSD, но вы можете использовать мои инструкции для любой *Nix-системы.
Журналирование через UDP
Sentry использует соединение по протоколу TCP (HTTP). Это не очень здорово для журналирования, потому что этот протокол работает медленно из-за своей "гарантированной доставки". Для не слишком критичных приложений, таких, как журналирование, лучше подходит соединение по UDP. В данный момент последняя стабильная версия Sentry не поддерживает UDP. Однако для тех, кому важна производительность, версия с поддержкой UDP уже в работе и . Учтите все же, что для потокового управления журналами лучше подходят другие инструменты, такие, как .
Установка Sentry
Вначале добудьте себе сервер. Я взял свой на но вы можете с таким же успехом получить его с , или . Сделайте основные настройки, заведите пользователей и сконфигурируйте доступ по SSH. Если вы решили использовать FreeBSD — а это хороший выбор — просто следуйте моему руководству “”.
Нашей базой данных будет PostgreSQL. Я не буду описывать процесс ее установки, поскольку это уже описано другими. Вот руководства для , и :
Debian
Ubuntu
FreeBSD
Сервер PostgreSQL установлен? Хорошо! Давайте создадим базу данных для Sentry:
# Переключиться на пользователя pgsql
# Для Debian/Ubuntu это postgres
sudo su - pgsql
# Создать пользователя, ответить 'n' на все вопросы о роли
createuser -P pg_sentry
# Создать базу данных
createdb db_sentry -O pg_sentry --encoding=UNICODE
Мы установим в виртуальную среду при помощи . Чтобы установить эту среду, мы используем менеджер пакетов Python: .
На FreeBSD перейдите в каталог /usr/ports/devel/py-pip, и выполните команду make install clean от имени root. Для других систем прочтите . Pip позволяет легко установить, и среду “virtualenv”, и ее вспомогательную утилиту “virtualenvwrapper”. Выполните следующие команды от имени root:
pip install virtualenv
pip install virtualenvwrapper
Virtualenvwrapper требует правильной настройки среды окружения. Вот мои настройки из .zshrc, помещающие все виртуальные среды в каталог ~/.virtualenvs. Если у вас Bash, добавьте эти настройки в ваш .bashrc.
export WORKON_HOME=$HOME/.virtualenvs
# Проверить, установлена ли virtualenvwrapper, если да, запустить!
# Как видите, моя virtualenvwrapper находится в
# `/usr/local/bin/` но у вас это может быть `/usr/bin/`
if [ -e "/usr/local/bin/virtualenvwrapper.sh" ]; then
source /usr/local/bin/virtualenvwrapper.sh
fi
Выйдите из системы и зайдите снова, чтобы изменения вступили в силу. Если все прошло хорошо, вы получите сообщения об установке скриптов в каталоге .virtualenvs. Теперь все готово для создания виртуальной среды sentry:
mkdir ~/sentry
mkvirtualenv sentry
Ваша виртуальная среда будет активирована, когда вы вызовете скрипт mkvirtualenv, но не забудьте активировать ее снова при помощи workon sentry в следующий раз, когда будете работать с проектом sentry. Все теперь готово, пора установить Sentry. Я люблю работать с файлом требований (requirements) и с pip, поэтому давайте создадим файл requirements.txt в нашем каталоге sentry и заполним его требованиями для Sentry.
touch ~/sentry/requirements.txt
echo "Django==1.3.1" >> ~/sentry/requirements.txt
echo "sentry==2.0.0-RC6" >> ~/sentry/requirements.txt
echo "psycopg2==2.4.2" >> ~/sentry/requirements.txt
Вам не требуется добавлять в файл требований Django, поскольку Sentry позаботится обо всех зависимостях. Но нам нужна последняя стабильная версия Django, поэтому мы поместили сюда это требование.
Теперь, выполним установку при помощи команды pip install -r ~/sentry/requirements.txt. Будет установлено множество библиотек, но в результате вы должны увидеть:
Successfully installed Django sentry django-paging django-indexer django-templatetag-sugar raven python-daemon eventlet South kombu django-kombu simplejson lockfile greenlet anyjson amqplib psycopg2 Cleaning up…"
Нам нужно инициализировать конфигурацию базы для Sentry. Следующая команда создаст файл конфигурации в каталоге sentry :
sentry init ~/sentry/sentry.conf.py
Отредактируем конфигурацию. У меня получилось, в итоге, следующее:
import os.path
from sentry.conf.server import *
ROOT = os.path.dirname(__file__)
DATABASES = {
'default': {
# Используется база данных PostgreSQL, которую мы создали ранее
'ENGINE': "django.db.backends.postgresql_psycopg2",
'NAME': "db_sentry",
'USER': 'pg_sentry',
'PASSWORD': 'your_password',
'HOST': 'localhost',
}
}
SENTRY_KEY = "SOME_KEY"
# Установите позднее в false, чтобы требовалась аутентификация
SENTRY_PUBLIC = True
SENTRY_WEB_HOST = '0.0.0.0'
SENTRY_WEB_PORT = 9000
Обратите внимание, мы сохранили для SENTRY_PUBLIC значение True. Это сделано для того, чтобы упростить тестирование в дальнейшем. При переходе к реальной работе нужно будет вернуть значение False. Остальные настройки говорят сами за себя.
Довольно неудобно будет указывать местонахождение конфигурации Sentry при выполнении каждой команды. Поскольку Sentry ищет свою конфигурацию в каталоге ~/.sentry/sentry.conf.py, давайте добавим туда символическую ссылку.
mkdir ~/.sentry
ln -s ~/sentry/sentry.conf.py ~/.sentry/sentry.conf.py
Прежде чем запускать Sentry, нужно еще инициализировать базу данных:
cd ~/sentry
sentry upgrade
Теперь мы можем запустить сервер следующей командой:
cd ~/sentry
sentry start
Если порт у вас открыт, то вы можете теперь зайти на веб-сервер по порту 9000, например, http://example.com:9000
Nginx
Не очень удобно каждый раз заходить на сервер по порту “9000”, а в то же время имеется мощный сервер, хорошо подходящий для работы со статическим контентом. Давайте установим Nginx и используем его в качестве прокси для Sentry. На FreeBSD установить Nginx можно, перейдя в каталог /usr/ports/www/nginx и выполнив команду install clean от имени root. Добавьте строку nginx_enable="YES" в файл /etc/rc.conf, чтобы Nginx стартовал при загрузке системы. Запустите сервер при помощи следующей команды от имени root:
/usr/local/etc/rc.d/nginx start
Nginx для Ubuntu или Debian устанавливается также просто, достаточно заглянуть в одно из руководств в . Далее приведена конфигурация, которую я использовал для настройки Nginx, если вы замените "example" своими настройками, все должно заработать.
Помните, однако, что Ubuntu и Debian работают с каталогом sites_enabled ,который они включают в основную конфигурацию. Вам в этом случае необходимо вставить раздел server { … } внутрь того файла. Например, /etc/nginx/sites-enabled/sentry.conf.
# На Ubuntu/Debian это, обычно, www-data
# На FreeBSD - www
user www www;
# Рабочие процессы, по 1 на процессор
worker_processes 2;
error_log /var/log/nginx-error.log;
# Оптимизация
worker_rlimit_nofile 8192;
events {
worker_connections 8000;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx-access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
keepalive_timeout 20;
# Оптимизация доступа к файлу
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
# Gzipping
gzip on;
gzip_http_version 1.0;
gzip_comp_level 5;
gzip_proxied any;
gzip_min_length 512;
gzip_buffers 4 8k;
gzip_vary on;
gzip_types
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
# Некоторые версии IE не понимают сжатие на некоторых типах mime
# поэтому, для них, отключим
gzip_disable "MSIE [1-6]\.";
server {
listen 80;
# Заменить именем своего хоста
server_name sentry.example.com;
access_log /home/example/sentry/logs/nginx-access.log;
# Задать кодировку
charset utf-8;
# Разрешить Nginx работать со статическими данными. Убедитесь,
# что указали их верное местоположение
location /_static {
alias /home/example/.virtualenvs/sentry/lib/python2.7/site-packages/sentry/static/;
expires 14d;
access_log off;
}
# Прокси для Sentry
location / {
proxy_pass http://localhost:9000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Перезапустите Nginx и вернитесь в каталог Sentry. Запустите Sentry следующим образом:
cd ~/sentry
sentry start --config=sentry.conf.py
Когда вы теперь зайдете на сервер своим браузером, то увидите страницу Sentry без необходимости добавлять номер порта - ":9000". Но вам вряд ли захочется запускать Sentry каждый раз вручную, поэтому давайте установим “Supervisor” для контроля над процессом.
Супервизор
Для установки супервизора в FreeBSD достаточно перейти в каталог /usr/ports/sysutils/py-supervisor и выполнить команду install clean от имени root. Для того, чтобы супервизор запускался при загрузке, добавьте в /etc/rc.conf следующую строку:
supervisord_enable="YES"
Запустите теперь супервизор командой от имени root:
/usr/local/etc/rc.d/supervisord start
Если у вас используется система, отличная от FreeBSD, следуйте указаниям из документации .
Для слежения за процессом Sentry при помощи Supervisor, добавьте следующие строки в файл supervisord.conf. На FreeBSD он расположен в каталоге /usr/local/etc/supervisord.conf. (Конечно, снова замените "example" на имя вашего пользователя, выполняющего Sentry):
[program:sentry]
directory=/home/example/sentry
command=/home/example/.virtualenvs/sentry/bin/sentry start --config=/home/example/sentry/sentry.conf.py
user=example
umask=022
autostart=True
autorestart=True
redirect_stderr=True
Для того чтобы супервизор смог найти этот новый раздел, нам необходимо перезагрузить его конфигурацию командой supervisorctl reload от имени root. Проверьте, все ли работает правильно - для этого перезапустите свой VPS-сервер. Будем исходить из того, что все прошло гладко (а если нет, то из того, что вы хороший отладчик). Последний шаг состоит в том, чтобы защитить Sentry при помощи авторизации. Добавьте суперпользователя следующими командами:
workon sentry
cd ~/sentry
sentry manage createsuperuser --config=sentry.conf.py
Отредактируйте ваш файл sentry.conf.py и задайте:
SENTRY_PUBLIC = False
Перезапустите Sentry, чтобы новая конфигурация вступила в силу (команда supervisorctl restart sentry от имени root). Теперь откройте свой веб-сайт Sentry - все работает!
Интеграция с вашим Django-проектом
Подключение вашего Django-проекта к Sentry требует наличия Sentry-клиента. Для Python таким клиентом является . Найдите или создайте тот Django-проект, для которого вы хотите использовать Raven. Вначале установите raven командой pip install raven --upgrade, затем откройте файл settings.py вашего Django-проекта.
Затем следуйте инструкциям из документации Raven . Переменную SENTRY_KEY на этом сервере можно найти в файле sentry.conf.py, а SENTRY_SERVERS нужно присвоить имя вашего сервера.
Если вы настроили LOGGING в соответствии с описанной конфигурацией, вы можете проверить систему, добавив в нее одно из ваших представлений "view", и открыв его в браузере. Вы должны увидеть сообщение об ошибке без ручного обновления сервера Sentry.
import logging
# Получить экземпляр logger
logger = logging.getLogger(__name__)
logger.error('There was some crazy error',
exc_info=True,
extra={'request': request,})
Собственно журналирование
Ваша система централизованного журналирования работает. Самое время объяснить своим сотрудникам, как она устроена! Полезно будет также прочесть , прежде чем выбирать в своем проекте подходящие точки журналирования. Если вам чего-то не хватило в этом руководстве, дайте мне знать твитом или через почту.