Using Sentry to log exceptions and logging messages from Django projects
sentry is something like an logs aggregation application. It can be used to log exceptions and other log messages from Django or other framework/programming languages (including JavaScript). Instead of sending a lot of emails to a project admin Django will send them to Sentry which will aggregate them and present in a readable form. Sentry is actually a Django application that can be launched setup on your local computer - perfect for testing.
In this article I'll show you how to run Sentry on your local computer (basic setup) and how to configure Django and other parts of the Python code for optimal Sentry logging results.
Installing and configuring Sentry
Installation is standard:Under Ubuntu-based system I had to also install Python header files for setproctitle
compilation (dependency of sentry). I've installed libpython-all-dev
and that solved the problem. Note that current Sentry release (0.5.5) is not compatible with Django 1.5 and newer so if you have such version in your system use a virtualenv to install Sentry in it.
As the platform we pick the framework or language we are interested in. In the case of Django we will get a basic setup instruction after we create the project. Presented configuration covers basic exception logging only.
Configuring Django
Install raven at start:RAVEN_CONFIG = {
'dsn': 'YOUR_SENTRY_DSN',
}
Exception logging
Here is our test view:from django.views import generic
class ExceptionView(generic.View):
def get(self, request, **kwargs):
raise ValueError('I don\'t like this value')
exception_view = ExceptionView.as_view()
You can click on the exception title to get more details like the whole exception, stacktrace, Django user data etc.
Logging messages from logging module
Logging module is often use to log some events that did occur, while they shouldn't in general (either in the case of a catch exception or odd result that isn't a critical error for which exception would be suitable). Here is an example usage:
import logging
from django import http
from django.views import generic
logger = logging.getLogger(__name__)
class LoggingView(generic.View):
def get(self, request, **kwargs):
logger.warning("An error")
return http.HttpResponse("ok")
logging_view = LoggingView.as_view()
class InheritingView(LoggingView):
pass
inheriting_view = InheritingView.as_view()
No handlers could be found for logger "myapp.views"
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'root': {
'level': 'DEBUG',
'handlers': ['sentry'],
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
},
'handlers': {
'sentry': {
'level': 'DEBUG',
'class': 'raven.contrib.django.raven_compat.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,
},
},
}
This configuration is described on Sentry documentation. Whats worth checking is that "root" and "sentry" have "DEBUG" log level. They will log everything (usually you would send errors and warnings to sentry, and low important debug or info to some files etc.).
With new LOGGING configuration the logger will log to Sentry:
You may notice that the logged event doesn't contain to much data. There is no request or stacktrace. Python logging supports passing a dictionary under extra argument. Sentry has some extended support for it. If you pass the request object underrequestkey it will log it nicely. If you pass
stackkey set to True it will add a stacktrace and you will be able to tell which of the two test views triggered the logged event (and more).
logger.warning("an error", extra={'request': request, 'stack': True})
Logging from Celery tasks to Sentry
To log exceptions from Celery task we have to add one extra logger to LOGGING:'celery': {
'level': 'WARNING',
'handlers': ['sentry'],
'propagate': False,
},
from celery import task
@task()
def celery_task():
logger = celery_task.get_logger()
logger.warning("celerrrrrrrrrry log")
To use the logging like in the views logging you can set CELERYD_HIJACK_ROOT_LOGGER to False:
Some other Python services may require their own logger. But that's all you need to get a nicely configured Sentry logging.
Comment article