4 декабря 2012 г. Django Jira Python Flask Sentry

Агрегирование исключений и логов при помощи Sentry

Это агрегатор "исключений", который делится на две части, серверную и клиентскую. На сервере будут агрегироваться исключения и можно будет производить поиск и фильтрацию и т.д. Клиентская сторона просто посылает на сервер "исключения" и всё.

Делает эту клевую штуку небезызвестный David Cramer и команда DISQUS.

Умеет рисовать графики событий по возникшим "исключениям". Для конкретного "исключения" умеет выводить заголовки, куки и прочее, стек с контекстом (а не голый как при получении на почту), окружение пользователя (какой был браузер, ОС и т.п.), данные о авторизованном пользователе (для реквестов), информацию о установленных приложениях и т.п.

Можно добавлять группы ошибок в избранное. А при подключении плагинов можно, к примеру, регистрировать "исключения" в Jira, Assembla и Trello.

Помимо проектов на Python (в частности меня интересует Django и Flask) поддерживается также PHP, Ruby, Node.js, Java, Javascript. Все официальные клиенты работают через raven.

Сам sentry работает на Django +зависимости. В качестве wsgi-сервера использует gunicorn.

Имеет вот такой секси-интерфейс на Twitter bootstrap:

Sentry панель

Текущая версия Sentry 5.0.21

Настройка серверной части

Есть платное хранилище на getsentry.com, где вы сможете хранить свои "исключения", минимальная цена на текущий момент всего $9/mo. То есть вы можете вообще не устанавливать серверную-часть, а сразу перейти к настройке клиентской части. Меня не устраивал этот вариант из-за некоторой паранойи у проекта, если у вашего проекта нет такого, то конечно проще арендовать sentry-сервер.

Итак, приступим к установке и настройки серверной части! Входим на сервер и устанавливаем Sentry, а также генерируем конфигурационный файл:

virtualenv --no-site-packages --distribute /var/www/sentry
source /var/www/sentry/bin/activate
pip install sentry
sentry init /etc/sentry.conf

Далее указываем нужный бекенд (секция ENGINE в DATABASES) для хранения данных о ошибках, лично я предпочитаю MySQL:

emacs /etc/sentry.conf
# Укажите настройки для подключения к БД
DATABASES = {
    'default': {
        # You can swap out the engine for SQLite easily by changing this value
        # to ``django.db.backends.sqlite3`` or to PostgreSQL with
        # ``django.db.backends.postgresql_psycopg2``
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'sentry',
        'USER': 'sentry',
        'PASSWORD': '<password>',
        'HOST': '',
        'PORT': '',
    }
}

...

# Установите в False чтобы требовать авторизацию
SENTRY_PUBLIC = False

...

# Укажите URL по которому будет находиться ваш Sentry
# SENTRY_URL_PREFIX = 'http://www.example.org/sentry'
SENTRY_URL_PREFIX = "http://sentry.example.org"

Доустанавливаем MySQL-python:

pip install MySQL-python

Подсоединяемся к нашему mysql-server:

$ mysql -uroot -p
mysql> CREATE DATABASE sentry CHARSET utf8 COLLATE utf8_general_ci;
mysql> SELECT password('<PASSWORD>');           
mysql> GRANT USAGE ON sentry.* TO 'sentry'@'localhost' IDENTIFIED BY PASSWORD '<PASSWORD_HASH>';
mysql> GRANT ALL PRIVILEGES ON `sentry`.* TO 'sentry'@'localhost';

Настраиваем проксирование через Nginx:

server {
    listen 80;
    server_name sentry.example.org;
    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;
    }
}

Теперь создаем конфигурационный файл для supervisor:

[program:sentry]
directory=/var/www/sentry
command=/var/www/sentry/bin/sentry --config=/etc/sentry.conf start http
autostart=true
autorestart=true
redirect_stderr=true

И запускаем вебсервер:

sudo supervisorctl start sentry
sudo nginx -s reload

Если по каким-то причинам вы не используете supervisor, то запускать Sentry надо так:

sentry --config=/etc/sentry.conf start

Остальное можно прочитать в документации, а про запуск Sentry читать в этом разделе документации.

Добавляем суперпользователя

Выполните и введите имя, пароль, почту, вообщем как обычно для Django-проекта:

sentry --config=/etc/sentry.conf createsuperuser
Если у вас возникла вот такая ошибка:
Traceback (most recent call last):
...
TypeError: decode() argument 1 must be string, not None

Тогда установите язык в консоли и выполните снова createsuperuser:
export LANG="ru_RU.UTF-8"
sentry --config=/etc/sentry.conf createsuperuser

Добавление новых пользователей осуществляется в два этапа, сначала в админке http://sentry.example.org/admin/auth/user/ создаете пользователя, потом добавляете его в настройках проекта.

Настройки на стороне клиента

Так как у меня Django-проект, то я приведу способ настройки для Django 1.4.2. Авторизуйтесь по адресу http://sentry.example.org/, там вас попросят ввести "имя проекта" и "имя вашей команды". После чего произойдет редирект на страницу "документации по настройке клиента для вашего проекта".

Сначала устанавливаем raven (клиент для Sentry):

pip install raven

Документация по настройке raven и Django тут.

Указываем в <project>/settings.py (точнее в local_settings.py) вашего проекта следующие настройки:

# Этот DSN вы получите на странице "документации по настройке клиента для вашего проекта"
SENTRY_DSN = 'http://<PUBLIC_KEY>:<SECRET_KEY>@sentry.example.org/2'

# Добавьте raven в INSTALLED_APPS
INSTALLED_APPS = (
    # ...
    'raven.contrib.django',
)

# Теперь настроим LOGGING
LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'root': {
        'level': 'WARNING',
        'handlers': ['sentry'],
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
    },
    'handlers': {
        'sentry': {
            'level': 'ERROR',
            'class': 'raven.contrib.django.handlers.SentryHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'django.db.backends': {
            'level': 'ERROR',
            'handlers': ['console'],
            'propagate': False,
        },
        'raven': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False,
        },
        'sentry.errors': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False,
        },
    }
}

Оберните WSGIHandler в Sentry, файл <project>/wsgi.py:

from django.core.handlers import wsgi
from raven.contrib.django.middleware.wsgi import Sentry
application = Sentry(wsgi.WSGIHandler())

Пример uWSGI-конфига, файл <project>/uwsgi/production.ini:

[uwsgi]
chdir=/path/to/<project>
pidfile=/var/run/<project>/uwsgi.pid
socket=/var/run/<project>/uwsgi.sock
chmod-socket=777
virtualenv=venv
pythonpath=.
pythonpath=<project>
module=<project>.wsgi:application
env=DJANGO_SETTINGS_MODULE=<project>.settings
master=true
processes=10
harakiri=30
buffer-size=32768
procname-prefix=<project>_

Это собственно всё, Sentry решил проблему со сбором "исключений" и предоставил удобный интерфейс для работы с ними! Рекоммендую воспользоваться этим замечательным инструментом!

Комментарии

Про минусы забыл написать :)

Пока рано, но ты можешь привести свои пункты :)

Уже месяц хочу попробовать но все руки не доходят._)

Пункт один:

Делает эту клевую штуку небезызвестный David Cramer и команда DISQUS.

А то раньше я думал - "ну в своем уме люди, которые сервис комментариев делают на джанге?", а потом "ну в своем уме люди, которые делают на джанге хранилище логов?". А теперь всё сошлось! Жду от этих ребят: чат на джанге, xmpp-сервер на джанге, мониторинг на джанге, видеостриминг на джанге и т.д.

Есть название у болезни, когда пациент одним инструментом делает всё? Ну типа - закручивает шурупы отверткой, забивает гвозди отверткой, ест отверткой.
Одни пишут эрланг на си++, другие пишут на руби, то что на скриптовом языке бесперспективно, третьи на эрланге пытаются сделать джангу. Что это за мода?

А если по существу:
1. это SPOF, без рецептов по распределению
2. это избыточность (ну nginx+uwsgi+django(с роутингом, с прослойками, с сигналами, с ORM)+RDB для того чтобы лог записать)
3. это низкая производительность (как следствие пункта 2).
4. отсутствие аналитики (понятно, что можно выгрузить, или плагин написать, но из коробки ноль)

Это просто коллектор логов. На питоновском MVC-фреймворке. С SQL-базой. Без аналитики.

Да, и у меня ощущение, что это правильно делать на riak или couchDB(couchApp).

Да, django тут невписывается. А вообще я считаю надо всегда заниматься чем-то одним, одни делают коллекторы и хранилище, другие веб-интерфесы, графики и аналитику

Я уже писал про настройку UDP в Sentry, но сам постоянно забываю использовать внешний интерфейс в SENTRY_UDP_HOST:

SENTRY_UDP_HOST = '198.51.100.1'  # Внешний IP-адрес вашего сетевого интерфейса
SENTRY_UDP_PORT = 9091

Проверять идут ли логи по UDP можно так:

tcpdump -i eth0 'ip proto \udp'

И в соседней консоли:

./manage.py shell
>>> import logging
>>> log = logging.getLogger('Test')
>>> log.error('Test error!')

ps. вообщем это я для себя записал, не обращайте внимание :-)

Оставьте свой комментарий

Markdown