Legacy Python client for Sentry error monitoring service with framework integration and exception tracking capabilities.
—
Raven provides native Python logging integration, automatically capturing log records as Sentry events with configurable filtering, formatting, and context inclusion.
Python logging handler that sends log records to Sentry as events.
from raven.handlers.logging import SentryHandler
class SentryHandler(logging.Handler):
def __init__(self, client=None, dsn=None, level=logging.NOTSET,
client_cls=None, tags=None, extra=None, **kwargs):
"""
Logging handler for Sentry integration.
Parameters:
- client (Client): Existing Sentry client instance
- dsn (str): Sentry DSN for new client creation
- level (int): Minimum logging level
- client_cls (type): Custom client class
- tags (dict): Default tags for all log events
- extra (dict): Default extra data for all log events
"""
def emit(self, record):
"""
Process log record and send to Sentry.
Parameters:
- record (LogRecord): Python logging record
"""
def can_record(self, record):
"""
Determine if record should be processed.
Parameters:
- record (LogRecord): Python logging record
Returns:
bool: True if record should be sent to Sentry
"""Integration with the Logbook logging library.
from raven.handlers.logbook import SentryHandler as LogbookSentryHandler
class SentryHandler(logbook.Handler):
def __init__(self, client=None, dsn=None, level=logbook.NOTSET, **kwargs):
"""
Logbook handler for Sentry integration.
Parameters:
- client (Client): Existing Sentry client instance
- dsn (str): Sentry DSN for new client creation
- level (int): Minimum logging level
"""
def emit(self, record):
"""Process Logbook record and send to Sentry."""Utility function for configuring logging to pipe to Sentry.
from raven.conf import setup_logging, EXCLUDE_LOGGER_DEFAULTS
def setup_logging(handler, exclude=EXCLUDE_LOGGER_DEFAULTS):
"""
Configure logging to pipe to Sentry.
Parameters:
- handler (Handler): Sentry logging handler instance
- exclude (tuple): Logger names to exclude from Sentry
Returns:
bool: True if logging was successfully configured
"""
# Default excluded loggers
EXCLUDE_LOGGER_DEFAULTS = (
'raven',
'gunicorn',
'south',
'sentry.errors',
'django.request',
'dill',
)import logging
from raven import Client
from raven.handlers.logging import SentryHandler
from raven.conf import setup_logging
# Create client and handler
client = Client('https://your-dsn@sentry.io/project-id')
handler = SentryHandler(client)
handler.setLevel(logging.ERROR)
# Setup logging
setup_logging(handler)
# Use logging normally
logger = logging.getLogger(__name__)
logger.info('This will not be sent to Sentry')
logger.error('This error will be sent to Sentry')
logger.exception('This exception will be sent with stack trace')import logging
from raven.handlers.logging import SentryHandler
# Handler with custom tags and extra data
handler = SentryHandler(
dsn='https://your-dsn@sentry.io/project-id',
level=logging.WARNING,
tags={'component': 'auth', 'environment': 'prod'},
extra={'server': 'web-01', 'version': '1.2.3'}
)
# Add to specific logger
logger = logging.getLogger('myapp.auth')
logger.addHandler(handler)
logger.setLevel(logging.WARNING)
# Log with additional context
logger.warning('Login attempt failed', extra={
'user_id': 123,
'ip_address': '192.168.1.1',
'user_agent': 'Mozilla/5.0...'
})import logging
from raven.handlers.logging import SentryHandler
class FilteredSentryHandler(SentryHandler):
def can_record(self, record):
# Skip sensitive operations
if hasattr(record, 'funcName') and 'password' in record.funcName:
return False
# Only send errors from specific modules
if record.levelno >= logging.ERROR:
return record.name.startswith('myapp.')
return super().can_record(record)
handler = FilteredSentryHandler('https://your-dsn@sentry.io/project-id')import logging.config
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
'sentry': {
'class': 'raven.handlers.logging.SentryHandler',
'dsn': 'https://your-dsn@sentry.io/project-id',
'level': 'ERROR',
'tags': {'environment': 'production'},
},
},
'loggers': {
'myapp': {
'handlers': ['console', 'sentry'],
'level': 'INFO',
'propagate': False,
},
'django': {
'handlers': ['console'],
'level': 'INFO',
'propagate': False,
},
},
'root': {
'handlers': ['console', 'sentry'],
'level': 'WARNING',
},
}
logging.config.dictConfig(LOGGING_CONFIG)import logbook
from raven.handlers.logbook import SentryHandler
# Setup Logbook with Sentry
handler = SentryHandler('https://your-dsn@sentry.io/project-id')
with handler:
logger = logbook.Logger(__name__)
logger.info('This is just info')
logger.error('This error goes to Sentry')
try:
1/0
except ZeroDivisionError:
logger.exception('Division by zero error')import logging
from raven import Client
from raven.handlers.logging import SentryHandler
client = Client('https://your-dsn@sentry.io/project-id')
handler = SentryHandler(client)
logger = logging.getLogger(__name__)
logger.addHandler(handler)
logger.setLevel(logging.ERROR)
def process_user_request(user_id, request_data):
# Set context for all events in this request
client.user_context({'id': user_id})
client.tags_context({'operation': 'user_request'})
try:
result = complex_operation(request_data)
logger.info('Request processed successfully')
return result
except Exception as e:
# This will include the user context
logger.exception('Request processing failed')
raiseimport logging
from raven.handlers.logging import SentryHandler
class ThrottledSentryHandler(SentryHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._error_counts = {}
self._max_errors_per_minute = 10
def can_record(self, record):
if not super().can_record(record):
return False
# Throttling logic to prevent spam
import time
now = time.time()
minute = int(now // 60)
key = f"{record.name}:{record.levelno}"
if key not in self._error_counts:
self._error_counts[key] = {}
current_count = self._error_counts[key].get(minute, 0)
if current_count >= self._max_errors_per_minute:
return False
self._error_counts[key][minute] = current_count + 1
# Clean old entries
for k in list(self._error_counts.keys()):
self._error_counts[k] = {
m: c for m, c in self._error_counts[k].items()
if m >= minute - 5
}
return TrueInstall with Tessl CLI
npx tessl i tessl/pypi-raven