Integrations

The Raven Python module also comes with integration for some commonly used libraries to automatically capture errors from common environments. This means that once you have such an integration configured you typically do not need to report errors manually.

Some integrations allow specifying these in a standard configuration, otherwise they are generally passed upon instantiation of the Sentry client.

Bottle

Bottle is a microframework for Python. Raven supports this framework through the WSGI integration.

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

The first thing you’ll need to do is to disable catchall in your Bottle app:

import bottle

app = bottle.app()
app.catchall = False

Sentry will then act as Middleware:

from raven import Client
from raven.contrib.bottle import Sentry
client = Client('___DSN___')
app = Sentry(app, client)

Usage

Once you’ve configured the Sentry application you need only call run with it:

run(app=app)

If you want to send additional events, a couple of shortcuts are provided on the Bottle request app object.

Capture an arbitrary exception by calling captureException:

try:
    1 / 0
except ZeroDivisionError:
    request.app.sentry.captureException()

Log a generic message with captureMessage:

request.app.sentry.captureMessage('Hello, world!')

Celery

Celery is a distributed task queue system for Python built on AMQP principles. For Celery built-in support by Raven is provided but it requires some manual configuration.

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

To capture errors, you need to register a couple of signals to hijack Celery error handling:

from raven import Client
from raven.contrib.celery import register_signal, register_logger_signal

client = Client('___DSN___')

# register a custom filter to filter out duplicate logs
register_logger_signal(client)

# The register_logger_signal function can also take an optional argument
# `loglevel` which is the level used for the handler created.
# Defaults to `logging.ERROR`
register_logger_signal(client, loglevel=logging.INFO)

# hook into the Celery error handler
register_signal(client)

# The register_signal function can also take an optional argument
# `ignore_expected` which causes exception classes specified in Task.throws
# to be ignored
register_signal(client, ignore_expected=True)

A more complex version to encapsulate behavior:

import celery
import raven
from raven.contrib.celery import register_signal, register_logger_signal

class Celery(celery.Celery):

    def on_configure(self):
        client = raven.Client('___DSN___')

        # register a custom filter to filter out duplicate logs
        register_logger_signal(client)

        # hook into the Celery error handler
        register_signal(client)

app = Celery(__name__)
app.config_from_object('django.conf:settings')

Django

Django versions 1.4 to 2.0 are supported. Since this SDK is being phased out, newer versions of Django are only supported by the new Python SDK.

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

Using the Django integration is as simple as adding raven.contrib.django.raven_compat to your installed apps:

INSTALLED_APPS = (
    'raven.contrib.django.raven_compat',
)

Additional settings for the client are configured using the RAVEN_CONFIG dictionary:

import os
import raven

RAVEN_CONFIG = {
    'dsn': '___DSN___',
    # If you are using git, you can also automatically configure the
    # release based on the git info.
    'release': raven.fetch_git_sha(os.path.abspath(os.pardir)),
}

Once you’ve configured the client, you can test it using the standard Django management interface:

python manage.py raven test

You’ll be referencing the client slightly differently in Django as well:

from raven.contrib.django.raven_compat.models import client

client.captureException()

Using with Raven.js

A Django template tag is provided to render a proper public DSN inside your templates, you must first load raven:

{% load raven %}

Inside your template, you can now use:

<script>Raven.config('{% sentry_public_dsn %}').install()</script>

By default, the DSN is generated in a protocol relative fashion, e.g. //public@example.com/1. If you need a specific protocol, you can override:

{% sentry_public_dsn 'https' %}

See the Raven.js documentation for more information.

Integration with logging

To integrate with the standard library’s logging module, and send all ERROR and above messages to sentry, the following config can be used:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'root': {
        'level': 'WARNING',
        'handlers': ['sentry'],
    },
    'formatters': {
        'verbose': {
            'format': '%(levelname)s  %(asctime)s  %(module)s '
                      '%(process)d  %(thread)d  %(message)s'
        },
    },
    'handlers': {
        'sentry': {
            'level': 'ERROR', # To capture more than ERROR, change to WARNING, INFO, etc.
            'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
            'tags': {'custom-tag': 'x'},
        },
        '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,
        },
    },
}

Usage

Logging usage works the same way as it does outside of Django, with the addition of an optional request key in the extra data:

logger.error('There was some crazy error', exc_info=True, extra={
    # Optionally pass a request and we'll grab any information we can
    'request': request,
})

404 Logging

In certain conditions you may wish to log 404 events to the Sentry server. To do this, you simply need to enable a Django middleware:

# Use ``MIDDLEWARE_CLASSES`` prior to Django 1.10
MIDDLEWARE = (
    'raven.contrib.django.raven_compat.middleware.Sentry404CatchMiddleware',
    ...,
) + MIDDLEWARE

It is recommended to put the middleware at the top, so that only 404s that bubbled all the way up get logged. Certain middlewares (e.g. flatpages) capture 404s and replace the response.

It is also possible to configure this middleware to ignore 404s on particular pages by defining the IGNORABLE_404_URLS setting as an iterable of regular expression patterns. If any pattern produces a match against the full requested URL (as defined by the regular expression’s search method), then the 404 will not be reported to Sentry.

import re

IGNORABLE_404_URLS = (
    re.compile('/foo'),
)

Message References

Sentry supports sending a message ID to your clients so that they can be tracked easily by your development team. There are two ways to access this information, the first is via the X-Sentry-ID HTTP response header. Adding this is as simple as appending a middleware to your stack:

# Use ``MIDDLEWARE_CLASSES`` prior to Django 1.10
MIDDLEWARE = MIDDLEWARE + (
  # We recommend putting this as high in the chain as possible
  'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware',
  ...,
)

Another alternative method is rendering it within a template. By default, Sentry will attach request.sentry when it catches a Django exception. In our example, we will use this information to modify the default 500.html which is rendered, and show the user a case reference ID. The first step in doing this is creating a custom handler500() in your urls.py file:

from django.conf.urls.defaults import *

from django.views.defaults import page_not_found, server_error
from django.template.response import TemplateResponse

def handler500(request):
    """500 error handler which includes ``request`` in the context.

 Templates: `500.html`
 Context: None
 """

    context = {'request': request}
    template_name = '500.html'  # You need to create a 500.html template.
    return TemplateResponse(request, template_name, context, status=500)

Once we’ve successfully added the request context variable, adding the Sentry reference ID to our 500.html is simple:

<p>You've encountered an error, oh noes!</p>
{% if request.sentry.id %}
    <p>If you need assistance, you may reference this error as
    <strong>{{ request.sentry.id }}</strong>.</p>
{% endif %}

WSGI Middleware

If you are using a WSGI interface to serve your app, you can also apply a middleware which will ensure that you catch errors even at the fundamental level of your Django application:

from raven.contrib.django.raven_compat.middleware.wsgi import Sentry
from django.core.wsgi import get_wsgi_application

application = Sentry(get_wsgi_application())

User Feedback

To enable user feedback for crash reports, start with ensuring the request value is available in your context processors:

TEMPLATE_CONTEXT_PROCESSORS = (
    # ...
    'django.core.context_processors.request',
)

By default Django will render 500.html, so simply drop the following snippet into your template:

<!-- Sentry JS SDK 2.1.+ required -->
<script src="https://cdn.ravenjs.com/2.3.0/raven.min.js"></script>

{% if request.sentry.id %}
  <script>
  Raven.showReportDialog({
    eventId: '{{ request.sentry.id }}',

    // use the public DSN (dont include your secret!)
    dsn: '___PUBLIC_DSN___'
  });
  </script>
{% endif %}

That’s it!

For more details on this feature, see the User Feedback guide.

Additional Settings

SENTRY_CLIENT

In some situations you may wish for a slightly different behavior to how Sentry communicates with your server. For this, Raven allows you to specify a custom client:

SENTRY_CLIENT = 'raven.contrib.django.raven_compat.DjangoClient'
SENTRY_CELERY_LOGLEVEL

If you are also using Celery, there is a handler being automatically registered for you that captures the errors from workers. The default logging level for that handler is logging.ERROR and can be customized using this setting:

SENTRY_CELERY_LOGLEVEL = logging.INFO

Alternatively you can use a similarly named key in RAVEN_CONFIG:

RAVEN_CONFIG = {
    'CELERY_LOGLEVEL': logging.INFO
}
SENTRY_CELERY_IGNORE_EXPECTED

If you are also using Celery, then you can ignore expected exceptions by setting this to True. This will cause exception classes in Task.throws to be ignored.

Caveats

The following things you should keep in mind when using Raven with Django.

Error Handling Middleware

If you already have middleware in place that handles process_exception() you will need to take extra care when using Sentry.

For example, the following middleware would suppress Sentry logging due to it returning a response:

class MyMiddleware(object):
    def process_exception(self, request, exception):
        return HttpResponse('foo')

To work around this, you can either disable your error handling middleware, or add something like the following:

from django.core.signals import got_request_exception

class MyMiddleware(object):
    def process_exception(self, request, exception):
        # Make sure the exception signal is fired for Sentry
        got_request_exception.send(sender=self, request=request)
        return HttpResponse('foo')

Note that this technique may break unit tests using the Django test client (django.test.client.Client) if a view under test generates a Http404 or PermissionDenied exception, because the exceptions won’t be translated into the expected 404 or 403 response codes.

Or, alternatively, you can just enable Sentry responses:

from raven.contrib.django.raven_compat.models import sentry_exception_handler

class MyMiddleware(object):
    def process_exception(self, request, exception):
        # Make sure the exception signal is fired for Sentry
        sentry_exception_handler(request=request)
        return HttpResponse('foo')

Circus

If you are running Django with circus and chaussette you will also need to add a hook to circus to activate Raven:

from django.conf import settings
from django.core.management import call_command

def run_raven(*args, **kwargs):
    """Set up raven for django by running a django command.
 It is necessary because chaussette doesn't run a django command.
 """
    if not settings.configured:
        settings.configure()

    call_command('validate')
    return True

And in your circus configuration:

[socket:dwebapp]
host = 127.0.0.1
port = 8080

[watcher:dwebworker]
cmd = chaussette --fd $(circus.sockets.dwebapp) dproject.wsgi.application
use_sockets = True
numprocesses = 2
hooks.after_start = dproject.hooks.run_raven

Flask

Installation

If you haven’t already, install raven with its explicit Flask dependencies:

pip install raven[flask]

Setup

The first thing you’ll need to do is to initialize Raven under your application:

from raven.contrib.flask import Sentry
sentry = Sentry(app, dsn='___DSN___')

If you don’t specify the dsn value, we will attempt to read it from your environment under the SENTRY_DSN key.

Extended Setup

You can optionally configure logging too:

import logging
from raven.contrib.flask import Sentry
sentry = Sentry(app, logging=True, level=logging.ERROR, \
                logging_exclusions=("logger1", "logger2", ...))

Building applications on the fly? You can use Raven’s init_app hook:

sentry = Sentry(dsn='http://public_key:secret_key@example.com/1')

def create_app():
    app = Flask(__name__)
    sentry.init_app(app)
    return app

You can pass parameters in the init_app hook:

sentry = Sentry()

def create_app():
    app = Flask(__name__)
    sentry.init_app(app, dsn='___DSN___', logging=True,
                    level=logging.ERROR,
                    logging_exclusions=("logger1", "logger2", ...))
    return app

Settings

Additional settings for the client can be configured using SENTRY_CONFIG in your application’s configuration:

class MyConfig(object):
    SENTRY_CONFIG = {
        'dsn': '___DSN___',
        'include_paths': ['myproject'],
        'release': raven.fetch_git_sha(os.path.dirname(__file__)),
    }

If Flask-Login is used by your application (including Flask-Security), user information will be captured when an exception or message is captured. By default, only the id (current_user.get_id()), is_authenticated, and is_anonymous is captured for the user. If you would like additional attributes on the current_user to be captured, you can configure them using SENTRY_USER_ATTRS:

class MyConfig(object):
    SENTRY_USER_ATTRS = ['username', 'first_name', 'last_name', 'email']

email will be captured as sentry.interfaces.User.email, and any additional attributes will be available under sentry.interfaces.User.data

You can specify the types of exceptions that should not be reported by Sentry client in your application by setting the ignore_exceptions configuration value:

class MyExceptionType(Exception):
    def __init__(self, message):
        super(MyExceptionType, self).__init__(message)

app = Flask(__name__)
app.config['SENTRY_CONFIG'] = {
    'ignore_exceptions': [MyExceptionType],
}

Usage

Once you’ve configured the Sentry application it will automatically capture uncaught exceptions within Flask. If you want to send additional events, a couple of shortcuts are provided on the Sentry Flask middleware object.

Capture an arbitrary exception by calling captureException:

try:
    1 / 0
except ZeroDivisionError:
    sentry.captureException()

Log a generic message with captureMessage:

sentry.captureMessage('hello, world!')

Getting The Last Event ID

If possible, the last Sentry event ID is stored in the request context g.sentry_event_id variable. This allow to present the user an error ID if have done a custom error 500 page.

<h2>Error 500</h2>
{% if g.sentry_event_id %}
<p>The error identifier is {{ g.sentry_event_id }}</p>
{% endif %}

User Feedback

To enable user feedback for crash reports just make sure you have a custom 500 error handler and render out a HTML snippet for bringing up the crash dialog:

from flask import Flask, g, render_template
from raven.contrib.flask import Sentry

app = Flask(__name__)
sentry = Sentry(app, dsn='___DSN___')

@app.errorhandler(500)
def internal_server_error(error):
    return render_template('500.html',
        event_id=g.sentry_event_id,
        public_dsn=sentry.client.get_public_dsn('https')
    )

And in the error template (500.html) you can then do this:

<!-- Sentry JS SDK 2.1.+ required -->
<script src="https://cdn.ravenjs.com/2.3.0/raven.min.js"></script>

{% if event_id %}
  <script>
  Raven.showReportDialog({
    eventId: '{{ event_id }}',
    dsn: '{{ public_dsn }}'
  });
  </script>
{% endif %}

That’s it!

For more details on this feature, see the User Feedback guide.

Dealing With Proxies

When your Flask application is behind a proxy such as nginx, Sentry will use the remote address from the proxy, rather than from the actual requesting computer. By using ProxyFix from werkzeug.contrib.fixers the Flask .wsgi_app can be modified to send the actual REMOTE_ADDR along to Sentry.

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

This may also require changes to the proxy configuration to pass the right headers if it isn’t doing so already.

Signals

Raven uses blinker to emit a signal (called logging_configured) after logging has been configured for the client. You may bind to that signal in your application to do any additional configuration to the logging handler SentryHandler.

from raven.contrib.flask import Sentry, logging_configured
from flask import Flask, g, render_template
from raven.contrib.flask import Sentry

app = Flask(__name__)
sentry = Sentry(app, dsn='___DSN___', logging=True)

@logging_configured.connect
def internal_server_error(sender, sentry_handler=None, **kwargs):
    # configure sentry_handler here
    sentry_handler.addFilter(some_filter)

Amazon Web Services Lambda

Installation

To use Sentry with AWS Lambda, you have to install raven as an external dependency. This involves creating a Deployment package and uploading it to AWS.

To install raven into your current project directory:

pip install raven -t /path/to/project-dir

Setup

Create a LambdaClient instance and wrap your lambda handler with the capture_exceptions decorator:

from raven.contrib.awslambda import LambdaClient

client = LambdaClient()

@client.capture_exceptions
def handler(event, context):
    ...
    raise Exception('I will be sent to sentry!')

By default this will report unhandled exceptions and errors to Sentry.

The LambdaClient accepts the same arguments as the regular Client, see Configuring the Client.

The integration was inspired by raven python lambda, another implementation that also integrates with Serverless Framework and has SQS transport support.

Logbook

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

Raven provides a logbook handler which will pipe messages to Sentry.

First you’ll need to configure a handler:

from raven.handlers.logbook import SentryHandler

# Manually specify a client
client = Client(...)
handler = SentryHandler(client)

You can also automatically configure the default client with a DSN:

# Configure the default client
handler = SentryHandler('___DSN___')

Finally, bind your handler to your context:

from raven.handlers.logbook import SentryHandler

client = Client(...)
sentry_handler = SentryHandler(client)
with sentry_handler.applicationbound():
    # everything logged here will go to sentry.
    ...

Logging

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

Sentry supports the ability to directly tie into the logging module. To use it simply add SentryHandler to your logger.

First you’ll need to configure a handler:

from raven.handlers.logging import SentryHandler

# Manually specify a client
client = Client(...)
handler = SentryHandler(client)

You can also automatically configure the default client with a DSN:

# Configure the default client
handler = SentryHandler('___DSN___')

You may want to specify the logging level at this point so you don’t send INFO or DEBUG messages to Sentry:

handler.setLevel(logging.ERROR)

Finally, call the setup_logging() helper function:

from raven.conf import setup_logging

setup_logging(handler)

Another option is to use logging.config.dictConfig:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,

    'formatters': {
        'console': {
            'format': '[%(asctime)s][%(levelname)s] %(name)s '
                      '%(filename)s:%(funcName)s:%(lineno)d | %(message)s',
            'datefmt': '%H:%M:%S',
            },
        },

    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'console'
            },
        'sentry': {
            'level': 'ERROR',
            'class': 'raven.handlers.logging.SentryHandler',
            'dsn': '___DSN___',
            },
        },

    'loggers': {
        '': {
            'handlers': ['console', 'sentry'],
            'level': 'DEBUG',
            'propagate': False,
            },
        'your_app': {
            'level': 'DEBUG',
            'propagate': True,
        },
    }
}

Usage

A recommended pattern in logging is to simply reference the modules name for each logger, so for example, you might at the top of your module define the following:

import logging
logger = logging.getLogger(__name__)

You can also use the exc_info and extra={'stack': True} arguments on your log methods. This will store the appropriate information and allow Sentry to render it based on that information:

# If you're actually catching an exception, use `exc_info=True`
logger.error('There was an error, with a stack trace!', exc_info=True)

# If you don't have an exception, but still want to capture a
# stack trace, use the `stack` arg
logger.error('There was an error, with a stack trace!', extra={
    'stack': True,
})

While we don’t recommend this, you can also enable implicit stack capturing for all messages:

client = Client(..., auto_log_stacks=True)
handler = SentryHandler(client)

logger.error('There was an error, with a stack trace!')

Passing tags and user context is also available through extra:

logger.error('There was an error, with user context and tags'), extra={
    'user': {'email': 'test@test.com'},
    'tags': {'database': '1.0'},
})

You may also pass additional information to be stored as meta information with the event. As long as the key name is not reserved and not private (_foo) it will be displayed on the Sentry dashboard. To do this, pass it as data within your extra clause:

logger.error('There was some crazy error', exc_info=True, extra={
    # Optionally you can pass additional arguments to specify request info
    'culprit': 'my.view.name',
    'fingerprint': [...],

    'data': {
        # You may specify any values here and Sentry will log and output them
        'username': request.user.username,
    }
})

Sentry will intelligently group messages if you use proper string formatting. For example, the following messages would be seen as the same message within Sentry:

logger.error('There was some %s error', 'crazy')
logger.error('There was some %s error', 'fun')
logger.error('There was some %s error', 1)

Exclusions

You can also configure some logging exclusions during setup. These loggers will not propagate their logs to the Sentry handler:

from raven.conf import setup_logging

setup_logging(handler, exclude=("logger1", "logger2", ...))

Pylons

Pylons is a framework for Python.

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

WSGI Middleware

A Pylons-specific middleware exists to enable easy configuration from settings:

from raven.contrib.pylons import Sentry

application = Sentry(application, config)

Configuration is handled via the sentry namespace:

[sentry]
dsn=___DSN___
include_paths=my.package,my.other.package,
exclude_paths=my.package.crud

Logger setup

Add the following lines to your project’s .ini file to setup SentryHandler:

[loggers]
keys = root, sentry

[handlers]
keys = console, sentry

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console, sentry

[logger_sentry]
level = WARN
handlers = console
qualname = sentry.errors
propagate = 0

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[handler_sentry]
class = raven.handlers.logging.SentryHandler
args = ('SENTRY_DSN',)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

Pyramid

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

PasteDeploy Filter

A filter factory for PasteDeploy exists to allow easily inserting Raven into a WSGI pipeline:

[pipeline:main]
pipeline =
 raven
 tm
 MyApp

[filter:raven]
use = egg:raven#raven
dsn = ___DSN___
include_paths = my.package, my.other.package
exclude_paths = my.package.crud

In the [filter:raven] section, you must specify the entry-point for raven with the use = key. All other raven client parameters can be included in this section as well.

See the Pyramid PasteDeploy Configuration Documentation for more information.

Logger setup

Add the following lines to your project’s .ini file to setup SentryHandler:

[loggers]
keys = root, sentry

[handlers]
keys = console, sentry

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console, sentry

[logger_sentry]
level = WARN
handlers = console
qualname = sentry.errors
propagate = 0

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[handler_sentry]
class = raven.handlers.logging.SentryHandler
args = ('___DSN___',)
level = WARNING
formatter = generic

[formatter_generic]
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

Instead of defining the DSN in the .ini file you can also use the environment variable SENTRY_DSN which overwrites the setting in this file. Because of a syntax check you cannot remove the args setting completely, as workaround you can define an empty list of arguments args = ().

RQ

Starting with RQ version 0.3.1, support for Sentry has been built in.

Usage

RQ natively supports binding with Sentry by passing your SENTRY_DSN through rqworker:

$ rqworker --sentry-dsn="___DSN___"

Extended Setup

If you want to pass additional information, such as release, you’ll need to bind your own instance of the Sentry Client:

from raven import Client
from raven.transport.http import HTTPTransport
from rq.contrib.sentry import register_sentry

client = Client('___DSN___', transport=HTTPTransport)
register_sentry(client, worker)

Please see rq‘s documentation for more information: http://python-rq.org/patterns/sentry/

Tornado

Tornado is an async web framework for Python.

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

The first thing you’ll need to do is to initialize sentry client under your application

import tornado.web
from raven.contrib.tornado import AsyncSentryClient

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

application = tornado.web.Application([
    (r"/", MainHandler),
])
application.sentry_client = AsyncSentryClient(
    '___DSN___'
)

Usage

Once the sentry client is attached to the application, request handlers can automatically capture uncaught exceptions by inheriting the SentryMixin class.

import tornado.web
from raven.contrib.tornado import SentryMixin

class UncaughtExceptionExampleHandler(
        SentryMixin, tornado.web.RequestHandler):
    def get(self):
        1/0

You can also send events manually using the shortcuts defined in SentryMixin. The shortcuts can be used for both asynchronous and synchronous usage.

Asynchronous

import tornado.web
import tornado.gen
from raven.contrib.tornado import SentryMixin

class AsyncMessageHandler(SentryMixin, tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        self.write("You requested the main page")
        yield tornado.gen.Task(
            self.captureMessage, "Request for main page served"
        )
        self.finish()

class AsyncExceptionHandler(SentryMixin, tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        try:
            raise ValueError()
        except Exception as e:
            response = yield tornado.gen.Task(
                self.captureException, exc_info=True
            )
        self.finish()

Synchronous

import tornado.web
from raven.contrib.tornado import SentryMixin

class AsyncExampleHandler(SentryMixin, tornado.web.RequestHandler):
    def get(self):
        self.write("You requested the main page")
        self.captureMessage("Request for main page served")

WSGI Middleware

Raven includes a simple to use WSGI middleware.

from raven import Client
from raven.middleware import Sentry

application = Sentry(
    application,
    Client('___DSN___')
)

ZConfig logging configuration

ZConfig provides a configuration mechanism for the Python logging module.

To learn more, see:

http://zconfig.readthedocs.io/en/latest/using-logging.html

To use with sentry, use the sentry handler tag:

<logger>
  level INFO
  <logfile>
   path ${buildout:directory}/var/{:_buildout_section_name_}.log
   level INFO
  </logfile>

  %import raven.contrib.zconfig
  <sentry>
    dsn ___DSN___
    level ERROR
  </sentry>
</logger>

This configuration retains normal logging to a logfile, but adds Sentry logging for ERRORs.

All options of raven.base.Client are supported.

ZeroRPC

ZeroRPC is a light-weight, reliable and language-agnostic library for distributed communication between server-side processes.

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

Setup

The ZeroRPC integration comes as middleware for ZeroRPC. The middleware can be configured like the original Raven client (using keyword arguments) and registered into ZeroRPC’s context manager:

import zerorpc

from raven.contrib.zerorpc import SentryMiddleware

sentry = SentryMiddleware(dsn='___DSN___')
zerorpc.Context.get_instance().register_middleware(sentry)

By default, the middleware will hide internal frames from ZeroRPC when it submits exceptions to Sentry. This behavior can be disabled by passing the hide_zerorpc_frames parameter to the middleware:

sentry = SentryMiddleware(hide_zerorpc_frames=False, dsn='___DSN___')

Compatibility

  • ZeroRPC-Python < 0.4.0 is compatible with Raven <= 3.1.0;
  • ZeroRPC-Python >= 0.4.0 requires Raven > 3.1.0.

Zope/Plone

Installation

If you haven’t already, start by downloading Raven. The easiest way is with pip:

pip install raven --upgrade

zope.conf

Zope has extensible logging configuration options. A basic instance (not ZEO client) setup for logging looks like this:

<eventlog>
  level INFO
  <logfile>
   path ${buildout:directory}/var/{:_buildout_section_name_}.log
   level INFO
  </logfile>

  %import raven.contrib.zope
  <sentry>
    dsn ___DSN___
    level ERROR
  </sentry>
</eventlog>

This configuration retains normal logging to a logfile, but adds Sentry logging for ERRORs.

All options of raven.base.Client are supported.

Use a buildout recipe instead of editing zope.conf directly. To add the equivalent instance configuration, you would do this:

[instance]
recipe = plone.recipe.zope2instance
...
event-log-custom =
 %import raven.contrib.zope
 <logfile>
 path ${buildout:directory}/var/instance.log
 level INFO
 </logfile>
 <sentry>
 dsn ___DSN___
 level ERROR
 </sentry>

To add the equivalent ZEO client configuration, you would do this:

[instance]
recipe = plone.recipe.zope2instance
...
event-log-custom =
 %import raven.contrib.zope
 <logfile>
 path ${buildout:var-dir}/${:_buildout_section_name_}/event.log
 level INFO
 </logfile>
 <sentry>
 dsn ___DSN___
 level ERROR
 </sentry>