Legacy Python client for Sentry error monitoring service with framework integration and exception tracking capabilities.
—
Raven's breadcrumb system provides automatic and manual tracking of user actions and application state leading up to errors, creating a timeline of events that helps with debugging and understanding error context.
Core breadcrumb storage and management with size limits and processing.
from raven.breadcrumbs import BreadcrumbBuffer
class BreadcrumbBuffer:
def __init__(self, limit=100, message_max_length=1024):
"""
Initialize breadcrumb buffer with configurable limits.
Parameters:
- limit (int): Maximum number of breadcrumbs to store
- message_max_length (int): Maximum length of breadcrumb messages
"""
def record(self, timestamp=None, level=None, message=None, category=None,
data=None, type=None, processor=None):
"""
Record a breadcrumb.
Parameters:
- timestamp (datetime): Breadcrumb timestamp (defaults to now)
- level (str): Breadcrumb level ('debug', 'info', 'warning', 'error', 'critical')
- message (str): Breadcrumb message
- category (str): Breadcrumb category
- data (dict): Additional breadcrumb data
- type (str): Breadcrumb type
- processor (callable): Custom breadcrumb processor
"""
def clear(self):
"""Clear all breadcrumbs from buffer."""
def get_buffer(self):
"""
Get processed breadcrumbs for event inclusion.
Returns:
list: List of processed breadcrumb dictionaries
"""
def format(self, result):
"""
Format breadcrumb data, applying length limits.
Parameters:
- result (dict): Raw breadcrumb data
Returns:
dict: Formatted breadcrumb data
"""Prevent duplicate consecutive breadcrumbs.
from raven.breadcrumbs import event_payload_considered_equal
def event_payload_considered_equal(a, b):
"""
Check if two breadcrumb payloads are considered equal for deduplication.
Parameters:
- a (dict): First breadcrumb payload
- b (dict): Second breadcrumb payload
Returns:
bool: True if payloads are considered equal
"""Module-level functions for recording breadcrumbs across all active clients.
from raven.breadcrumbs import record, record_breadcrumb
def record(**kwargs):
"""
Record breadcrumb for all active clients.
Parameters:
- message (str): Breadcrumb message
- timestamp (datetime): Breadcrumb timestamp
- level (str): Breadcrumb level
- category (str): Breadcrumb category
- data (dict): Additional breadcrumb data
- type (str): Breadcrumb type
- processor (callable): Custom breadcrumb processor
"""
def record_breadcrumb(type, **kwargs):
"""
Legacy breadcrumb recording function.
Parameters:
- type (str): Breadcrumb type
- **kwargs: Breadcrumb data
"""Functions for enabling automatic breadcrumb collection from various sources.
from raven.breadcrumbs import (
install_logging_hook, ignore_logger, register_logging_handler, hook_libraries
)
def install_logging_hook():
"""Install logging breadcrumb hook for automatic log capture."""
def ignore_logger(name_or_logger, allow_level=None):
"""
Ignore logger for breadcrumb collection.
Parameters:
- name_or_logger (str|Logger): Logger name or instance to ignore
- allow_level (int): Optional minimum level to still capture
"""
def register_logging_handler(callback):
"""
Register custom logging handler for breadcrumbs.
Parameters:
- callback (callable): Handler function for log records
"""
def hook_libraries(libraries):
"""
Hook libraries for automatic breadcrumb collection.
Parameters:
- libraries (list): List of library names to hook
"""Client methods for breadcrumb management and recording.
# From Client class
def captureBreadcrumb(self, message=None, timestamp=None, level=None,
category=None, data=None, type=None, processor=None):
"""
Record breadcrumb for this client.
Parameters:
- message (str): Breadcrumb message
- timestamp (datetime): Breadcrumb timestamp
- level (str): Breadcrumb level
- category (str): Breadcrumb category
- data (dict): Additional breadcrumb data
- type (str): Breadcrumb type
- processor (callable): Custom breadcrumb processor
"""from raven import Client
client = Client('https://your-dsn@sentry.io/project-id')
def process_user_order():
# Record user action
client.captureBreadcrumb(
message='User started checkout process',
category='ui.click',
level='info',
data={'button_id': 'checkout-btn', 'cart_items': 3}
)
# Record API call
client.captureBreadcrumb(
message='Calling payment API',
category='http',
level='info',
data={'url': '/api/payments', 'method': 'POST'}
)
try:
payment_result = process_payment()
# Record successful operation
client.captureBreadcrumb(
message='Payment processed successfully',
category='payment',
level='info',
data={'transaction_id': payment_result.id}
)
except PaymentError as e:
# Record failure details
client.captureBreadcrumb(
message='Payment processing failed',
category='payment',
level='error',
data={'error_code': e.code, 'error_message': str(e)}
)
# Exception will include all breadcrumbs
client.captureException()
raisefrom raven import Client
from raven.breadcrumbs import install_logging_hook, ignore_logger
import logging
client = Client('https://your-dsn@sentry.io/project-id')
# Enable automatic logging breadcrumbs
install_logging_hook()
# Ignore noisy loggers
ignore_logger('urllib3')
ignore_logger('requests.packages.urllib3')
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def user_workflow():
logger.info('User login started')
try:
authenticate_user()
logger.info('User authenticated successfully')
load_user_data()
logger.info('User data loaded')
process_request()
logger.info('Request processed')
except AuthenticationError:
logger.error('Authentication failed')
client.captureException() # Includes log breadcrumbs
except Exception:
logger.exception('Unexpected error in user workflow')
client.captureException() # Includes log breadcrumbsfrom flask import Flask, request
from raven.contrib.flask import Sentry
app = Flask(__name__)
sentry = Sentry(app)
@app.before_request
def before_request():
# Record request start
sentry.client.captureBreadcrumb(
message=f'{request.method} {request.path}',
category='http.request',
level='info',
data={
'method': request.method,
'url': request.url,
'headers': dict(request.headers),
'query_string': request.query_string.decode()
}
)
@app.after_request
def after_request(response):
# Record response
sentry.client.captureBreadcrumb(
message=f'Response {response.status_code}',
category='http.response',
level='info' if response.status_code < 400 else 'warning',
data={
'status_code': response.status_code,
'content_length': response.content_length
}
)
return response
@app.route('/api/users/<int:user_id>')
def get_user(user_id):
# Record business logic steps
sentry.client.captureBreadcrumb(
message=f'Loading user {user_id}',
category='db.query',
level='info',
data={'user_id': user_id}
)
try:
user = User.query.get(user_id)
if not user:
sentry.client.captureBreadcrumb(
message='User not found',
category='business.logic',
level='warning',
data={'user_id': user_id}
)
return {'error': 'User not found'}, 404
return user.to_dict()
except DatabaseError:
# Exception includes all request breadcrumbs
sentry.captureException()
return {'error': 'Database error'}, 500from raven import Client
import json
def sanitize_breadcrumb_data(data):
"""Remove sensitive data from breadcrumb data."""
if not isinstance(data, dict):
return data
sanitized = {}
for key, value in data.items():
if key.lower() in ('password', 'token', 'secret', 'key'):
sanitized[key] = '[FILTERED]'
elif isinstance(value, dict):
sanitized[key] = sanitize_breadcrumb_data(value)
else:
sanitized[key] = value
return sanitized
client = Client('https://your-dsn@sentry.io/project-id')
def api_call_breadcrumb(url, method, payload=None, response=None):
"""Record API call with sanitized data."""
breadcrumb_data = {
'url': url,
'method': method
}
if payload:
breadcrumb_data['payload'] = sanitize_breadcrumb_data(payload)
if response:
breadcrumb_data['response'] = {
'status': response.get('status'),
'size': len(str(response)) if response else 0
}
client.captureBreadcrumb(
message=f'{method} {url}',
category='api.call',
level='info',
data=breadcrumb_data,
processor=sanitize_breadcrumb_data
)
# Usage
api_call_breadcrumb(
'/api/auth/login',
'POST',
payload={'username': 'john', 'password': 'secret123'},
response={'status': 200, 'token': 'jwt_token_here'}
)from raven import Client
import time
client = Client('https://your-dsn@sentry.io/project-id')
class DatabaseLogger:
def __init__(self, client):
self.client = client
def log_query(self, query, params=None, duration=None):
# Sanitize query parameters
safe_params = self._sanitize_params(params) if params else None
self.client.captureBreadcrumb(
message=f'Database query: {query[:50]}...' if len(query) > 50 else query,
category='db.sql',
level='info',
data={
'query': query,
'params': safe_params,
'duration_ms': duration * 1000 if duration else None
}
)
def _sanitize_params(self, params):
if isinstance(params, (list, tuple)):
return [self._sanitize_value(p) for p in params]
elif isinstance(params, dict):
return {k: self._sanitize_value(v) for k, v in params.items()}
return params
def _sanitize_value(self, value):
if isinstance(value, str) and len(value) > 100:
return value[:97] + '...'
return value
db_logger = DatabaseLogger(client)
def get_user_orders(user_id):
start_time = time.time()
query = "SELECT * FROM orders WHERE user_id = %s ORDER BY created_at DESC"
try:
cursor.execute(query, (user_id,))
results = cursor.fetchall()
duration = time.time() - start_time
db_logger.log_query(query, (user_id,), duration)
return results
except DatabaseError:
duration = time.time() - start_time
db_logger.log_query(query, (user_id,), duration)
client.captureException() # Includes query breadcrumb
raisefrom raven import Client
from raven.breadcrumbs import BreadcrumbBuffer
class OptimizedBreadcrumbBuffer(BreadcrumbBuffer):
def __init__(self, max_buffer_size=100, max_data_size=1024):
super().__init__(max_buffer_size)
self.max_data_size = max_data_size
def record(self, **kwargs):
# Limit data size to prevent memory issues
if 'data' in kwargs and kwargs['data']:
kwargs['data'] = self._truncate_data(kwargs['data'])
# Skip duplicate consecutive breadcrumbs
if self._is_duplicate(kwargs):
return
super().record(**kwargs)
def _truncate_data(self, data):
if not isinstance(data, dict):
return data
truncated = {}
total_size = 0
for key, value in data.items():
value_str = str(value)
if total_size + len(value_str) > self.max_data_size:
truncated[key] = value_str[:self.max_data_size - total_size - 3] + '...'
break
truncated[key] = value
total_size += len(value_str)
return truncated
def _is_duplicate(self, new_breadcrumb):
if not self.buffer:
return False
last_breadcrumb = self.buffer[-1]
return (
last_breadcrumb.get('message') == new_breadcrumb.get('message') and
last_breadcrumb.get('category') == new_breadcrumb.get('category')
)
# Use optimized buffer
client = Client('https://your-dsn@sentry.io/project-id')
client.context.breadcrumbs = OptimizedBreadcrumbBuffer(max_buffer_size=50)from raven.breadcrumbs import record
# Record breadcrumbs globally (affects all active clients)
def track_user_action(action, details=None):
record(
message=f'User action: {action}',
category='user.action',
level='info',
data=details or {}
)
def track_system_event(event, level='info', details=None):
record(
message=f'System event: {event}',
category='system',
level=level,
data=details or {}
)
# Usage throughout application
track_user_action('login', {'username': 'john_doe'})
track_user_action('view_product', {'product_id': 123})
track_system_event('cache_miss', 'warning', {'key': 'user_123'})
track_system_event('background_job_completed', 'info', {'job_id': 'abc123'})Install with Tessl CLI
npx tessl i tessl/pypi-raven